| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 | 
							- /*=========================================================================
 
-   Program:   Insight Segmentation & Registration Toolkit
 
-   Module:    $RCSfile$
 
-   Language:  C++
 
-   Date:      $Date$
 
-   Version:   $Revision$
 
-   Copyright (c) 2002 Insight Consortium. All rights reserved.
 
-   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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.
 
- =========================================================================*/
 
- #include "cmWin32ProcessExecution.h"
 
- #include "cmSystemTools.h"   
 
- #include <malloc.h>
 
- #include <io.h>
 
- #include <fcntl.h>
 
- #include <stdio.h>
 
- #include <sys/stat.h>
 
- #include <windows.h>
 
- #if defined(__BORLANDC__)
 
- #  define STRICMP stricmp
 
- #  define TO_INTPTR(x) ((long)(x))
 
- #else // Visual studio
 
- #  if ( _MSC_VER >= 1300 )
 
- #    include <stddef.h>
 
- #    define TO_INTPTR(x) ((intptr_t)(x))
 
- #  else // Visual Studio 6
 
- #    define TO_INTPTR(x) ((long)(x))
 
- #  endif // Visual studio .NET
 
- #  define STRICMP _stricmp
 
- #endif // Borland
 
- #define POPEN_1 1
 
- #define POPEN_2 2
 
- #define POPEN_3 3
 
- #define POPEN_4 4
 
- #define cmMAX(x,y) (((x)<(y))?(y):(x))
 
- #define win32_error(x,y) std::cout << "Win32_Error(" << x << ", " << y << ")" << std::endl, false
 
- bool cmWin32ProcessExecution::StartProcess(
 
-   const char* cmd, const char* path, bool verbose)
 
- {
 
-   this->Initialize();
 
-   this->m_Verbose = verbose;
 
-   return this->PrivateOpen(cmd, path, _O_RDONLY | _O_TEXT, POPEN_3);
 
- }
 
- bool cmWin32ProcessExecution::Wait(int timeout)
 
- {
 
-   return this->PrivateClose(timeout);
 
- }
 
- #define PERROR(str) //::ErrorMessage(__LINE__, str)
 
- static void ErrorMessage(int line, char *str)  //display detailed error info
 
- {
 
-   DWORD lastmsg = GetLastError();
 
-   LPVOID msg;
 
-   FormatMessage(
 
-     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 
-     NULL,
 
-     lastmsg,
 
-     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
 
-     (LPTSTR) &msg,
 
-     0,
 
-     NULL
 
-   );
 
-   printf("%d - %s: %s (%d)\n",line,str,msg, lastmsg);
 
-   LocalFree(msg);
 
-   ::SetLastError(ERROR_SUCCESS);
 
- }
 
- /*
 
-  * Internal dictionary mapping popen* file pointers to process handles,
 
-  * for use when retrieving the process exit code.  See _PyPclose() below
 
-  * for more information on this dictionary's use.
 
-  */
 
- static void *_PyPopenProcs = NULL;
 
- static BOOL RealPopenCreateProcess(const char *cmdstring,
 
- 				   const char *path, 
 
- 				   const char *szConsoleSpawn,
 
- 				   HANDLE hStdin,
 
- 				   HANDLE hStdout,
 
- 				   HANDLE hStderr,
 
- 				   HANDLE *hProcess)
 
- {
 
-   PERROR("Start");
 
-   //std::cout << "Run: " << cmdstring << std::endl;
 
-   PERROR("Start");
 
-   PROCESS_INFORMATION piProcInfo;
 
-   PERROR("PROCESS_INFORMATION");
 
-   STARTUPINFO siStartInfo;
 
-   PERROR("STARTUPINFO");
 
-   char *s1,*s2, *s3 = " /c ";
 
-   int i;
 
-   int x;
 
-   if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) 
 
