+ if (flags & wxKILL_CHILDREN)
+ wxKillAllChildren(pid, sig, krc);
+
+ // get the process handle to operate on
+ DWORD dwAccess = PROCESS_QUERY_INFORMATION | SYNCHRONIZE;
+ if ( sig == wxSIGKILL )
+ dwAccess |= PROCESS_TERMINATE;
+
+ HANDLE hProcess = ::OpenProcess(dwAccess, FALSE, (DWORD)pid);
+ if ( hProcess == NULL )
+ {
+ if ( krc )
+ {
+ // recognize wxKILL_ACCESS_DENIED as special because this doesn't
+ // mean that the process doesn't exist and this is important for
+ // wxProcess::Exists()
+ *krc = ::GetLastError() == ERROR_ACCESS_DENIED
+ ? wxKILL_ACCESS_DENIED
+ : wxKILL_NO_PROCESS;
+ }
+
+ return -1;
+ }
+
+ wxON_BLOCK_EXIT1(::CloseHandle, hProcess);
+
+ // Default timeout for waiting for the process termination after killing
+ // it. It should be long enough to allow the process to terminate even on a
+ // busy system but short enough to avoid blocking the main thread for too
+ // long.
+ DWORD waitTimeout = 500; // ms
+
+ bool ok = true;
+ switch ( sig )
+ {
+ case wxSIGKILL:
+ // kill the process forcefully returning -1 as error code
+ if ( !::TerminateProcess(hProcess, (UINT)-1) )
+ {
+ wxLogSysError(_("Failed to kill process %d"), pid);
+
+ if ( krc )
+ {
+ // this is not supposed to happen if we could open the
+ // process
+ *krc = wxKILL_ERROR;
+ }
+
+ ok = false;
+ }
+ break;
+
+ case wxSIGNONE:
+ // Opening the process handle may succeed for a process even if it
+ // doesn't run any more (typically because open handles to it still
+ // exist elsewhere, possibly in this process itself if we're
+ // killing a child process) so we still need check if it hasn't
+ // terminated yet but, unlike when killing it, we don't need to
+ // wait for any time at all.
+ waitTimeout = 0;
+ break;
+
+ default:
+ // any other signal means "terminate"
+ {
+ wxFindByPidParams params;
+ params.pid = (DWORD)pid;
+
+ // EnumWindows() has nice semantics: it returns 0 if it found
+ // something or if an error occurred and non zero if it
+ // enumerated all the window
+ if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)¶ms) )
+ {
+ // did we find any window?
+ if ( params.hwnd )
+ {
+ // tell the app to close
+ //
+ // NB: this is the harshest way, the app won't have an
+ // opportunity to save any files, for example, but
+ // this is probably what we want here. If not we
+ // can also use SendMesageTimeout(WM_CLOSE)
+ if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) )
+ {
+ wxLogLastError(wxT("PostMessage(WM_QUIT)"));
+ }
+ }
+ else // it was an error then
+ {
+ wxLogLastError(wxT("EnumWindows"));
+
+ ok = false;
+ }
+ }
+ else // no windows for this PID
+ {
+ if ( krc )
+ *krc = wxKILL_ERROR;
+
+ ok = false;
+ }
+ }
+ }
+
+ // the return code
+ if ( ok )
+ {
+ // as we wait for a short time, we can use just WaitForSingleObject()
+ // and not MsgWaitForMultipleObjects()
+ switch ( ::WaitForSingleObject(hProcess, waitTimeout) )
+ {
+ case WAIT_OBJECT_0:
+ // Process terminated: normally this indicates that we
+ // successfully killed it but when testing for the process
+ // existence, this means failure.
+ if ( sig == wxSIGNONE )
+ {
+ if ( krc )
+ *krc = wxKILL_NO_PROCESS;
+
+ ok = false;
+ }
+ break;
+
+ default:
+ wxFAIL_MSG( wxT("unexpected WaitForSingleObject() return") );
+ // fall through
+
+ case WAIT_FAILED:
+ wxLogLastError(wxT("WaitForSingleObject"));
+ // fall through
+
+ case WAIT_TIMEOUT:
+ // Process didn't terminate: normally this is a failure but not
+ // when we're just testing for its existence.
+ if ( sig != wxSIGNONE )
+ {
+ if ( krc )
+ *krc = wxKILL_ERROR;