1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 10:46:02 +02:00

This isn't a binary.

This commit is contained in:
Doug Schaefer 2007-09-05 14:17:42 +00:00
parent 1c52fecbad
commit 2d980092d9

View file

@ -1,481 +1,481 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2002, 2007 QNX Software Systems and others. * Copyright (c) 2002, 2007 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* QNX Software Systems - initial API and implementation * QNX Software Systems - initial API and implementation
* Wind River Systems, Inc. * Wind River Systems, Inc.
* *
* starter.cpp * starter.cpp
* *
* This is a small utility for windows spawner * This is a small utility for windows spawner
*******************************************************************************/ *******************************************************************************/
#define STRICT #define STRICT
#define _WIN32_WINNT 0x0500 #define _WIN32_WINNT 0x0500
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
#include <tchar.h> #include <tchar.h>
#include <stdio.h> #include <stdio.h>
#include <psapi.h> #include <psapi.h>
//#define DEBUG_MONITOR //#define DEBUG_MONITOR
#define MAX_CMD_LINE_LENGTH (2049) #define MAX_CMD_LINE_LENGTH (2049)
#define PIPE_NAME_LENGTH 100 #define PIPE_NAME_LENGTH 100
int copyTo(wchar_t * target, const wchar_t * source, int cpyLength, int copyTo(wchar_t * target, const wchar_t * source, int cpyLength,
int availSpace); int availSpace);
void DisplayErrorMessage(); void DisplayErrorMessage();
//BOOL KillProcessEx(DWORD dwProcessId); // Handle of the process //BOOL KillProcessEx(DWORD dwProcessId); // Handle of the process
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI HandlerRoutine( DWORD dwCtrlType) // control signal type BOOL WINAPI HandlerRoutine( DWORD dwCtrlType) // control signal type
{ {
BOOL ret = TRUE; BOOL ret = TRUE;
switch(dwCtrlType) switch(dwCtrlType)
{ {
case CTRL_C_EVENT: case CTRL_C_EVENT:
break; break;
case CTRL_BREAK_EVENT: case CTRL_BREAK_EVENT:
break; break;
case CTRL_CLOSE_EVENT: case CTRL_CLOSE_EVENT:
ret = FALSE; ret = FALSE;
break; break;
case CTRL_LOGOFF_EVENT: case CTRL_LOGOFF_EVENT:
ret = FALSE; ret = FALSE;
break; break;
case CTRL_SHUTDOWN_EVENT: case CTRL_SHUTDOWN_EVENT:
ret = FALSE; ret = FALSE;
break; break;
default: default:
break; break;
} }
return ret; return ret;
} }
// The default here means we haven't checked yet // The default here means we haven't checked yet
// i.e. cygwin is true but the bin dir hasn't been captured // i.e. cygwin is true but the bin dir hasn't been captured
wchar_t * cygwinBin = NULL; wchar_t * cygwinBin = NULL;
bool _isCygwin = true; bool _isCygwin = true;
bool isCygwin(HANDLE process) { bool isCygwin(HANDLE process) {
// Have we checked before? // Have we checked before?
if (cygwinBin != NULL || !_isCygwin) if (cygwinBin != NULL || !_isCygwin)
return _isCygwin; return _isCygwin;
// See if this process loaded cygwin, need a different SIGINT for them // See if this process loaded cygwin, need a different SIGINT for them
HMODULE mods[1024]; HMODULE mods[1024];
DWORD needed; DWORD needed;
if (EnumProcessModules(process, mods, sizeof(mods), &needed)) { if (EnumProcessModules(process, mods, sizeof(mods), &needed)) {
int i; int i;
needed /= sizeof(HMODULE); needed /= sizeof(HMODULE);
for (i = 0; i < needed; ++i ) { for (i = 0; i < needed; ++i ) {
wchar_t modName[MAX_PATH]; wchar_t modName[MAX_PATH];
if (GetModuleFileNameEx(process, mods[i], modName, MAX_PATH)) { if (GetModuleFileNameEx(process, mods[i], modName, MAX_PATH)) {
wchar_t * p = wcsrchr(modName, L'\\'); wchar_t * p = wcsrchr(modName, L'\\');
if (p) { if (p) {
*p = 0; // Null terminate there for future reference *p = 0; // Null terminate there for future reference
if (!wcscmp(++p, L"cygwin1.dll")) { if (!wcscmp(++p, L"cygwin1.dll")) {
_isCygwin = true; _isCygwin = true;
// Store away the bind dir // Store away the bind dir
cygwinBin = wcsdup(modName); cygwinBin = wcsdup(modName);
return _isCygwin; return _isCygwin;
} }
} }
} }
} }
} }
_isCygwin = false; _isCygwin = false;
return _isCygwin; return _isCygwin;
} }
bool runCygwinCommand(wchar_t * command) { bool runCygwinCommand(wchar_t * command) {
wchar_t cygcmd[1024]; wchar_t cygcmd[1024];
swprintf(cygcmd, L"%s\\%s", cygwinBin, command); swprintf(cygcmd, L"%s\\%s", cygwinBin, command);
STARTUPINFO si; STARTUPINFO si;
ZeroMemory(&si, sizeof(si)); ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si); si.cb = sizeof(si);
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&pi, sizeof(pi));
if (CreateProcess(NULL, cygcmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { if (CreateProcess(NULL, cygcmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE); WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
return true; return true;
} else if (CreateProcess(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { } else if (CreateProcess(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE); WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
return true; return true;
} }
return false; return false;
} }
void ensureSize(wchar_t** ptr, int* psize, int requiredLength) { void ensureSize(wchar_t** ptr, int* psize, int requiredLength) {
int size= *psize; int size= *psize;
if (requiredLength > size) { if (requiredLength > size) {
size= 2*size; size= 2*size;
if (size < requiredLength) { if (size < requiredLength) {
size= requiredLength; size= requiredLength;
} }
*ptr= (wchar_t *)realloc(*ptr, size * sizeof(wchar_t)); *ptr= (wchar_t *)realloc(*ptr, size * sizeof(wchar_t));
if (NULL == *ptr) { if (NULL == *ptr) {
*psize= 0; *psize= 0;
} else { } else {
*psize= size; *psize= size;
} }
} }
} }
int main() { int main() {
int argc; int argc;
wchar_t ** argv = CommandLineToArgvW(GetCommandLine(), &argc); wchar_t ** argv = CommandLineToArgvW(GetCommandLine(), &argc);
// Make sure that we've been passed the right number of arguments // Make sure that we've been passed the right number of arguments
if (argc < 7) { if (argc < 7) {
_tprintf(_T("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"), _tprintf(_T("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"),
argv[0]); argv[0]);
return(0); return(0);
} }
// Construct the full command line // Construct the full command line
int nCmdLineLength= MAX_CMD_LINE_LENGTH; int nCmdLineLength= MAX_CMD_LINE_LENGTH;
wchar_t * szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t)); wchar_t * szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t));
szCmdLine[0]= 0; szCmdLine[0]= 0;
int nPos = 0; int nPos = 0;
for(int i = 6; i < argc; ++i) for(int i = 6; i < argc; ++i)
{ {
int nCpyLen; int nCpyLen;
int len= wcslen(argv[i]); int len= wcslen(argv[i]);
int requiredSize= nPos+len+2; int requiredSize= nPos+len+2;
if (requiredSize > 32*1024) { if (requiredSize > 32*1024) {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Command line too long!\n")); OutputDebugStringW(_T("Command line too long!\n"));
#endif #endif
return 0; return 0;
} }
ensureSize(&szCmdLine, &nCmdLineLength, requiredSize); ensureSize(&szCmdLine, &nCmdLineLength, requiredSize);
if (NULL == szCmdLine) { if (NULL == szCmdLine) {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Not enough memory to build cmd line!\n")); OutputDebugStringW(_T("Not enough memory to build cmd line!\n"));
#endif #endif
return 0; return 0;
} }
if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], len, nCmdLineLength - nPos))) if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], len, nCmdLineLength - nPos)))
{ {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Not enough space to build command line\n")); OutputDebugStringW(_T("Not enough space to build command line\n"));
#endif #endif
return 0; return 0;
} }
nPos += nCpyLen; nPos += nCpyLen;
szCmdLine[nPos] = _T(' '); szCmdLine[nPos] = _T(' ');
++nPos; ++nPos;
} }
szCmdLine[nPos] = _T('\0'); szCmdLine[nPos] = _T('\0');
STARTUPINFOW si = {sizeof(si)}; STARTUPINFOW si = {sizeof(si)};
PROCESS_INFORMATION pi = {0}; PROCESS_INFORMATION pi = {0};
DWORD dwExitCode = 0; DWORD dwExitCode = 0;
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
int currentPID = GetCurrentProcessId(); int currentPID = GetCurrentProcessId();
wchar_t buffer[MAX_CMD_LINE_LENGTH]; wchar_t buffer[MAX_CMD_LINE_LENGTH];
#endif #endif
BOOL exitProc = FALSE; BOOL exitProc = FALSE;
HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]); HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]);
HANDLE h[3]; HANDLE h[3];
h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]); h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]);
h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // This is a terminate event h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // This is a terminate event
SetConsoleCtrlHandler(HandlerRoutine, TRUE); SetConsoleCtrlHandler(HandlerRoutine, TRUE);
int parentPid = wcstol(argv[1], NULL, 10); int parentPid = wcstol(argv[1], NULL, 10);
int nCounter = wcstol(argv[2], NULL, 10); int nCounter = wcstol(argv[2], NULL, 10);
wchar_t inPipeName[PIPE_NAME_LENGTH]; wchar_t inPipeName[PIPE_NAME_LENGTH];
wchar_t outPipeName[PIPE_NAME_LENGTH]; wchar_t outPipeName[PIPE_NAME_LENGTH];
wchar_t errPipeName[PIPE_NAME_LENGTH]; wchar_t errPipeName[PIPE_NAME_LENGTH];
swprintf(inPipeName, L"\\\\.\\pipe\\stdin%08i%010i", parentPid, nCounter); swprintf(inPipeName, L"\\\\.\\pipe\\stdin%08i%010i", parentPid, nCounter);
swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", parentPid, nCounter); swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", parentPid, nCounter);
swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", parentPid, nCounter); swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", parentPid, nCounter);
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName); swprintf(buffer, _T("Pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
HANDLE stdHandles[3]; HANDLE stdHandles[3];
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE; sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL; sa.lpSecurityDescriptor = NULL;
if((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateFileW(inPipeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, &sa))) || if((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateFileW(inPipeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, &sa))) ||
(INVALID_HANDLE_VALUE == (stdHandles[1] = CreateFileW(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) || (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateFileW(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) ||
(INVALID_HANDLE_VALUE == (stdHandles[2] = CreateFileW(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa)))) (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateFileW(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))))
{ {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Failed to open pipe %i, %i, %i: %i\n"), stdHandles[0], stdHandles[1], stdHandles[2], GetLastError()); swprintf(buffer, _T("Failed to open pipe %i, %i, %i: %i\n"), stdHandles[0], stdHandles[1], stdHandles[2], GetLastError());
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
CloseHandle(stdHandles[0]); CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]); CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]); CloseHandle(stdHandles[2]);
return -1;; return -1;;
} }
SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, TRUE);
SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, TRUE);
SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, TRUE);
if(!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) || if(!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) ||
!SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) || !SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) ||
!SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) { !SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Failed to reassign standard streams: %i\n"), GetLastError()); swprintf(buffer, _T("Failed to reassign standard streams: %i\n"), GetLastError());
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
CloseHandle(stdHandles[0]); CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]); CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]); CloseHandle(stdHandles[2]);
return -1;; return -1;;
} }
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
wchar_t * lpvEnv = GetEnvironmentStringsW(); wchar_t * lpvEnv = GetEnvironmentStringsW();
// If the returned pointer is NULL, exit. // If the returned pointer is NULL, exit.
if (lpvEnv == NULL) if (lpvEnv == NULL)
OutputDebugStringW(_T("Cannot Read Environment\n")); OutputDebugStringW(_T("Cannot Read Environment\n"));
else { else {
// Variable strings are separated by NULL byte, and the block is // Variable strings are separated by NULL byte, and the block is
// terminated by a NULL byte. // terminated by a NULL byte.
OutputDebugStringW(_T("Starter: Environment\n")); OutputDebugStringW(_T("Starter: Environment\n"));
for (wchar_t * lpszVariable = (wchar_t *) lpvEnv; *lpszVariable; lpszVariable+=wcslen(lpszVariable) + 1) { for (wchar_t * lpszVariable = (wchar_t *) lpvEnv; *lpszVariable; lpszVariable+=wcslen(lpszVariable) + 1) {
swprintf(buffer, _T("%s\n"), lpszVariable); swprintf(buffer, _T("%s\n"), lpszVariable);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
} }
FreeEnvironmentStringsW(lpvEnv); FreeEnvironmentStringsW(lpvEnv);
} }
#endif #endif
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Starting: %s\n"), szCmdLine); swprintf(buffer, _T("Starting: %s\n"), szCmdLine);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
// Create job object // Create job object
HANDLE hJob = CreateJobObject(NULL, NULL); HANDLE hJob = CreateJobObject(NULL, NULL);
// Spawn the other processes as part of this Process Group // Spawn the other processes as part of this Process Group
BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE, BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE,
0, NULL, NULL, &si, &pi); 0, NULL, NULL, &si, &pi);
// We don't need them any more // We don't need them any more
CloseHandle(stdHandles[0]); CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]); CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]); CloseHandle(stdHandles[2]);
if (f) { if (f) {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Process %i started\n"), pi.dwProcessId); swprintf(buffer, _T("Process %i started\n"), pi.dwProcessId);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
SetEvent(waitEvent); // Means thar process has been spawned SetEvent(waitEvent); // Means thar process has been spawned
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
h[1] = pi.hProcess; h[1] = pi.hProcess;
if(NULL != hJob) { if(NULL != hJob) {
if(!AssignProcessToJobObject(hJob, pi.hProcess)) { if(!AssignProcessToJobObject(hJob, pi.hProcess)) {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Cannot assign process %i to a job\n"), pi.dwProcessId); swprintf(buffer, _T("Cannot assign process %i to a job\n"), pi.dwProcessId);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
DisplayErrorMessage(); DisplayErrorMessage();
#endif #endif
} }
} }
while(!exitProc) while(!exitProc)
{ {
// Wait for the spawned-process to die or for the event // Wait for the spawned-process to die or for the event
// indicating that the processes should be forcibly killed. // indicating that the processes should be forcibly killed.
switch (WaitForMultipleObjects(3, h, FALSE, INFINITE)) switch (WaitForMultipleObjects(3, h, FALSE, INFINITE))
{ {
case WAIT_OBJECT_0 + 0: // Send Ctrl-C case WAIT_OBJECT_0 + 0: // Send Ctrl-C
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID); swprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
if (isCygwin(h[1])) { if (isCygwin(h[1])) {
// Need to issue a kill command // Need to issue a kill command
wchar_t kill[1024]; wchar_t kill[1024];
swprintf(kill, L"kill -SIGINT %d", pi.dwProcessId); swprintf(kill, L"kill -SIGINT %d", pi.dwProcessId);
if (!runCygwinCommand(kill)) { if (!runCygwinCommand(kill)) {
// fall back to console event // fall back to console event
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
} }
} else { } else {
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
} }
SetEvent(waitEvent); SetEvent(waitEvent);
break; break;
case WAIT_OBJECT_0 + 1: // App terminated normally case WAIT_OBJECT_0 + 1: // App terminated normally
// Make it's exit code our exit code // Make it's exit code our exit code
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("starter: launched process has been terminated(PID %i)\n"), swprintf(buffer, _T("starter: launched process has been terminated(PID %i)\n"),
pi.dwProcessId); pi.dwProcessId);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
GetExitCodeProcess(pi.hProcess, &dwExitCode); GetExitCodeProcess(pi.hProcess, &dwExitCode);
exitProc = TRUE; exitProc = TRUE;
break; break;
case WAIT_OBJECT_0 + 2: // Kill case WAIT_OBJECT_0 + 2: // Kill
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("starter received KILL event (PID %i)\n"), currentPID); swprintf(buffer, _T("starter received KILL event (PID %i)\n"), currentPID);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
#endif #endif
if (isCygwin(h[1])) { if (isCygwin(h[1])) {
// Need to issue a kill command // Need to issue a kill command
wchar_t kill[1024]; wchar_t kill[1024];
swprintf(kill, L"kill -SIGTERM %d", pi.dwProcessId); swprintf(kill, L"kill -SIGTERM %d", pi.dwProcessId);
if (!runCygwinCommand(kill)) { if (!runCygwinCommand(kill)) {
// fall back to console event // fall back to console event
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
} }
} else { } else {
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
} }
SetEvent(waitEvent); SetEvent(waitEvent);
if(NULL != hJob) { if(NULL != hJob) {
if(!TerminateJobObject(hJob, (DWORD)-1)) { if(!TerminateJobObject(hJob, (DWORD)-1)) {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Cannot terminate job\n")); OutputDebugStringW(_T("Cannot terminate job\n"));
DisplayErrorMessage(); DisplayErrorMessage();
#endif #endif
} }
} else } else
exitProc = TRUE; exitProc = TRUE;
break; break;
default: default:
// Unexpected code // Unexpected code
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
DisplayErrorMessage(); DisplayErrorMessage();
#endif #endif
exitProc = TRUE; exitProc = TRUE;
break; break;
} }
} }
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
} else { } else {
#ifdef DEBUG_MONITOR #ifdef DEBUG_MONITOR
swprintf(buffer, _T("Cannot start: %s\n"), szCmdLine); swprintf(buffer, _T("Cannot start: %s\n"), szCmdLine);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
DisplayErrorMessage(); DisplayErrorMessage();
#endif #endif
} }
if (NULL != szCmdLine) if (NULL != szCmdLine)
{ {
free(szCmdLine); free(szCmdLine);
} }
CloseHandle(waitEvent); CloseHandle(waitEvent);
CloseHandle(h[0]); CloseHandle(h[0]);
CloseHandle(h[1]); CloseHandle(h[1]);
CloseHandle(h[2]); CloseHandle(h[2]);
return(dwExitCode); return(dwExitCode);
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Use this utility program to process correctly quotation marks in the command line // Use this utility program to process correctly quotation marks in the command line
// Arguments: // Arguments:
// target - string to copy to // target - string to copy to
// source - string to copy from // source - string to copy from
// cpyLength - copy length // cpyLength - copy length
// availSpace - size of the target buffer // availSpace - size of the target buffer
// Return :number of bytes used in target, or -1 in case of error // Return :number of bytes used in target, or -1 in case of error
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
int copyTo(wchar_t * target, const wchar_t * source, int cpyLength, int copyTo(wchar_t * target, const wchar_t * source, int cpyLength,
int availSpace) { int availSpace) {
BOOL bSlash = FALSE; BOOL bSlash = FALSE;
int i = 0, j = 0; int i = 0, j = 0;
int totCpyLength = cpyLength; int totCpyLength = cpyLength;
#define QUOTATION_DO 0 #define QUOTATION_DO 0
#define QUOTATION_DONE 1 #define QUOTATION_DONE 1
#define QUOTATION_NONE 2 #define QUOTATION_NONE 2
int nQuotationMode = 0; int nQuotationMode = 0;
if (availSpace <= cpyLength) // = to reserve space for '\0' if (availSpace <= cpyLength) // = to reserve space for '\0'
return -1; return -1;
if ((_T('\"') == *source) && (_T('\"') == *(source + cpyLength - 1))) { if ((_T('\"') == *source) && (_T('\"') == *(source + cpyLength - 1))) {
// Already done // Already done
nQuotationMode = QUOTATION_DONE; nQuotationMode = QUOTATION_DONE;
} else if (wcschr(source, _T(' '))== NULL) { } else if (wcschr(source, _T(' '))== NULL) {
// No reason to quotate term becase it doesn't have embedded spaces // No reason to quotate term becase it doesn't have embedded spaces
nQuotationMode = QUOTATION_NONE; nQuotationMode = QUOTATION_NONE;
} else { } else {
// Needs to be quotated // Needs to be quotated
nQuotationMode = QUOTATION_DO; nQuotationMode = QUOTATION_DO;
*target = _T('\"'); *target = _T('\"');
++j; ++j;
} }
for (; i < cpyLength; ++i, ++j) { for (; i < cpyLength; ++i, ++j) {
if (source[i] == _T('\\')) if (source[i] == _T('\\'))
bSlash = TRUE; bSlash = TRUE;
else else
// Don't escape embracing quotation marks // Don't escape embracing quotation marks
if ((source[i] == _T('\"')) && !((nQuotationMode == QUOTATION_DONE) && ((i == 0) || (i == (cpyLength - 1))) )) { if ((source[i] == _T('\"')) && !((nQuotationMode == QUOTATION_DONE) && ((i == 0) || (i == (cpyLength - 1))) )) {
if (!bSlash) { if (!bSlash) {
if (j == availSpace) if (j == availSpace)
return -1; return -1;
target[j] = _T('\\'); target[j] = _T('\\');
++j; ++j;
} }
bSlash = FALSE; bSlash = FALSE;
} else } else
bSlash = FALSE; bSlash = FALSE;
if (j == availSpace) if (j == availSpace)
return -1; return -1;
target[j] = source[i]; target[j] = source[i];
} }
if (nQuotationMode == QUOTATION_DO) { if (nQuotationMode == QUOTATION_DO) {
if (j == availSpace) if (j == availSpace)
return -1; return -1;
target[j] = _T('\"'); target[j] = _T('\"');
++j; ++j;
} }
return j; return j;
} }
void DisplayErrorMessage() { void DisplayErrorMessage() {
wchar_t * lpMsgBuf; wchar_t * lpMsgBuf;
FormatMessageW( FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(wchar_t *) &lpMsgBuf, 0, NULL); (wchar_t *) &lpMsgBuf, 0, NULL);
OutputDebugStringW(lpMsgBuf); OutputDebugStringW(lpMsgBuf);
// Free the buffer. // Free the buffer.
LocalFree(lpMsgBuf); LocalFree(lpMsgBuf);
} }
//////////////////////////////// End of File ////////////////////////////////// //////////////////////////////// End of File //////////////////////////////////