1
/*******************************************************************************
2
* Copyright (c) 2002, 2007 QNX Software Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* QNX Software Systems - initial API and implementation
13
* This is a part of JNI implementation of spawner
14
*******************************************************************************/
21
extern void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
24
static HWND consoleHWND;
27
/////////////////////////////////////////////////////////////////////////////////////
28
// Check if window is a console of process with pid
30
// hwnd - window handler
32
// Return : TRUE if yes
33
/////////////////////////////////////////////////////////////////////////////////////
35
find_child_console (HWND hwnd, LPARAM arg)
41
thread_id = GetWindowThreadProcessId (hwnd, &process_id);
42
if (process_id == pid)
44
wchar_t window_class[32];
46
GetClassName (hwnd, window_class, sizeof (window_class));
47
if (wcscmp (window_class, L"ConsoleWindowClass") == 0)
58
/////////////////////////////////////////////////////////////////////////////////////
59
// Function implements interrupt process (Ctrl-C emulation)
62
// Return : 0 if OK or error code
63
/////////////////////////////////////////////////////////////////////////////////////
64
int interruptProcess(int pid)
75
_stprintf(buffer, _T("Try to interrupt process %i\n"), pid);
76
OutputDebugStringW(buffer);
79
EnumWindows (find_child_console, (LPARAM) pid);
81
if(NULL != consoleHWND) // Yes, we found out it
83
// We are going to switch focus to console,
84
// send Ctrl-C and then restore focus
85
BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
86
/* Fake Ctrl-C for SIGINT, and Ctrl-Break for SIGQUIT. */
88
BYTE vk_break_code = VK_CANCEL;
89
BYTE c_scan_code = (BYTE) MapVirtualKey (vk_c_code, 0);
90
BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
91
HWND foreground_window;
94
foreground_window = GetForegroundWindow ();
95
if (foreground_window)
97
/* NT 5.0, and apparently also Windows 98, will not allow
98
a Window to be set to foreground directly without the
99
user's involvement. The workaround is to attach
100
ourselves to the thread that owns the foreground
101
window, since that is the only thread that can set the
102
foreground window. */
103
DWORD foreground_thread, child_thread;
105
GetWindowThreadProcessId (foreground_window, NULL);
106
if (foreground_thread == GetCurrentThreadId ()
107
|| !AttachThreadInput (GetCurrentThreadId (),
108
foreground_thread, TRUE))
109
foreground_thread = 0;
111
child_thread = GetWindowThreadProcessId (consoleHWND, NULL);
112
if (child_thread == GetCurrentThreadId ()
113
|| !AttachThreadInput (GetCurrentThreadId (),
117
/* Set the foreground window to the child. */
118
if (SetForegroundWindow (consoleHWND))
120
if(0 != break_scan_code) {
121
/* Generate keystrokes as if user had typed Ctrl-Break */
122
keybd_event (VK_CONTROL, control_scan_code, 0, 0);
123
keybd_event (vk_break_code, break_scan_code, KEYEVENTF_EXTENDEDKEY, 0);
124
keybd_event (vk_break_code, break_scan_code,
125
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
126
keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
129
/* Sleep for a bit to give time for respond */
132
SetForegroundWindow (foreground_window);
134
/* Detach from the foreground and child threads now that
135
the foreground switching is over. */
136
if (foreground_thread)
137
AttachThreadInput (GetCurrentThreadId (),
138
foreground_thread, FALSE);
140
AttachThreadInput (GetCurrentThreadId (),
141
child_thread, FALSE);
143
_stprintf(buffer, _T("Sent Ctrl-C & Ctrl-Break to process %i\n"), pid);
144
OutputDebugStringW(buffer);
150
_stprintf(buffer, _T("Cannot find console for process %i\n"), pid);
151
OutputDebugStringW(buffer);