-     {
 
-     PERROR("GetEnvironmentVariable");
 
-     char *comshell;
 
-     s1 = (char *)_alloca(i);
 
-     if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
 
-       {
 
-       PERROR("GetEnvironmentVariable");
 
-       return x;
 
-       }
 
-     /* Explicitly check if we are using COMMAND.COM.  If we are
 
-      * then use the w9xpopen hack.
 
-      */
 
-     comshell = s1 + x;
 
-     while (comshell >= s1 && *comshell != '\\')
 
-       --comshell;
 
-     ++comshell;
 
-     if (GetVersion() < 0x80000000 &&
 
- 	STRICMP(comshell, "command.com") != 0) 
 
-       {
 
-       /* NT/2000 and not using command.com. */
 
-       x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1;
 
-       s2 = (char *)_alloca(x);
 
-       ZeroMemory(s2, x);
 
-       sprintf(s2, "%s%s%s", s1, s3, cmdstring);
 
-       //std::cout << "s1: " << s1 << " s2: " << s2 << " s3: " << s3 
 
-       //		<< std::endl;
 
-       }
 
-     else 
 
-       {
 
-       /*
 
-        * Oh gag, we're on Win9x or using COMMAND.COM. Use
 
-        * the workaround listed in KB: Q150956
 
-        */
 
-       char modulepath[_MAX_PATH];
 
-       struct stat statinfo;
 
-       GetModuleFileName(NULL, modulepath, sizeof(modulepath));
 
-       for (i = x = 0; modulepath[i]; i++)
 
- 	if (modulepath[i] == '\\')
 
- 	  x = i+1;
 
-       modulepath[x] = '\0';
 
-       /* Create the full-name to w9xpopen, so we can test it exists */
 
-       strncat(modulepath, 
 
- 	      szConsoleSpawn, 
 
- 	      (sizeof(modulepath)/sizeof(modulepath[0]))
 
- 	      -strlen(modulepath));
 
-       if (stat(modulepath, &statinfo) != 0) 
 
- 	{
 
- 				/* Eeek - file-not-found - possibly an embedding 
 
- 				   situation - see if we can locate it in sys.prefix 
 
- 				*/
 
- 	strncpy(modulepath, 
 
- 		".", 
 
- 		sizeof(modulepath)/sizeof(modulepath[0]));
 
- 	if (modulepath[strlen(modulepath)-1] != '\\')
 
- 	  strcat(modulepath, "\\");
 
- 	strncat(modulepath, 
 
- 		szConsoleSpawn, 
 
- 		(sizeof(modulepath)/sizeof(modulepath[0]))
 
- 		-strlen(modulepath));
 
- 	/* No where else to look - raise an easily identifiable
 
- 	   error, rather than leaving Windows to report
 
- 	   "file not found" - as the user is probably blissfully
 
- 	   unaware this shim EXE is used, and it will confuse them.
 
- 	   (well, it confused me for a while ;-)
 
- 	*/
 
- 	if (stat(modulepath, &statinfo) != 0) 
 
- 	  {
 
- 	  std::cout 
 
- 	    << "Can not locate '" << szConsoleSpawn 
 
- 	    << "' which is needed "
 
- 	    "for popen to work with your shell "
 
- 	    "or platform." << std::endl;
 
- 	  return FALSE;
 
- 	  }
 
- 	}
 
-       x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1 +
 
- 	(int)strlen(modulepath) + 
 
- 	(int)strlen(szConsoleSpawn) + 1;
 
-       s2 = (char *)_alloca(x);
 
-       ZeroMemory(s2, x);
 
-       sprintf(
 
- 	s2,
 
- 	"%s \"%s%s%s\"",
 
- 	modulepath,
 
- 	s1,
 
- 	s3,
 
- 	cmdstring);
 
-       }
 
-     }
 
-   /* Could be an else here to try cmd.exe / command.com in the path
 
-      Now we'll just error out.. */
 
-   else 
 
-     {
 
-     std::cout << "Cannot locate a COMSPEC environment variable to "
 
- 	      << "use as the shell" << std::endl;
 
-     return FALSE;
 
-     }
 
-   
 
-   ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
 
-   siStartInfo.cb = sizeof(STARTUPINFO);
 
-   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
 
-   siStartInfo.hStdInput = hStdin;
 
-   siStartInfo.hStdOutput = hStdout;
 
-   siStartInfo.hStdError = hStderr;
 
-   siStartInfo.wShowWindow = SW_HIDE;
 
-   if (CreateProcess(NULL,
 
- 		    s2,
 
- 		    NULL,
 
- 		    NULL,
 
- 		    TRUE,
 
- 		    CREATE_NEW_CONSOLE,
 
- 		    NULL,
 
- 		    path,
 
- 		    &siStartInfo,
 
- 		    &piProcInfo) ) 
 
