Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 5224412a063832cd4eeea59056fc43bbd09c489d (plain) (tree)



























                                                                            

                                                                               





































                                                                                            
















                                                                                                                    

































































































                                                                                                                        






                                                                         
                                                                    
                           
 
                                                                             















                                                                                                        

                                                                                                        
























                                                      



                  

                                                                                
/* Copyright, 2002, QNX Software Systems Ltd.  All Rights Reserved

 * This source code has been published by QNX Software Systems
 * Ltd. (QSSL). However, any use, reproduction, modification, distribution
 * or transfer of this software, or any software which includes or is based
 * upon any of this code, is only permitted if expressly authorized by a
 * written license agreement from QSSL. Contact the QNX Developer's Network
 * or contact QSSL's legal department for more information.
 *
 *
 *  starter.c
 *
 *  This is a small utility for windows spawner
 */


//#define UNICODE
//#define _UNICODE

#define STRICT
#include <Windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>

// #define DEBUG_MONITOR
#define MAX_CMD_LINE_LENGTH (1024)

int copyTo(char * target, const char * source, int cpyLength, int availSpace);

///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI HandlerRoutine(  DWORD dwCtrlType)   //  control signal type
{
	BOOL ret = TRUE;
	switch(dwCtrlType)
	{
		case CTRL_C_EVENT:
			break;
		case CTRL_BREAK_EVENT:
			break;
		case CTRL_CLOSE_EVENT:
			ret = FALSE;
			break;
		case CTRL_LOGOFF_EVENT:
			ret = FALSE;
			break;
		case CTRL_SHUTDOWN_EVENT:
			ret = FALSE;
			break;
		default:
			break;
	}
	return ret;
}



extern "C" int  _tmain(int argc, TCHAR* argv[]) {

   // Make sure that we've been passed the right number of arguments
   if (argc < 5) {
      _tprintf(__TEXT("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"), 
         argv[0]);
      return(0);
   }

   // Construct the full command line
   TCHAR szCmdLine[MAX_CMD_LINE_LENGTH] = { 0 };
   int nPos = 0;

   for(int i = 4; i < argc; ++i) 
		{
		int nCpyLen;
		if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], _tcslen(argv[i]), MAX_CMD_LINE_LENGTH - nPos)))
			{
#ifdef DEBUG_MONITOR
			OutputDebugString("Not enough space to build command line\n");
#endif
			return 0;
			}
		nPos += nCpyLen;
		szCmdLine[nPos] = _T(' ');
		++nPos;
		}   
   szCmdLine[nPos] = _T('\0');

   STARTUPINFO         si = { sizeof(si) };
   PROCESS_INFORMATION pi = { 0 };
   DWORD dwExitCode = 0;
#ifdef DEBUG_MONITOR
   int currentPID = GetCurrentProcessId();
   char buffer[MAX_CMD_LINE_LENGTH];
#endif
   
   BOOL exitProc = FALSE;
   HANDLE waitEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[2]);
   HANDLE h[3];
   h[0] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[1]);
   h[2] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[3]); // This is a terminate event
   SetConsoleCtrlHandler(HandlerRoutine, TRUE);

#ifdef DEBUG_MONITOR
	sprintf(buffer, "starter start command: %s\n", szCmdLine);
	OutputDebugString(buffer);
#endif

//   OutputDebugString(szCmdLine);
   // Spawn the other processes as part of this Process Group
   BOOL f = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 
      0, NULL, NULL, &si, &pi);

   if (f) 
   {
   	  SetEvent(waitEvent); // Means thar process has been spawned
      CloseHandle(pi.hThread);
      h[1] = pi.hProcess;

	  while(!exitProc)
		  {
		  // Wait for the spawned-process to die or for the event
		  // indicating that the processes should be forcibly killed.
		  switch (WaitForMultipleObjects(3, h, FALSE, INFINITE)) 
			{
			 case WAIT_OBJECT_0 + 0:  // Send Ctrl-C
#ifdef DEBUG_MONITOR
				sprintf(buffer, "starter (PID %i) received CTRL-C event\n", currentPID);
				OutputDebugString(buffer);
#endif
   				GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
				SetEvent(waitEvent);
				break;

			 case WAIT_OBJECT_0 + 1:  // App terminated normally
				// Make it's exit code our exit code
#ifdef DEBUG_MONITOR
				sprintf(buffer, "starter: launched process has been terminated(PID %i)\n", currentPID);
				OutputDebugString(buffer);
#endif
				GetExitCodeProcess(pi.hProcess, &dwExitCode);
				exitProc = TRUE;
				break;
			 case WAIT_OBJECT_0 + 2:  // Kill
#ifdef DEBUG_MONITOR
				sprintf(buffer, "starter received KILL event (PID %i)\n", currentPID);
				OutputDebugString(buffer);
#endif
   				GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
				TerminateProcess(h[1], 0);
				exitProc = TRUE;
				break;
			 default:
			 // Unexpected code
				LPTSTR lpMsgBuf;

				FormatMessage( 
					FORMAT_MESSAGE_ALLOCATE_BUFFER | 
					FORMAT_MESSAGE_FROM_SYSTEM | 
					FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL,
					GetLastError(),
					MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
					(LPTSTR) &lpMsgBuf,
					0,
					NULL 
				);
				OutputDebugString(lpMsgBuf);
				// Free the buffer.
				LocalFree( lpMsgBuf );
				exitProc = TRUE;
				break;
			 }
			
		  }
      CloseHandle(pi.hProcess);
	}

   CloseHandle(waitEvent);
   CloseHandle(h[0]);
   CloseHandle(h[2]);
 
   return(dwExitCode);
}

// Return number of bytes in target or -1 in case of error
int copyTo(LPTSTR target, LPCTSTR source, int cpyLength, int availSpace)
{
	BOOL bSlash = FALSE;
	int i = 0, j = 0;
	int totCpyLength = cpyLength;
	BOOL bQoutedTerm = FALSE;
	if(availSpace <= cpyLength)  // = to reserve space for '\0'
		return -1;

	if((_T('\"') == *source) && (_T('\"') == *(source + cpyLength - 1)))
		bQoutedTerm = TRUE; // Already quoted
	else
	if(_tcschr(source, _T(' ')) == NULL)
		bQoutedTerm = TRUE; // No reason to quotate term becase it doesn't have embedded spaces
	else
		{
		*target = _T('\"');
		++j;
		}


	for(; i < cpyLength; ++i, ++j) 
		{
		if(source[i] == _T('\\'))
			bSlash = TRUE;
		else
		// Escape double quote only if quotation mark is not start or end character
		if((source[i] == _T('\"')) && (!bQoutedTerm || ((i != 0) && (i != (cpyLength - 1)))) ) 
			{
			if(!bSlash)
				{
				if(j == availSpace)
					return -1;
				target[j] = _T('\\');
				++j;
				}
			bSlash = FALSE;
			}
		else
			bSlash = FALSE;

		if(j == availSpace)
			return -1;
		target[j] = source[i];
		}

	if(!bQoutedTerm)
		{
		if(j == availSpace)
			return -1;
		target[j] = _T('\"');
		++j;
		}
	return j;
}



//////////////////////////////// End of File //////////////////////////////////

Back to the top