Errors Misc_executeCommand(const char *commandTemplate, const TextMacro macros[], uint macroCount, ExecuteIOFunction stdoutExecuteIOFunction, ExecuteIOFunction stderrExecuteIOFunction, void *executeIOUserData ) { Errors error; String commandLine; StringTokenizer stringTokenizer; String token; String command; StringList argumentList; const char *path; String fileName; bool foundFlag; char const **arguments; int pipeStdin[2],pipeStdout[2],pipeStderr[2]; int pid; StringNode *stringNode; uint n,z; int status; bool sleepFlag; String stdoutLine,stderrLine; int exitcode; int terminateSignal; error = ERROR_NONE; if (commandTemplate != NULL) { commandLine = String_new(); command = File_newFileName(); StringList_init(&argumentList); // expand command line Misc_expandMacros(commandLine,commandTemplate,macros,macroCount); printInfo(3,"Execute command '%s'...",String_cString(commandLine)); // parse command String_initTokenizer(&stringTokenizer,commandLine,STRING_BEGIN,STRING_WHITE_SPACES,STRING_QUOTES,FALSE); if (!String_getNextToken(&stringTokenizer,&token,NULL)) { String_doneTokenizer(&stringTokenizer); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return ERRORX_(PARSE_COMMAND,0,String_cString(commandLine)); } File_setFileName(command,token); // parse arguments while (String_getNextToken(&stringTokenizer,&token,NULL)) { StringList_append(&argumentList,token); } String_doneTokenizer(&stringTokenizer); // find command in PATH path = getenv("PATH"); if (path != NULL) { fileName = File_newFileName(); foundFlag = FALSE; String_initTokenizerCString(&stringTokenizer,path,":","",FALSE); while (String_getNextToken(&stringTokenizer,&token,NULL) && !foundFlag) { File_setFileName(fileName,token); File_appendFileName(fileName,command); if (File_exists(fileName)) { File_setFileName(command,fileName); foundFlag = TRUE; } } String_doneTokenizer(&stringTokenizer); File_deleteFileName(fileName); } #if 0 fprintf(stderr,"%s,%d: command %s\n",__FILE__,__LINE__,String_cString(command)); stringNode = argumentList.head; while (stringNode != NULL) { fprintf(stderr,"%s,%d: argument %s\n",__FILE__,__LINE__,String_cString(stringNode->string)); stringNode = stringNode->next; } #endif /* 0 */ #if defined(HAVE_PIPE) && defined(HAVE_FORK) && defined(HAVE_WAITPID) #if 1 // create i/o pipes if (pipe(pipeStdin) != 0) { error = ERRORX_(IO_REDIRECT_FAIL,errno,String_cString(commandLine)); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } if (pipe(pipeStdout) != 0) { error = ERRORX_(IO_REDIRECT_FAIL,errno,String_cString(commandLine)); close(pipeStdin[0]); close(pipeStdin[1]); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } if (pipe(pipeStderr) != 0) { error = ERRORX_(IO_REDIRECT_FAIL,errno,String_cString(commandLine)); close(pipeStdout[0]); close(pipeStdout[1]); close(pipeStdin[0]); close(pipeStdin[1]); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } // do fork to start separated process pid = fork(); if (pid == 0) { // close stdin, stdout, and stderr and reassign them to the pipes close(STDERR_FILENO); close(STDOUT_FILENO); close(STDIN_FILENO); // redirect stdin/stdout/stderr to pipe dup2(pipeStdin[0],STDIN_FILENO); dup2(pipeStdout[1],STDOUT_FILENO); dup2(pipeStderr[1],STDERR_FILENO); /* close unused pipe handles (the pipes are duplicated by fork(), thus there are two open ends of the pipes) */ close(pipeStderr[0]); close(pipeStdout[0]); close(pipeStdin[1]); // execute of external program n = 1+StringList_count(&argumentList)+1; arguments = (char const**)malloc(n*sizeof(char*)); if (arguments == NULL) { HALT_INSUFFICIENT_MEMORY(); } z = 0; arguments[z] = String_cString(command); z++; stringNode = argumentList.head; while (stringNode != NULL) { assert(z < n); arguments[z] = String_cString(stringNode->string); z++; stringNode = stringNode->next; } assert(z < n); arguments[z] = NULL; z++; execvp(String_cString(command),(char**)arguments); // in case exec() fail, return a default exitcode HALT_INTERNAL_ERROR("execvp() returned"); } else if (pid < 0) { error = ERRORX_(EXEC_FAIL,errno,String_cString(commandLine)); printInfo(3,"FAIL!\n"); close(pipeStderr[0]); close(pipeStderr[1]); close(pipeStdout[0]); close(pipeStdout[1]); close(pipeStdin[0]); close(pipeStdin[1]); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } // close unused pipe handles (the pipe is duplicated by fork(), thus there are two open ends of the pipe) close(pipeStderr[1]); close(pipeStdout[1]); close(pipeStdin[0]); #else /* 0 */ error = ERROR_NONE; #endif /* 0 */ // wait until process terminate and read stdout/stderr stdoutLine = String_new(); stderrLine = String_new(); status = 0; while ((waitpid(pid,&status,WNOHANG) == 0) || (!WIFEXITED(status) && !WIFSIGNALED(status))) { sleepFlag = TRUE; if (readProcessIO(pipeStdout[0],stdoutLine)) { if (stdoutExecuteIOFunction != NULL) stdoutExecuteIOFunction(executeIOUserData,stdoutLine); String_clear(stdoutLine); sleepFlag = FALSE; } if (readProcessIO(pipeStderr[0],stderrLine)) { if (stderrExecuteIOFunction != NULL) stderrExecuteIOFunction(executeIOUserData,stderrLine); String_clear(stderrLine); sleepFlag = FALSE; } if (sleepFlag) { Misc_udelay(500LL*1000LL); } } while (readProcessIO(pipeStdout[0],stdoutLine)) { if (stdoutExecuteIOFunction != NULL) stdoutExecuteIOFunction(executeIOUserData,stdoutLine); String_clear(stdoutLine); } while (readProcessIO(pipeStderr[0],stderrLine)) { if (stderrExecuteIOFunction != NULL) stderrExecuteIOFunction(executeIOUserData,stderrLine); String_clear(stderrLine); } String_delete(stderrLine); String_delete(stdoutLine); // close i/o close(pipeStderr[0]); close(pipeStdout[0]); close(pipeStdin[1]); // check exit code exitcode = -1; if (WIFEXITED(status)) { exitcode = WEXITSTATUS(status); printInfo(3,"ok (exitcode %d)\n",exitcode); if (exitcode != 0) { error = ERRORX_(EXEC_FAIL,exitcode,String_cString(commandLine)); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } } else if (WIFSIGNALED(status)) { terminateSignal = WTERMSIG(status); error = ERRORX_(EXEC_FAIL,terminateSignal,String_cString(commandLine)); printInfo(3,"FAIL (signal %d)\n",terminateSignal); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } else { printInfo(3,"ok (unknown exit)\n"); } #elif defined(WIN32) #if 0 HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; HANDLE hInputWriteTmp,hInputRead,hInputWrite; HANDLE hErrorWrite; HANDLE hThread; DWORD ThreadId; SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Create the child output pipe. if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) DisplayError("CreatePipe"); // Create a duplicate of the output write handle for the std error // write handle. This is necessary in case the child application // closes one of its std output handles. if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, GetCurrentProcess(),&hErrorWrite,0, TRUE,DUPLICATE_SAME_ACCESS)) DisplayError("DuplicateHandle"); // Create the child input pipe. if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) DisplayError("CreatePipe"); // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, GetCurrentProcess(), &hOutputRead, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError("DupliateHandle"); if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, GetCurrentProcess(), &hInputWrite, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError("DupliateHandle"); // Close inheritable copies of the handles you do not want to be // inherited. if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle"); // Get std input handle so you can close it and force the ReadFile to // fail when you want the input thread to exit. if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE ) DisplayError("GetStdHandle"); PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite); // Close pipe handles (do not continue to modify the parent). // 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(hOutputWrite)) DisplayError("CloseHandle"); if (!CloseHandle(hInputRead )) DisplayError("CloseHandle"); if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); // Launch the thread that gets the input and sends it to the child. hThread = CreateThread(NULL,0,GetAndSendInputThread, (LPVOID)hInputWrite,0,&ThreadId); if (hThread == NULL) DisplayError("CreateThread"); // Read the child's output. ReadAndHandleOutput(hOutputRead); // Redirection is complete // Force the read on the input to return by closing the stdin handle. if (!CloseHandle(hStdIn)) DisplayError("CloseHandle"); // Tell the thread to exit and wait for thread to die. bRunThread = FALSE; if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED) DisplayError("WaitForSingleObject"); if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle"); #endif #else /* not defined(HAVE_PIPE) && defined(HAVE_FORK) && defined(HAVE_WAITPID) || WIN32 */ #error pipe()/fork()/waitpid() not available nor Win32 system! #endif /* defined(HAVE_PIPE) && defined(HAVE_FORK) && defined(HAVE_WAITPID) || WIN32 */ // free resources StringList_done(&argumentList); String_delete(command); String_delete(commandLine); } return error; }
BOOL Redirector::StartChildProcess(LPCTSTR lpszCmdLine, BOOL bShowChildWindow) { if (m_bWorking) return TRUE; Handle hProcess = ::GetCurrentProcess(); // Set up the security attributes struct. SECURITY_ATTRIBUTES sa = {0}; sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; Handle hStdInWriteTmp, hStdOutReadTmp, hStdErrReadTmp; // Create the child stdin pipe. if (! ::CreatePipe(&m_hStdIn, &hStdInWriteTmp, &sa, 0)) return FALSE; // Create the child stdout pipe. if (! ::CreatePipe(&hStdOutReadTmp, &m_hStdOut, &sa, 0)) return FALSE; // Create the child stderr pipe. if (! ::CreatePipe(&hStdErrReadTmp, &m_hStdErr, &sa, 0)) return FALSE; // Create new stdin write, stdout and stderr read handles. // Set the properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (! ::DuplicateHandle(hProcess, hStdInWriteTmp, hProcess, &m_hStdInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)) return FALSE; if (! ::DuplicateHandle(hProcess, hStdOutReadTmp, hProcess, &m_hStdOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) return FALSE; if (! ::DuplicateHandle(hProcess, hStdErrReadTmp, hProcess, &m_hStdErrRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) return FALSE; // Close inheritable copies of the handles you do not want to be // inherited. hStdInWriteTmp.Close(); hStdOutReadTmp.Close(); hStdErrReadTmp.Close(); // Start child process with redirected stdout, stdin & stderr BOOL bCreateOK = PrepAndLaunchRedirectedChild(lpszCmdLine, m_hStdOut, m_hStdIn, m_hStdErr, bShowChildWindow, &m_hChildProcess); if (! bCreateOK) { CHAR lpszBuffer[BUFFER_SIZE]; sprintf_s(lpszBuffer, "Unable to start %s", t2a(lpszCmdLine)); OnChildStdOutWrite(lpszBuffer); // close all handles and return FALSE m_hStdIn.Close(); m_hStdOut.Close(); m_hStdErr.Close(); return FALSE; } DWORD dwThreadID; m_bRunThread = TRUE; // Create Exit event m_hExitEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); if (! m_hExitEvent.IsValid()) return FALSE; // Launch the thread that read the child stdout. m_hStdOutThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)staticStdOutThread, (LPVOID)this, 0, &dwThreadID); if (! m_hStdOutThread.IsValid()) return FALSE; // Launch the thread that read the child stderr. m_hStdErrThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)staticStdErrThread, (LPVOID)this, 0, &dwThreadID); if (! m_hStdErrThread.IsValid()) return FALSE; // Launch the thread that monitoring the child process. m_hProcessThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)staticProcessThread, (LPVOID)this, 0, &dwThreadID); if (! m_hProcessThread.IsValid()) return FALSE; // Virtual function to notify derived class that the child is started. OnChildStarted(t2a(lpszCmdLine)); m_bWorking = TRUE; return TRUE; }
bool System::call(const char *command,bool capt_stdout) { hOutputRead=NULL; hInputWrite=NULL; capture_stdout=capt_stdout; hChildProcess = NULL; HANDLE hOutputWrite=GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hInputRead=GetStdHandle(STD_INPUT_HANDLE); SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (capture_stdout) { HANDLE hOutputReadTmp=NULL; HANDLE hInputWriteTmp=NULL; // Create the child output pipe. if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) { ERROR2("CreatePipe errno:%i\n",GetLastError()); return false; } // Create the child input pipe. if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) { ERROR2("CreatePipe errno:%i\n",GetLastError()); return false; } // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, GetCurrentProcess(), &hOutputRead, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) { ERROR2("DupliateHandle errno:%i\n",GetLastError()); return false; } if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, GetCurrentProcess(), &hInputWrite, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) { ERROR2("DupliateHandle errno:%i\n",GetLastError()); return false; } // Close inheritable copies of the handles you do not want to be // inherited. if (!CloseHandle(hOutputReadTmp)) { ERROR2("CloseHandle errno:%i\n",GetLastError()); return false; } if (!CloseHandle(hInputWriteTmp)) { ERROR2("CloseHandle errno:%i\n",GetLastError()); return false; } } hChildProcess = PrepAndLaunchRedirectedChild(command,hOutputWrite,hInputRead,GetStdHandle(STD_ERROR_HANDLE)); if (capt_stdout) { // Close pipe handles (do not continue to modify the parent). // 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(hOutputWrite)) { ERROR2("CloseHandle errno:%i\n",GetLastError()); return false; } if (!CloseHandle(hInputRead )) { ERROR2("CloseHandle errno:%i\n",GetLastError()); return false; } } return true; }
BOOL StartChildProcess(void* handle, char* lpszCmdLine, BOOL bShowChildWindow, PROCESS_INFORMATION* ppi) { pcmd_backend_data local = handle; HANDLE hProcess = GetCurrentProcess(); HANDLE hStdInWriteTmp, hStdOutReadTmp, hStdErrReadTmp; DWORD dwThreadID; // Set up the security attributes struct. SECURITY_ATTRIBUTES sa; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Create the child stdin pipe. VERIFY(CreatePipe(&local->m_hStdIn, &hStdInWriteTmp, &sa, 0)); // Create the child stdout pipe. VERIFY(CreatePipe(&hStdOutReadTmp, &local->m_hStdOut, &sa, 0)); // Create the child stderr pipe. VERIFY(CreatePipe(&hStdErrReadTmp, &local->m_hStdErr, &sa, 0)); // Create new stdin write, stdout and stderr read handles. // Set the properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. VERIFY(DuplicateHandle(hProcess, hStdInWriteTmp, hProcess, &local->m_hStdInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)); VERIFY(DuplicateHandle(hProcess, hStdOutReadTmp, hProcess, &local->m_hStdOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS)); VERIFY(DuplicateHandle(hProcess, hStdErrReadTmp, hProcess, &local->m_hStdErrRead, 0, FALSE, DUPLICATE_SAME_ACCESS)); // Close inheritable copies of the handles you do not want to be // inherited. VERIFY(CloseHandle(hStdInWriteTmp)); VERIFY(CloseHandle(hStdOutReadTmp)); VERIFY(CloseHandle(hStdErrReadTmp)); // Start child process with redirected stdout, stdin & stderr local->m_hChildProcess = PrepAndLaunchRedirectedChild(lpszCmdLine, ppi, local->m_hStdOut, local->m_hStdIn, local->m_hStdErr, bShowChildWindow); if (local->m_hChildProcess == NULL) { // close all handles and return FALSE VERIFY(CloseHandle(local->m_hStdIn)); local->m_hStdIn = NULL; VERIFY(CloseHandle(local->m_hStdOut)); local->m_hStdOut = NULL; VERIFY(CloseHandle(local->m_hStdErr)); local->m_hStdErr = NULL; return FALSE; } local->m_bRunThread = TRUE; // Create Exit event local->m_hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); VERIFY(local->m_hExitEvent != NULL); // Launch the thread that read the child stdout. local->m_hStdOutThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cygterm_readstdin_thread, (LPVOID)local, 0, &dwThreadID); VERIFY(local->m_hStdOutThread != NULL); SetStdHandle(STD_OUTPUT_HANDLE, local->m_hStdInWrite); SetStdHandle(STD_INPUT_HANDLE, local->m_hStdOutRead); //// Launch the thread that read the child stderr. local->m_hStdErrThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cygterm_readstderr_thread, (LPVOID)local, 0, &dwThreadID); VERIFY(local->m_hStdErrThread != NULL); // Launch the thread that monitoring the child process. local->m_hProcessThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cygterm_watch_child_process, (LPVOID)local, 0, &dwThreadID); VERIFY(local->m_hProcessThread != NULL); local->m_hWriteEvent = CreateEvent(NULL, FALSE, TRUE, NULL); return TRUE; }
void main () { HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; HANDLE hInputWriteTmp,hInputRead,hInputWrite; HANDLE hErrorWrite; HANDLE hThread; DWORD ThreadId; SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Create the child output pipe. if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) DisplayError("CreatePipe"); // Create a duplicate of the output write handle for the std error // write handle. This is necessary in case the child application // closes one of its std output handles. if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, GetCurrentProcess(),&hErrorWrite,0, TRUE,DUPLICATE_SAME_ACCESS)) DisplayError("DuplicateHandle"); // Create the child input pipe. if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) DisplayError("CreatePipe"); // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, GetCurrentProcess(), &hOutputRead, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError("DupliateHandle"); if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, GetCurrentProcess(), &hInputWrite, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError("DupliateHandle"); // Close inheritable copies of the handles you do not want to be // inherited. if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle"); // Get std input handle so you can close it and force the ReadFile to // fail when you want the input thread to exit. if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE ) DisplayError("GetStdHandle"); PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite); // Close pipe handles (do not continue to modify the parent). // 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(hOutputWrite)) DisplayError("CloseHandle"); if (!CloseHandle(hInputRead )) DisplayError("CloseHandle"); if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); // Launch the thread that gets the input and sends it to the child. hThread = CreateThread(NULL,0,GetAndSendInputThread, (LPVOID)hInputWrite,0,&ThreadId); if (hThread == NULL) DisplayError("CreateThread"); // Read the child's output. ReadAndHandleOutput(hOutputRead); // Redirection is complete // Force the read on the input to return by closing the stdin handle. Sleep(5000); if (!CloseHandle(hStdIn)) DisplayError("CloseHandle"); printf("closed hStdIn\n"); // Tell the thread to exit and wait for thread to die. bRunThread = FALSE; if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED) DisplayError("WaitForSingleObject"); if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle"); }
BOOL CExecutor::Execute(CString strCmdLine, CMemFile* pInput) { HANDLE hOutputReadTmp,hOutputWrite; HANDLE hInputWriteTmp,hInputRead; HANDLE hErrorWrite; // Set up the security attributes struct. SECURITY_ATTRIBUTES sa; sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Create the child output pipe. if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) { //theApp.FormatMessage("CExecutor::Execute::CreatePipe"); } // Create a duplicate of the output write handle for the std error // write handle. This is necessary in case the child application // closes one of its std output handles. if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, GetCurrentProcess(),&hErrorWrite,0, TRUE,DUPLICATE_SAME_ACCESS)) { //theApp.FormatMessage("CExecutor::Execute::DuplicateHandle"); } // Create the child input pipe. if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) { //theApp.FormatMessage("CExecutor::Execute::CreatePipe"); } // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, GetCurrentProcess(), &m_hOutputRead, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) { //theApp.FormatMessage("CExecutor::Execute::DupliateHandle"); } if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, GetCurrentProcess(), &m_hInputWrite, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) { //theApp.FormatMessage("DupliateHandle"); } // Close inheritable copies of the handles you do not want to be // inherited. if (!CloseHandle(hOutputReadTmp)) { //theApp.FormatMessage("CExecutor::Execute::CloseHandle"); } if (!CloseHandle(hInputWriteTmp)) { //theApp.FormatMessage("CExecutor::Execute::CloseHandle"); } PrepAndLaunchRedirectedChild(hOutputWrite, hInputRead, hErrorWrite, strCmdLine); // Close pipe handles (do not continue to modify the parent). // 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(hOutputWrite)) { //theApp.FormatMessage("CExecutor::Execute::CloseHandle"); } if (!CloseHandle(hInputRead )) { //theApp.FormatMessage("CExecutor::Execute::CloseHandle"); } if (!CloseHandle(hErrorWrite)) { //theApp.FormatMessage("CExecutor::Execute::CloseHandle"); } // Launch the thread that gets the input and sends it to the child. DWORD ThreadId; m_hThread = CreateThread(NULL, 0, ReadAndHandleOutput, (LPVOID)this, 0, &ThreadId); if (m_hThread == NULL) { //theApp.FormatMessage("CExecutor::Execute::CreateThread"); } if ( pInput!=NULL ) { LPBYTE buf = (LPBYTE)malloc(pInput->GetLength()); pInput->SeekToBegin(); pInput->Read(buf, pInput->GetLength()); Write(buf, pInput->GetLength()); Close(); free(buf); } else Close(); return TRUE; }
BOOL CGravador::RodaConsole(DWORD * pdwExitCode, CString strRun) { HANDLE hOutputReadTmp; HANDLE hOutputWrite; SECURITY_ATTRIBUTES sa; strReturn.Empty(); // Set up the security attributes struct. sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Create the child output pipe. if (!CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0)) DisplayError(_T("CreatePipe")); // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (!DuplicateHandle( GetCurrentProcess(), hOutputReadTmp, GetCurrentProcess(), &hOutputRead, // Address of new handle. 0, FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError(_T("DuplicateHandle")); // Close inheritable copies of the handles you do not want to be // inherited. if (!CloseHandle(hOutputReadTmp)) DisplayError(_T("CloseHandle")); pWDlg->BeginWaitCursor(); CHandleThread * pHandleThread; pHandleThread = new CHandleThread(); pHandleThread->IniciaThread((void *) this, ReadAndHandleOutput); PrepAndLaunchRedirectedChild(hOutputWrite, NULL, NULL, strRun); // o child neste caso será o osql.exe // Close pipe handles (do not continue to modify the parent). // 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(hOutputWrite)) DisplayError(_T("CloseHandle")); // Read the child's output. // ReadAndHandleOutput(hOutputRead); // Redirection is complete // espera finalização do osql.exe DWORD dwRet; dwRet = WaitForSingleObject(hChildProcess, INFINITE); pHandleThread->FinalizaThread(10000); delete pHandleThread; if (dwRet == WAIT_FAILED) DisplayError(_T("WaitForSingleObject")); pWDlg->EndWaitCursor(); if (!CloseHandle(hOutputRead)) DisplayError(_T("CloseHandle")); BOOL bResult; bResult = GetExitCodeProcess(hChildProcess, pdwExitCode); if (!CloseHandle(hChildProcess)) DisplayError(_T("CloseHandle")); return bResult; }