-     {
 
-     PERROR("CreateProcess");
 
-     /* Close the handles now so anyone waiting is woken. */
 
-     CloseHandle(piProcInfo.hThread);
 
-     PERROR("Close Handle");
 
-     /* Return process handle */
 
-     *hProcess = piProcInfo.hProcess;
 
-     //std::cout << "Process created..." << std::endl;
 
-     return TRUE;
 
-     }
 
-   win32_error("CreateProcess", s2);
 
-   return FALSE;
 
- }
 
- /* The following code is based off of KB: Q190351 */
 
- bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring, 
 
- 					  const char* path,
 
- 					  int mode, 
 
- 					  int n)
 
- {
 
-   HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
 
-     hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
 
-     hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */
 
-   SECURITY_ATTRIBUTES saAttr;
 
-   BOOL fSuccess;
 
-   int fd1, fd2, fd3;
 
-   //FILE *f1, *f2, *f3;
 
-   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
 
-   saAttr.bInheritHandle = TRUE;
 
-   saAttr.lpSecurityDescriptor = NULL;
 
-   if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
 
-     {
 
-     return win32_error("CreatePipe", NULL);
 
-     }
 
-   PERROR("CreatePipe");
 
-     
 
-   /* Create new output read handle and the input write handle. Set
 
-    * the inheritance properties to FALSE. Otherwise, the child inherits
 
-    * the these handles; resulting in non-closeable handles to the pipes
 
-    * being created. */
 
-   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
 
- 			     GetCurrentProcess(), &hChildStdinWrDup, 0,
 
- 			     FALSE,
 
- 			     DUPLICATE_SAME_ACCESS);
 
-   if (!fSuccess)
 
-     return win32_error("DuplicateHandle", NULL);
 
-   PERROR("DuplicateHandle");
 
-   /* Close the inheritable version of ChildStdin
 
-      that we're using. */
 
-   CloseHandle(hChildStdinWr);
 
-   PERROR("CloseHandle");
 
-   if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
 
-     return win32_error("CreatePipe", NULL);
 
-   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
 
- 			     GetCurrentProcess(), &hChildStdoutRdDup, 0,
 
- 			     FALSE, DUPLICATE_SAME_ACCESS);
 
-   if (!fSuccess)
 
-     return win32_error("DuplicateHandle", NULL);
 
-   PERROR("DuplicateHandle");
 
-   /* Close the inheritable version of ChildStdout
 
-      that we're using. */
 
-   CloseHandle(hChildStdoutRd);
 
-   PERROR("CloseHandle");
 
-   if (n != POPEN_4) 
 
-     {
 
-     if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
 
-       return win32_error("CreatePipe", NULL);
 
-    PERROR("CreatePipe");
 
-    fSuccess = DuplicateHandle(GetCurrentProcess(),
 
- 			       hChildStderrRd,
 
- 			       GetCurrentProcess(),
 
- 			       &hChildStderrRdDup, 0,
 
- 			       FALSE, DUPLICATE_SAME_ACCESS);
 
-     if (!fSuccess)
 
-       return win32_error("DuplicateHandle", NULL);
 
-     PERROR("DuplicateHandle");
 
-     /* Close the inheritable version of ChildStdErr that we're using. */
 
-     CloseHandle(hChildStderrRd);
 
-     PERROR("CloseHandle");
 
-     }
 
- 	  
 
-   switch (n) 
 
-     {
 
-     case POPEN_1:
 
-       switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) 
 
