ProcessFwd9x.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. void ReportLastError(HANDLE errorPipe);
  24. int main()
  25. {
  26. /* Process startup information for the real child. */
  27. STARTUPINFO si;
  28. PROCESS_INFORMATION pi;
  29. /* The result of waiting for the child to exit. */
  30. DWORD waitResult;
  31. /* The child's process return code. */
  32. DWORD retVal;
  33. /* The command line used to invoke this process. */
  34. LPSTR commandLine = GetCommandLine();
  35. /* Pointer that will be advanced to the beginning of the command
  36. line of the real child process. */
  37. LPSTR cmdLine = commandLine;
  38. /* Handle to the error reporting pipe provided by the parent. This
  39. is parsed off the command line. */
  40. HANDLE errorPipe = 0;
  41. HANDLE errorPipeOrig = 0;
  42. /* Handle to the event the parent uses to tell us to resume the child.
  43. This is parsed off the command line. */
  44. HANDLE resumeEvent = 0;
  45. /* Handle to the event the parent uses to tell us to kill the child.
  46. This is parsed off the command line. */
  47. HANDLE killEvent = 0;
  48. /* Flag for whether to hide window of child process. */
  49. int hideWindow = 0;
  50. /* An array of the handles on which we wait when the child is
  51. running. */
  52. HANDLE waitHandles[2] = {0, 0};
  53. /* Move the pointer past the name of this executable. */
  54. if(*cmdLine == '"')
  55. {
  56. ++cmdLine;
  57. while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
  58. if(*cmdLine) { ++cmdLine; }
  59. }
  60. else
  61. {
  62. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  63. }
  64. /* Parse the error pipe handle. */
  65. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  66. sscanf(cmdLine, "%p", &errorPipeOrig);
  67. /* Parse the resume event handle. */
  68. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  69. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  70. sscanf(cmdLine, "%p", &resumeEvent);
  71. /* Parse the kill event handle. */
  72. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  73. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  74. sscanf(cmdLine, "%p", &killEvent);
  75. /* Parse the hide window flag. */
  76. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  77. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  78. sscanf(cmdLine, "%d", &hideWindow);
  79. /* Skip to the beginning of the command line of the real child. */
  80. while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
  81. while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
  82. /* Create a non-inherited copy of the error pipe. We do not want
  83. the child to get it. */
  84. if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig,
  85. GetCurrentProcess(), &errorPipe,
  86. 0, FALSE, DUPLICATE_SAME_ACCESS))
  87. {
  88. /* Have a non-inherited duplicate. Close the inherited one. */
  89. CloseHandle(errorPipeOrig);
  90. }
  91. else
  92. {
  93. /* Could not duplicate handle. Report the error. */
  94. ReportLastError(errorPipeOrig);
  95. return 1;
  96. }
  97. /* Create the subprocess. */
  98. ZeroMemory(&si, sizeof(si));
  99. ZeroMemory(&pi, sizeof(pi));
  100. si.cb = sizeof(si);
  101. si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  102. si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT;
  103. si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  104. si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  105. si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  106. if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi))
  107. {
  108. /* Process created successfully. Close the error reporting pipe
  109. to notify the parent of success. */
  110. CloseHandle(errorPipe);
  111. }
  112. else
  113. {
  114. /* Error creating the process. Report the error to the parent
  115. process through the special error reporting pipe. */
  116. ReportLastError(errorPipe);
  117. return 1;
  118. }
  119. /* Wait for resume or kill event from parent. */
  120. waitHandles[0] = killEvent;
  121. waitHandles[1] = resumeEvent;
  122. waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
  123. /* Check what happened. */
  124. if(waitResult == WAIT_OBJECT_0)
  125. {
  126. /* We were asked to kill the child. */
  127. TerminateProcess(pi.hProcess, 255);
  128. WaitForSingleObject(pi.hProcess, INFINITE);
  129. CloseHandle(pi.hProcess);
  130. CloseHandle(pi.hThread);
  131. return 1;
  132. }
  133. else
  134. {
  135. /* We were asked to resume the child. */
  136. ResumeThread(pi.hThread);
  137. CloseHandle(pi.hThread);
  138. }
  139. /* Wait for subprocess to exit or for kill event from parent. */
  140. waitHandles[0] = killEvent;
  141. waitHandles[1] = pi.hProcess;
  142. waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
  143. /* Check what happened. */
  144. if(waitResult == WAIT_OBJECT_0)
  145. {
  146. /* We were asked to kill the child. */
  147. TerminateProcess(pi.hProcess, 255);
  148. WaitForSingleObject(pi.hProcess, INFINITE);
  149. CloseHandle(pi.hProcess);
  150. return 1;
  151. }
  152. else
  153. {
  154. /* The child exited. Get the return code. */
  155. GetExitCodeProcess(pi.hProcess, &retVal);
  156. CloseHandle(pi.hProcess);
  157. return retVal;
  158. }
  159. }
  160. void ReportLastError(HANDLE errorPipe)
  161. {
  162. LPVOID lpMsgBuf;
  163. DWORD n;
  164. FormatMessage(
  165. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  166. FORMAT_MESSAGE_FROM_SYSTEM |
  167. FORMAT_MESSAGE_IGNORE_INSERTS,
  168. NULL,
  169. GetLastError(),
  170. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  171. (LPTSTR) &lpMsgBuf,
  172. 0,
  173. NULL
  174. );
  175. WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
  176. LocalFree( lpMsgBuf );
  177. }