+ 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:
+ // do nothing, we just want to test for process existence
+ 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 occured 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
+ // 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(_T("PostMessage(WM_QUIT)"));
+ }
+ }
+ else // it was an error then
+ {
+ wxLogLastError(_T("EnumWindows"));
+
+ ok = FALSE;
+ }
+ }
+ else // no windows for this PID
+ {
+ if ( krc )
+ {
+ *krc = wxKILL_ERROR;
+ }
+
+ ok = FALSE;
+ }
+ }
+ }
+
+ // the return code
+ DWORD rc;
+
+ if ( ok )
+ {
+ // as we wait for a short time, we can use just WaitForSingleObject()
+ // and not MsgWaitForMultipleObjects()
+ switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) )
+ {
+ case WAIT_OBJECT_0:
+ // process terminated
+ if ( !::GetExitCodeProcess(hProcess, &rc) )
+ {
+ wxLogLastError(_T("GetExitCodeProcess"));
+ }
+ break;
+
+ default:
+ wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
+ // fall through
+
+ case WAIT_FAILED:
+ wxLogLastError(_T("WaitForSingleObject"));
+ // fall through
+
+ case WAIT_TIMEOUT:
+ if ( krc )
+ {
+ *krc = wxKILL_ERROR;
+ }
+
+ rc = STILL_ACTIVE;
+ break;
+ }
+ }
+ else // !ok
+ {
+ // just to suppress the warnings about uninitialized variable
+ rc = 0;
+ }
+
+ ::CloseHandle(hProcess);
+
+ // the return code is the same as from Unix kill(): 0 if killed
+ // successfully or -1 on error
+ if ( sig == wxSIGNONE )
+ {
+ if ( ok && rc == STILL_ACTIVE )
+ {
+ // there is such process => success
+ return 0;
+ }
+ }
+ else // not SIGNONE
+ {
+ if ( ok && rc != STILL_ACTIVE )
+ {
+ // killed => success
+ return 0;
+ }
+ }
+#else // Win15
+ wxFAIL_MSG( _T("not implemented") );
+#endif // Win32/Win16
+
+ // error
+ return -1;
+}
+
+// Execute a program in an Interactive Shell
+bool wxShell(const wxString& command)
+{
+ wxChar *shell = wxGetenv(wxT("COMSPEC"));
+ if ( !shell )
+ shell = wxT("\\COMMAND.COM");
+
+ wxString cmd;
+ if ( !command )
+ {
+ // just the shell
+ cmd = shell;
+ }
+ else
+ {
+ // pass the command to execute to the command processor
+ cmd.Printf(wxT("%s /c %s"), shell, command.c_str());
+ }
+
+ return wxExecute(cmd, TRUE /* sync */) != 0;