- 	{
 
- 	case _O_WRONLY | _O_TEXT:
 
- 	  /* Case for writing to child Stdin in text mode. */
 
- 	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
 
- 	  //f1 = _fdopen(fd1, "w");
 
- 	  /* We don't care about these pipes anymore,
 
- 	     so close them. */
 
- 	  CloseHandle(hChildStdoutRdDup);
 
- 	  CloseHandle(hChildStderrRdDup);
 
-           PERROR("CloseHandle");
 
- 	  break;
 
- 	case _O_RDONLY | _O_TEXT:
 
- 	  /* Case for reading from child Stdout in text mode. */
 
- 	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
 
- 	  //f1 = _fdopen(fd1, "r");
 
- 	  /* We don't care about these pipes anymore,
 
- 	     so close them. */
 
- 	  CloseHandle(hChildStdinWrDup);
 
- 	  CloseHandle(hChildStderrRdDup);
 
-           PERROR("CloseHandle");
 
- 	  break;
 
- 	case _O_RDONLY | _O_BINARY:
 
- 	  /* Case for readinig from child Stdout in
 
- 	     binary mode. */
 
- 	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
 
- 	  //f1 = _fdopen(fd1, "rb");
 
- 	  /* We don't care about these pipes anymore,
 
- 	     so close them. */
 
- 	  CloseHandle(hChildStdinWrDup);
 
- 	  CloseHandle(hChildStderrRdDup);
 
-           PERROR("CloseHandle");
 
- 	  break;
 
- 	case _O_WRONLY | _O_BINARY:
 
- 	  /* Case for writing to child Stdin in binary mode. */
 
- 	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
 
- 	  //f1 = _fdopen(fd1, "wb");
 
- 	  /* We don't care about these pipes anymore,
 
- 	     so close them. */
 
- 	  CloseHandle(hChildStdoutRdDup);
 
- 	  CloseHandle(hChildStderrRdDup);
 
-           PERROR("CloseHandle");
 
- 	  break;
 
- 	}
 
-       break;
 
- 	
 
-     case POPEN_2:
 
-     case POPEN_4: 
 
-       if ( 1 ) 
 
- 	{
 
-         // Comment this out. Maybe we will need it in the future.
 
-         // file IO access to the process might be cool.
 
- 	//char *m1,  *m2;
 
- 	
 
- 	//if (mode && _O_TEXT) 
 
- 	//  {
 
- 	//  m1 = "r";
 
- 	//  m2 = "w";
 
- 	//  } 
 
- 	//else 
 
- 	//  {
 
- 	//  m1 = "rb";
 
- 	//  m2 = "wb";
 
- 	//  }
 
- 	fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
 
- 	//f1 = _fdopen(fd1, m2);
 
- 	fd2 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
 
- 	//f2 = _fdopen(fd2, m1);
 
-         PERROR("_open_osfhandle");
 
- 	if (n != 4)
 
-           {
 
- 	  CloseHandle(hChildStderrRdDup);
 
-           PERROR("CloseHandle");              
 
-           }
 
- 	break;
 
- 	}
 
- 	
 
-     case POPEN_3:
 
-       if ( 1) 
 
- 	{
 
-         // Comment this out. Maybe we will need it in the future.
 
-         // file IO access to the process might be cool.
 
- 	//char *m1, *m2;
 
-       
 
- 	//if (mode && _O_TEXT) 
 
- 	//  {
 
- 	//  m1 = "r";
 
- 	//  m2 = "w";
 
- 	//  } 
 
- 	//else 
 
- 	//  {
 
- 	//  m1 = "rb";
 
- 	//  m2 = "wb";
 
- 	//  }
 
- 	fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
 
- 	//f1 = _fdopen(fd1, m2);
 
- 	fd2 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
 
- 	//f2 = _fdopen(fd2, m1);
 
- 	fd3 = _open_osfhandle(TO_INTPTR(hChildStderrRdDup), mode);
 
- 	//f3 = _fdopen(fd3, m1);	
 
-         PERROR("_open_osfhandle");
 
- 	break;
 
- 	}
 
-     }
 
-   if (n == POPEN_4) 
 
-     {
 
-     if (!RealPopenCreateProcess(cmdstring,
 
- 				path,
 
- 				this->m_ConsoleSpawn.c_str(),
 
- 				hChildStdinRd,
 
- 				hChildStdoutWr,
 
- 				hChildStdoutWr,
 
- 				&hProcess))
 
-       return NULL;
 
-     }
 
-   else 
 
-     {
 
-     if (!RealPopenCreateProcess(cmdstring,
 
- 				path,
 
- 				this->m_ConsoleSpawn.c_str(),
 
- 				hChildStdinRd,
 
- 				hChildStdoutWr,
 
- 				hChildStderrWr,
 
- 				&hProcess))
 
-       return NULL;
 
-     }
 
