/******************************************************************************
 Code derived from the following at http://www.microsoft.com/msj/0698/win320698.aspx
 Module name: SmallApp.cpp
 Written by:  Jeffrey Richter
 Purpose:     Spawn helper that kills everything in its Process Group.
******************************************************************************/
 
//#define UNICODE
//#define _UNICODE
 
#define STRICT
#include <Windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
 
///////////////////////////////////////////////////////////////////////////////
 
/******************************************************************************
    Sends the Ctrl-C to all processes spawned in this process' own console.
    (Sends Ctrl-C to the two connected httpd.exe instances launched together)
*******************************************************************************/

extern "C" int  _tmain(int argc, TCHAR* argv[]) 
{
  
  // Make sure that we've been passed the right number of arguments
  if (argc < 3) {
       _tprintf(
		__TEXT("Usage: %s (InheritableEventHandle) (CommandLineToSpawn)\n"), 
		argv[0]);
       return(-1);
  }
  
  // Construct the full command line
  TCHAR szCmdLine[MAX_PATH] = { 0 };
  for (int x = 2; x < argc; x++) {
    _tcscat(szCmdLine, argv[x]); 
    _tcscat(szCmdLine, __TEXT(" ")); 
  }
  
  STARTUPINFO         si = { sizeof(si) };
  PROCESS_INFORMATION pi = { 0 };
  DWORD dwExitCode = 0;
  
  HANDLE h[2];
  h[0] = (HANDLE) _ttoi(argv[1]);  // The inherited event handle
  
  // 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) {
    CloseHandle(pi.hThread);
    h[1] = pi.hProcess;
    
    // Wait for the spawned-process to die or for the event
    // indicating that the processes should be forcibly killed.
    switch (WaitForMultipleObjects(2, h, FALSE, INFINITE)) {
    case WAIT_OBJECT_0 + 0:  // Force termination
      GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
      WaitForSingleObject(pi.hProcess, INFINITE);
      break;
      
    case WAIT_OBJECT_0 + 1:  // App terminated normally
      // Make its exit code our exit code
      GetExitCodeProcess(pi.hProcess, &dwExitCode);
      break;
    }
    CloseHandle(pi.hProcess);
  }
  CloseHandle(h[0]);   // Close the inherited event handle
  return(dwExitCode);
}
 
//////////////////////////////// End of File //////////////////////////////////


