diff options
author | Brad King <brad.king@kitware.com> | 2003-06-10 19:46:31 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2003-06-10 19:46:31 (GMT) |
commit | 96ccaed54dcf97e802c2e958185cf321dfa7f1e4 (patch) | |
tree | fdeb2ff895a72232e4f290f39126faad8ab7b68f /Source/kwsys/ProcessFwd9x.c | |
parent | 89cf5d538c53af72c6f212d86e74011277233067 (diff) | |
download | CMake-96ccaed54dcf97e802c2e958185cf321dfa7f1e4.zip CMake-96ccaed54dcf97e802c2e958185cf321dfa7f1e4.tar.gz CMake-96ccaed54dcf97e802c2e958185cf321dfa7f1e4.tar.bz2 |
ENH: Added Process execution implementation.
Diffstat (limited to 'Source/kwsys/ProcessFwd9x.c')
-rw-r--r-- | Source/kwsys/ProcessFwd9x.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/Source/kwsys/ProcessFwd9x.c b/Source/kwsys/ProcessFwd9x.c new file mode 100644 index 0000000..a6a428a --- /dev/null +++ b/Source/kwsys/ProcessFwd9x.c @@ -0,0 +1,145 @@ +/*========================================================================= + +Program: KWSys - Kitware System Library +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. +See http://www.cmake.org/HTML/Copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +/* + On Windows9x platforms, this executable is spawned between a parent + process and the child it is invoking to work around a bug. See the + Win32 implementation file for details. +*/ + +#include <windows.h> +#include <stdio.h> + +int main() +{ + /* Process startup information for the real child. */ + STARTUPINFO si; + PROCESS_INFORMATION pi; + + /* The result of waiting for the child to exit. */ + DWORD waitResult; + + /* The child's process return code. */ + DWORD retVal; + + /* The command line used to invoke this process. */ + LPSTR commandLine = GetCommandLine(); + + /* Pointer that will be advanced to the beginning of the command + line of the real child process. */ + LPSTR cmdLine = commandLine; + + /* Handle to the error reporting pipe provided by the parent. This + is parsed off the command line. */ + HANDLE errorPipe = 0; + + /* Handle to the event the parent uses to tell us to kill the child. + This is parsed off the command line. */ + HANDLE killEvent = 0; + + /* An array of the handles on which we wait when the child is + running. */ + HANDLE waitHandles[2] = {0, 0}; + + /* Move the pointer past the name of this executable. */ + if(*cmdLine == '"') + { + ++cmdLine; + while(*cmdLine && *cmdLine != '"') { ++cmdLine; } + if(*cmdLine) { ++cmdLine; } + } + else + { + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + } + + /* Parse the error pipe handle. */ + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + sscanf(cmdLine, "%d", &errorPipe); + + /* Parse the kill event handle. */ + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + sscanf(cmdLine, "%d", &killEvent); + + /* Skip to the beginning of the command line of the real child. */ + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + + /* Create the subprocess. */ + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + si.wShowWindow = SW_SHOWDEFAULT; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + if(!CreateProcess(0, cmdLine, 0, 0, TRUE, 0, 0, 0, &si, &pi)) + { + /* Error creating the process. Report the error to the parent + process through the special error reporting pipe. */ + LPVOID lpMsgBuf; + DWORD n; + 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 + ); + WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0); + LocalFree( lpMsgBuf ); + return 1; + } + CloseHandle(pi.hThread); + + /* Wait for subprocess to exit or for kill event from parent. */ + waitHandles[0] = killEvent; + waitHandles[1] = pi.hProcess; + waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); + + /* Check what happened. */ + if(waitResult == WAIT_OBJECT_0) + { + /* We were asked to kill the child. */ + TerminateProcess(pi.hProcess, -1); + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + return 1; + } + else if(GetExitCodeProcess(pi.hProcess, &retVal)) + { + /* The child exited and we could get the return code. */ + CloseHandle(pi.hProcess); + return retVal; + } + else + { + /* The child exited and we could not get the return code. Report + the problem to the parent process. */ + DWORD n; + const char* msg = "Failed to get process return code."; + WriteFile(errorPipe, msg, strlen(msg)+1, &n, 0); + CloseHandle(pi.hProcess); + return -1; + } +} |