-   /*
 
-    * Insert the files we've created into the process dictionary
 
-    * all referencing the list with the process handle and the
 
-    * initial number of files (see description below in _PyPclose).
 
-    * Since if _PyPclose later tried to wait on a process when all
 
-    * handles weren't closed, it could create a deadlock with the
 
-    * child, we spend some energy here to try to ensure that we
 
-    * either insert all file handles into the dictionary or none
 
-    * at all.  It's a little clumsy with the various popen modes
 
-    * and variable number of files involved.
 
-    */
 
-   /* Child is launched. Close the parents copy of those pipe
 
-    * handles that only the child should have open.  You need to
 
-    * make sure that no handles to the write end of the output pipe
 
-    * are maintained in this process or else the pipe will not close
 
-    * when the child process exits and the ReadFile will hang. */
 
-   if (!CloseHandle(hChildStdinRd))
 
-     return win32_error("CloseHandle", NULL);
 
-   PERROR("CloseHandle");
 
- 	  
 
-   if (!CloseHandle(hChildStdoutWr))
 
-     return win32_error("CloseHandle", NULL);
 
-   PERROR("CloseHandle");
 
- 	  
 
-   if ((n != 4) && (!CloseHandle(hChildStderrWr)))
 
-     return win32_error("CloseHandle", NULL);
 
-   PERROR("CloseHandle");
 
-   
 
-   this->m_ProcessHandle = hProcess;
 
-   if ( fd1 >= 0 )
 
-     {
 
-     //  this->m_StdIn = f1;
 
-     this->m_pStdIn = fd1;
 
-     }
 
-   if ( fd2 >= 0 )
 
-     {
 
-     //  this->m_StdOut = f2;
 
-     this->m_pStdOut = fd2;
 
-     }
 
-   if ( fd3 >= 0 )
 
-     {
 
-     //  this->m_StdErr = f3;
 
-     this->m_pStdErr = fd3;
 
-     }
 
-   //std::cout << "Process created for real..." << std::endl;
 
-   //std::cout << fd1 << " " << fd2 << " " << fd3 << std::endl;
 
-   return true;
 
- }
 
- /*
 
-  * Wrapper for fclose() to use for popen* files, so we can retrieve the
 
-  * exit code for the child process and return as a result of the close.
 
-  *
 
-  * This function uses the _PyPopenProcs dictionary in order to map the
 
-  * input file pointer to information about the process that was
 
-  * originally created by the popen* call that created the file pointer.
 
-  * The dictionary uses the file pointer as a key (with one entry
 
-  * inserted for each file returned by the original popen* call) and a
 
-  * single list object as the value for all files from a single call.
 
-  * The list object contains the Win32 process handle at [0], and a file
 
-  * count at [1], which is initialized to the total number of file
 
-  * handles using that list.
 
-  *
 
-  * This function closes whichever handle it is passed, and decrements
 
-  * the file count in the dictionary for the process handle pointed to
 
-  * by this file.  On the last close (when the file count reaches zero),
 
-  * this function will wait for the child process and then return its
 
-  * exit code as the result of the close() operation.  This permits the
 
-  * files to be closed in any order - it is always the close() of the
 
-  * final handle that will return the exit code.
 
-  */
 
-  /* RED_FLAG 31-Aug-2000 Tim
 
-   * This is always called (today!) between a pair of
 
-   * Py_BEGIN_ALLOW_THREADS/ Py_END_ALLOW_THREADS
 
-   * macros.  So the thread running this has no valid thread state, as
 
-   * far as Python is concerned.  However, this calls some Python API
 
-   * functions that cannot be called safely without a valid thread
 
-   * state, in particular PyDict_GetItem.
 
-   * As a temporary hack (although it may last for years ...), we
 
-   * *rely* on not having a valid thread state in this function, in
 
-   * order to create our own "from scratch".
 
-   * This will deadlock if _PyPclose is ever called by a thread
 
-   * holding the global lock.
 
-   */
 
- bool cmWin32ProcessExecution::PrivateClose(int timeout)
 
