ProcessFwd9x.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*=========================================================================
  2. Program: KWSys - Kitware System Library
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. /*
  14. On Windows9x platforms, this executable is spawned between a parent
  15. process and the child it is invoking to work around a bug. See the
  16. Win32 implementation file for details.
  17. */
  18. #ifdef _MSC_VER
  19. #pragma warning (push, 1)
  20. #endif
  21. #include <windows.h>
  22. #include <stdio.h>
  23. int main()
  24. {
  25. /* Process startup information for the real child. */
  26. STARTUPINFO si;
  27. PROCESS_INFORMATION pi;
  28. /* The result of waiting for the child to exit. */
  29. DWORD waitResult;
  30. /* The child's process return code. */
  31. DWORD retVal;
  32. /* The command line used to invoke this process. */
  33. LPSTR commandLine = GetCommandLine();
  34. /* Pointer that will be advanced to the beginning of the command
  35. line of the real child process. */
  36. LPSTR cmdLine = commandLine;
  37. /* Handle to the error reporting pipe provided by the parent. This
  38. is parsed off the command line. */
  39. HANDLE errorPipe = 0;
  40. /* Handle to the event the parent uses to tell us to kill the child.
  41. This is parsed off the command line. */
  42. HANDLE killEvent = 0;
  43. /* Flag for whether to hide window of child process. */
  44. int hideWindow = 0;
  45. /* An array of the handles on which we wait when the child is
  46. running. */
  47. HANDLE waitHandles[2] = {0, 0};
  48. /* Move the pointer past the name of this executable. */
  49. if(*cmdLine == '"')
  50. {
  51. ++cmdLine;
  52. while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
  53. if(*cmdLine) { ++cmdLine; }
  54. }
  55. else
  56. {
  57. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  58. }
  59. /* Parse the error pipe handle. */
  60. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  61. sscanf(cmdLine, "%p", &errorPipe);
  62. /* Parse the kill event handle. */
  63. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  64. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  65. sscanf(cmdLine, "%p", &killEvent);
  66. /* Parse the hide window flag. */
  67. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  68. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  69. sscanf(cmdLine, "%d", &hideWindow);
  70. /* Skip to the beginning of the command line of the real child. */
  71. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  72. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  73. /* Create the subprocess. */
  74. ZeroMemory(&si, sizeof(si));
  75. ZeroMemory(&pi, sizeof(pi));
  76. si.cb = sizeof(si);
  77. si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  78. si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT;
  79. si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  80. si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  81. si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  82. if(!CreateProcess(0, cmdLine, 0, 0, TRUE, 0, 0, 0, &si, &pi))
  83. {
  84. /* Error creating the process. Report the error to the parent
  85. process through the special error reporting pipe. */
  86. LPVOID lpMsgBuf;
  87. DWORD n;
  88. FormatMessage(
  89. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  90. FORMAT_MESSAGE_FROM_SYSTEM |
  91. FORMAT_MESSAGE_IGNORE_INSERTS,
  92. NULL,
  93. GetLastError(),
  94. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  95. (LPTSTR) &lpMsgBuf,
  96. 0,
  97. NULL
  98. );
  99. WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
  100. LocalFree( lpMsgBuf );
  101. return 1;
  102. }
  103. CloseHandle(pi.hThread);
  104. /* Wait for subprocess to exit or for kill event from parent. */
  105. waitHandles[0] = killEvent;
  106. waitHandles[1] = pi.hProcess;
  107. waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
  108. /* Check what happened. */
  109. if(waitResult == WAIT_OBJECT_0)
  110. {
  111. /* We were asked to kill the child. */
  112. TerminateProcess(pi.hProcess, 255);
  113. WaitForSingleObject(pi.hProcess, INFINITE);
  114. CloseHandle(pi.hProcess);
  115. return 1;
  116. }
  117. else if(GetExitCodeProcess(pi.hProcess, &retVal))
  118. {
  119. /* The child exited and we could get the return code. */
  120. CloseHandle(pi.hProcess);
  121. return retVal;
  122. }
  123. else
  124. {
  125. /* The child exited and we could not get the return code. Report
  126. the problem to the parent process. */
  127. DWORD n;
  128. const char* msg = "Failed to get process return code.";
  129. WriteFile(errorPipe, msg, strlen(msg)+1, &n, 0);
  130. CloseHandle(pi.hProcess);
  131. return -1;
  132. }
  133. }