- {
 
-   HANDLE hProcess = this->m_ProcessHandle;
 
-   int result = -1;
 
-   DWORD exit_code;
 
-   std::string output = "";
 
-   bool done = false;
 
-   while(!done)
 
-     {
 
-     Sleep(10);
 
-     bool have_some = false;
 
-     struct _stat fsout;
 
-     struct _stat fserr;
 
-     int rout = _fstat(this->m_pStdOut, &fsout);
 
-     int rerr = _fstat(this->m_pStdErr, &fserr);
 
-     if ( rout && rerr )
 
-       {
 
-       break;
 
-       }
 
-     if (fserr.st_size > 0)
 
-       {
 
-       //std::cout << "Some error" << std::endl;
 
-       char buffer[1023];
 
-       int len = read(this->m_pStdErr, buffer, 1023);
 
-       buffer[len] = 0;
 
-       if ( this->m_Verbose )
 
- 	{
 
- 	std::cout << buffer << std::flush;
 
- 	}
 
-       output += buffer;
 
-       have_some = true;
 
-       }
 
-     if (fsout.st_size > 0)
 
-       {
 
-       //std::cout << "Some output" << std::endl;
 
-       char buffer[1023];
 
-       int len = read(this->m_pStdOut, buffer, 1023);
 
-       buffer[len] = 0;
 
-       if ( this->m_Verbose )
 
- 	{
 
- 	std::cout << buffer << std::flush;
 
- 	}
 
-       output += buffer;
 
-       have_some = true;
 
-       }
 
-     unsigned long exitCode;
 
-     if ( ! have_some )
 
-       {
 
-       GetExitCodeProcess(hProcess,&exitCode);
 
-       if (exitCode != STILL_ACTIVE)
 
-         {
 
-         //std::cout << "STILL_ACTIVE = " << STILL_ACTIVE << std::endl;
 
-         //std::cout << "Process is not active any more: " << exitCode << std::endl;
 
-         break;
 
-         }
 
-       }
 
-     }  
 
-   //std::cout << "Waiting for process to close" << std::endl;
 
-   
 
-   if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
 
-       GetExitCodeProcess(hProcess, &exit_code)) 
 
-     {
 
-     result = exit_code;
 
-     } 
 
-   else 
 
-     {
 
-     /* Indicate failure - this will cause the file object
 
-      * to raise an I/O error and translate the last Win32
 
-      * error code from errno.  We do have a problem with
 
-      * last errors that overlap the normal errno table,
 
-      * but that's a consistent problem with the file object.
 
-      */
 
-     if (result != EOF) 
 
-       {
 
-       /* If the error wasn't from the fclose(), then
 
-        * set errno for the file object error handling.
 
-        */
 
-       errno = GetLastError();
 
-       }
 
-     result = -1;
 
-     }
 
-   //std::cout << "Process closed with error code: " << result << std::endl;
 
- 	
 
-   /* Free up the native handle at this point */
 
-   CloseHandle(hProcess);
 
-   this->m_ExitValue = result;
 
-   this->m_Output = output;
 
-   if ( result < 0 )
 
-     {
 
-     return false;
 
-     }
 
-   return true;
 
- }
 
- int cmWin32ProcessExecution::Windows9xHack(const char* command)
 
- {
 
-   BOOL bRet;
 
-   STARTUPINFO si;
 
-   PROCESS_INFORMATION pi;
 
-   DWORD exit_code=0;
 
-   if (!command) 
 
-     {
 
-     cmSystemTools::Error("Windows9xHack: Command not specified");
 
-     return 1;
 
-   }
 
-   /* Make child process use this app's standard files. */
 
-   ZeroMemory(&si, sizeof si);
 
-   si.cb = sizeof si;
 
-   si.dwFlags = STARTF_USESTDHANDLES;
 
-   si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
 
-   si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 
-   si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 
-   char* cmd = new char[ strlen(command) + 1 ];
 
-   strcpy(cmd, command);
 
-   bRet = CreateProcess(
 
-     NULL, cmd,
 
-     NULL, NULL,
 
-     TRUE, 0,
 
-     NULL, NULL,
 
-     &si, &pi
 
-     );
 
-   delete [] cmd;
 
-   if (bRet) 
 
-     {
 
-     if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) 
 
-       {
 
-       GetExitCodeProcess(pi.hProcess, &exit_code);
 
-       }
 
-     CloseHandle(pi.hProcess);
 
-     CloseHandle(pi.hThread);
 
-     return exit_code;
 
-     }
 
-   return 1;
 
- }
 
 
  |