bool Q3Process::start( QStringList *env ) { #if defined(QT_Q3PROCESS_DEBUG) qDebug( "Q3Process::start()" ); #endif reset(); if ( _arguments.isEmpty() ) return false; // Open the pipes. Make non-inheritable copies of input write and output // read handles to avoid non-closable handles (this is done by the // DuplicateHandle() call). SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE }; #ifndef Q_OS_WINCE // I guess there is no stdin stdout and stderr on Q_OS_WINCE to dup // CreatePipe and DupilcateHandle aren't available for Q_OS_WINCE HANDLE tmpStdin, tmpStdout, tmpStderr; if ( comms & Stdin ) { if ( !CreatePipe( &d->pipeStdin[0], &tmpStdin, &secAtt, 0 ) ) { d->closeHandles(); return false; } if ( !DuplicateHandle( GetCurrentProcess(), tmpStdin, GetCurrentProcess(), &d->pipeStdin[1], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { d->closeHandles(); return false; } if ( !CloseHandle( tmpStdin ) ) { d->closeHandles(); return false; } } if ( comms & Stdout ) { if ( !CreatePipe( &tmpStdout, &d->pipeStdout[1], &secAtt, 0 ) ) { d->closeHandles(); return false; } if ( !DuplicateHandle( GetCurrentProcess(), tmpStdout, GetCurrentProcess(), &d->pipeStdout[0], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { d->closeHandles(); return false; } if ( !CloseHandle( tmpStdout ) ) { d->closeHandles(); return false; } } if ( comms & Stderr ) { if ( !CreatePipe( &tmpStderr, &d->pipeStderr[1], &secAtt, 0 ) ) { d->closeHandles(); return false; } if ( !DuplicateHandle( GetCurrentProcess(), tmpStderr, GetCurrentProcess(), &d->pipeStderr[0], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { d->closeHandles(); return false; } if ( !CloseHandle( tmpStderr ) ) { d->closeHandles(); return false; } } if ( comms & DupStderr ) { CloseHandle( d->pipeStderr[1] ); d->pipeStderr[1] = d->pipeStdout[1]; } #endif // construct the arguments for CreateProcess() QString args; QString appName; QStringList::Iterator it = _arguments.begin(); args = *it; ++it; if ( args.endsWith( QLatin1String(".bat") ) && args.contains( QLatin1Char(' ') ) ) { // CreateProcess() seems to have a strange semantics (see also // http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_11138647.html): // If you start a batch file with spaces in the filename, the first // argument to CreateProcess() must be the name of the batchfile // without quotes, but the second argument must start with the same // argument with quotes included. But if the same approach is used for // .exe files, it doesn't work. appName = args; args = QLatin1Char('"') + args + QLatin1Char('"'); } for ( ; it != _arguments.end(); ++it ) { QString tmp = *it; // escape a single " because the arguments will be parsed tmp.replace( QLatin1Char('\"'), QLatin1String("\\\"") ); if ( tmp.isEmpty() || tmp.contains( QLatin1Char(' ') ) || tmp.contains( QLatin1Char('\t') ) ) { // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: e.g. // rather use "foo"\ than "foo\" QString endQuote( QLatin1String("\"") ); int i = tmp.length(); while ( i>0 && tmp.at( i-1 ) == QLatin1Char('\\') ) { --i; endQuote += QLatin1Char('\\'); } args += QLatin1String(" \"") + tmp.left( i ) + endQuote; } else { args += QLatin1Char(' ') + tmp; } } #if defined(QT_Q3PROCESS_DEBUG) qDebug( "Q3Process::start(): args [%s]", args.latin1() ); #endif // CreateProcess() bool success; d->newPid(); STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, STARTF_USESTDHANDLES, 0, 0, 0, d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] }; wchar_t *applicationName; if ( appName.isNull() ) applicationName = 0; else applicationName = _wcsdup( (wchar_t*)appName.utf16() ); wchar_t *commandLine = _wcsdup( (wchar_t*)args.utf16() ); QByteArray envlist; if ( env != 0 ) { int pos = 0; // add PATH if necessary (for DLL loading) QByteArray path = qgetenv( "PATH" ); if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) { QString tmp = QString::fromLatin1("PATH=%1").arg(QLatin1String(path.constData())); uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data() + pos, tmp.utf16(), tmpSize ); pos += tmpSize; } // add the user environment for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { QString tmp = *it; uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data() + pos, tmp.utf16(), tmpSize ); pos += tmpSize; } // add the 2 terminating 0 (actually 4, just to be on the safe side) envlist.resize( envlist.size()+4 ); envlist[pos++] = 0; envlist[pos++] = 0; envlist[pos++] = 0; envlist[pos++] = 0; } success = CreateProcess( applicationName, commandLine, 0, 0, TRUE, ( comms == 0 ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW ) #ifndef Q_OS_WINCE | CREATE_UNICODE_ENVIRONMENT #endif , env == 0 ? 0 : envlist.data(), (wchar_t*)QDir::toNativeSeparators(workingDir.absPath()).utf16(), &startupInfo, d->pid ); free( applicationName ); free( commandLine ); if ( !success ) { d->deletePid(); return false; } #ifndef Q_OS_WINCE if ( comms & Stdin ) CloseHandle( d->pipeStdin[0] ); if ( comms & Stdout ) CloseHandle( d->pipeStdout[1] ); if ( (comms & Stderr) && !(comms & DupStderr) ) CloseHandle( d->pipeStderr[1] ); #endif if ( ioRedirection || notifyOnExit ) { d->lookup->start( 100 ); } // cleanup and return return true; }
int get_exec_output (struct extensible *ex) { #ifndef USING_UTILITIES_EXECUTE_MODULE ex->result = -1; NETSNMP_LOGONCE ((LOG_WARNING, "support for run_exec_command not available\n")); #else #if HAVE_EXECV char cachefile[STRMAX]; char cache[NETSNMP_MAXCACHESIZE]; int cachebytes; int cfd; #ifdef NETSNMP_EXCACHETIME long curtime; static char lastcmd[STRMAX]; static int lastresult; #endif DEBUGMSGTL (("exec:get_exec_output", "calling %s\n", ex->command)); sprintf (cachefile, "%s/%s", get_persistent_directory (), NETSNMP_CACHEFILE); #ifdef NETSNMP_EXCACHETIME curtime = time (NULL); if (curtime > (cachetime + NETSNMP_EXCACHETIME) || strcmp (ex->command, lastcmd) != 0) { strcpy (lastcmd, ex->command); cachetime = curtime; #endif cachebytes = NETSNMP_MAXCACHESIZE; ex->result = run_exec_command (ex->command, NULL, cache, &cachebytes); unlink (cachefile); /* * XXX Use SNMP_FILEMODE_CLOSED instead of 644? */ if ((cfd = open (cachefile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) { snmp_log (LOG_ERR, "can not create cache file\n"); setPerrorstatus (cachefile); #ifdef NETSNMP_EXCACHETIME cachetime = 0; #endif return -1; } if (cachebytes > 0) write (cfd, (void *) cache, cachebytes); close (cfd); #ifdef NETSNMP_EXCACHETIME lastresult = ex->result; } else { ex->result = lastresult; } #endif DEBUGMSGTL (("exec:get_exec_output", "using cached value\n")); if ((cfd = open (cachefile, O_RDONLY)) < 0) { snmp_log (LOG_ERR, "can not open cache file\n"); setPerrorstatus (cachefile); return -1; } return (cfd); #else /* !HAVE_EXECV */ #if defined(WIN32) && !defined(HAVE_EXECV) /* MSVC and MinGW. Cygwin already works as it has execv and fork */ int fd; /* Reference: MS tech note: 190351 */ HANDLE hOutputReadTmp, hOutputRead, hOutputWrite = NULL; HANDLE hErrorWrite; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; DEBUGMSGTL (("exec:get_exec_output", "calling %s\n", ex->command)); /* Child temporary output pipe with Inheritance on (sa.bInheritHandle is true) */ if (!CreatePipe (&hOutputReadTmp, &hOutputWrite, &sa, 0)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CreatePipe ChildOut: %lu\n", GetLastError ())); return -1; } /* Copy the stdout handle to the stderr handle in case the child closes one of * its stdout handles. */ if (!DuplicateHandle (GetCurrentProcess (), hOutputWrite, GetCurrentProcess (), &hErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL (("util_funcs", "get_exec_output DuplicateHandle: %lu\n", GetLastError ())); return -1; } /* Create new copies of the input and output handles but set bInheritHandle to * FALSE so the new handle can not be inherited. Otherwise the handles can not * be closed. */ if (!DuplicateHandle (GetCurrentProcess (), hOutputReadTmp, GetCurrentProcess (), &hOutputRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL (("util_funcs", "get_exec_output DupliateHandle ChildOut: %lu\n", GetLastError ())); CloseHandle (hErrorWrite); return -1; } /* Close the temporary output and input handles */ if (!CloseHandle (hOutputReadTmp)) { DEBUGMSGTL (("util_funcs", "get_exec_output CloseHandle (hOutputReadTmp): %lu\n", GetLastError ())); CloseHandle (hErrorWrite); CloseHandle (hOutputRead); return -1; } /* Associates a C run-time file descriptor with an existing operating-system file handle. */ fd = _open_osfhandle ((long) hOutputRead, 0); /* Set up STARTUPINFO for CreateProcess with the handles and have it hide the window * for the new process. */ ZeroMemory (&si, sizeof (STARTUPINFO)); si.cb = sizeof (STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdOutput = hOutputWrite; si.hStdError = hErrorWrite; si.wShowWindow = SW_HIDE; /* Launch the process that you want to redirect. Example snmpd.conf pass_persist: * pass_persist .1.3.6.1.4.1.2021.255 c:/perl/bin/perl c:/temp/pass_persisttest */ if (!CreateProcess (NULL, ex->command, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { DEBUGMSGTL (("util_funcs", "get_exec_output CreateProcess:'%s' %lu\n", ex->command, GetLastError ())); CloseHandle (hErrorWrite); CloseHandle (hOutputRead); return -1; } /* Set global child process handle */ ex->pid = pi.hProcess; ex->tid = pi.hThread; /* Close pipe handles 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 any calls to ReadFile * will hang. */ if (!CloseHandle (hOutputWrite)) { DEBUGMSGTL (("util_funcs", "get_exec_output CloseHandle hOutputWrite: %lu\n", GetLastError ())); return -1; } if (!CloseHandle (hErrorWrite)) { DEBUGMSGTL (("util_funcs", "get_exec_output CloseHandle hErrorWrite: %lu\n", GetLastError ())); return -1; } return fd; #endif /* WIN32 */ #endif #endif /* !defined(USING_UTILITIES_EXECUTE_MODULE) */ return -1; }
int launch_server(int server_port) { #ifdef HAVE_WIN32_PROC /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; char program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); startup.hStdOutput = pipe_write; startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ GetModuleFileName( NULL, program_path, sizeof(program_path) ); ret = CreateProcess( program_path, /* program path */ "adb fork-server server", /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #elif defined(HAVE_FORKEXEC) char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork // redirect stderr to the pipe // we use stderr instead of stdout due to stdout's buffering behavior. adb_close(fd[0]); dup2(fd[1], STDERR_FILENO); adb_close(fd[1]); // child process int result = execl(path, "adb", "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #else #error "cannot implement background server start on this platform" #endif return 0; }
int CheckForLinkerFeature( const char *option) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; char cmdline[100]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "link.exe -nologo "); /* * Append our option for testing. */ lstrcat(cmdline, option); ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in the stderr stream. */ return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL || strstr(Out.buffer, "LNK4044") != NULL || strstr(Err.buffer, "LNK4044") != NULL); }
int ProcessUtil::ForkCmd( const string &path, const string &cmd, const vector<string> &opts ) { #ifdef WIN32 SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if ( !CreatePipe( &m_StdoutPipe[PIPE_READ], &m_StdoutPipe[PIPE_WRITE], &saAttr, 0 ) ) { printf( "Error StdoutRd CreatePipe\n" ); exit( 0 ); } if ( !SetHandleInformation( m_StdoutPipe[PIPE_READ], HANDLE_FLAG_INHERIT, 0 ) ) { printf( "Stdout SetHandleInformation\n" ); exit( 0 ); } string command = QuoteString( path + string("\\") + cmd ); for( int i = 0; i < opts.size(); i++ ) { command += string(" ") + QuoteString( opts[i] ); } char *cmdstr = (char*) malloc( (command.size()+1) * sizeof(char) ); strcpy( cmdstr, command.c_str() ); ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); si.hStdError = m_StdoutPipe[PIPE_WRITE]; si.hStdOutput = m_StdoutPipe[PIPE_WRITE]; si.dwFlags |= STARTF_USESTDHANDLES; ZeroMemory( &pi, sizeof(pi) ); if( !CreateProcess( NULL, // No module name (use command line). TEXT( cmdstr ), // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. TRUE, // Set handle inheritance to FALSE. 0, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ) // Pointer to PROCESS_INFORMATION structure. ) { printf( "CreateProcess failed (%d).\n", GetLastError() ); return 0; } CloseHandle( m_StdoutPipe[PIPE_WRITE] ); m_StdoutPipe[PIPE_WRITE] = NULL; free( cmdstr ); #else if( pipe( m_StdoutPipe ) < 0 ) { printf( "Error allocating pipe for child output redirect"); return -1; } fcntl( m_StdoutPipe[PIPE_WRITE] , F_SETFL, O_NONBLOCK ); fcntl( m_StdoutPipe[PIPE_READ] , F_SETFL, O_NONBLOCK ); if ( ( childPid = fork() ) == 0 ) { if( dup2( m_StdoutPipe[PIPE_WRITE], STDOUT_FILENO ) == -1 || dup2( m_StdoutPipe[PIPE_WRITE], STDERR_FILENO ) == -1 ) { printf( "Error redirecting child stdout" ); exit( 0 ); } close( m_StdoutPipe[PIPE_READ] ); close( m_StdoutPipe[PIPE_WRITE] ); string command = path + string("/") + cmd; if( cppexecv( command, opts ) < 0 ) { printf( "execv error\n" ); } } else if (childPid < 0) { close( m_StdoutPipe[PIPE_READ] ); close( m_StdoutPipe[PIPE_WRITE] ); printf( "Fork failed (%d).\n", childPid ); return 0; } close( m_StdoutPipe[PIPE_WRITE] ); #endif return 0; }
int launch_server(int server_port) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE nul_read, nul_write; HANDLE pipe_read, pipe_write; HANDLE stdout_handle, stderr_handle; SECURITY_ATTRIBUTES sa; STARTUPINFOW startup; PROCESS_INFORMATION pinfo; WCHAR program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Redirect stdin and stderr to Windows /dev/null. If we instead pass our * stdin/stderr handles and they are console handles, when the adb server * starts up, the C Runtime will see console handles for a process that * isn't connected to a console and it will configure stderr to be closed. * At that point, freopen() could be used to reopen stderr, but it would * take more massaging to fixup the file descriptor number that freopen() * uses. It's simplest to avoid all of this complexity by just redirecting * stdin/stderr to `nul' and then the C Runtime acts as expected. */ nul_read = CreateFileW(L"nul", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_read == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFileW(nul, GENERIC_READ) failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } nul_write = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_write == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFileW(nul, GENERIC_WRITE) failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle(nul_read); return -1; } /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle(nul_read); CloseHandle(nul_write); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). */ stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); if (stdout_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); } if (stderr_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 ); } ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = nul_read; startup.hStdOutput = nul_write; startup.hStdError = nul_write; startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ DWORD module_result = GetModuleFileNameW(NULL, program_path, arraysize(program_path)); if ((module_result == arraysize(program_path)) || (module_result == 0)) { // String truncation or some other error. fprintf(stderr, "GetModuleFileNameW() failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } // Verify that the pipe_write handle value can be passed on the command line // as %d and that the rest of adb code can pass it around in an int. const int pipe_write_as_int = cast_handle_to_int(pipe_write); if (cast_int_to_handle(pipe_write_as_int) != pipe_write) { // If this fires, either handle values are larger than 32-bits or else // there is a bug in our casting. // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx fprintf(stderr, "CreatePipe handle value too large: 0x%p\n", pipe_write); return -1; } WCHAR args[64]; snwprintf(args, arraysize(args), L"adb -P %d fork-server server --reply-fd %d", server_port, pipe_write_as_int); ret = CreateProcessW( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( nul_read ); CloseHandle( nul_write ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #else /* !defined(_WIN32) */ char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and the child will write on fd[1] if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork adb_close(fd[0]); char str_port[30]; snprintf(str_port, sizeof(str_port), "%d", server_port); char reply_fd[30]; snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]); // child process int result = execl(path, "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #endif /* !defined(_WIN32) */ return 0; }
static PSESSION_DATA CreateSession( VOID ) { PSESSION_DATA Session = NULL; BOOL Result; SECURITY_ATTRIBUTES SecurityAttributes; HANDLE ShellStdinPipe = NULL; HANDLE ShellStdoutPipe = NULL; // // Allocate space for the session data // Session = (PSESSION_DATA) malloc(sizeof(SESSION_DATA)); if (Session == NULL) { return(NULL); } // // Reset fields in preparation for failure // Session->ReadPipeHandle = NULL; Session->WritePipeHandle = NULL; // // Create the I/O pipes for the shell // SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL SecurityAttributes.bInheritHandle = TRUE; // Shell will inherit handles Result = CreatePipe(&Session->ReadPipeHandle, &ShellStdoutPipe, &SecurityAttributes, 0); if (!Result) { holler("Failed to create shell stdout pipe, error = %s", itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); goto Failure; } Result = CreatePipe(&ShellStdinPipe, &Session->WritePipeHandle, &SecurityAttributes, 0); if (!Result) { holler("Failed to create shell stdin pipe, error = %s", itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); goto Failure; } // // Start the shell // Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe); // // We're finished with our copy of the shell pipe handles // Closing the runtime handles will close the pipe handles for us. // CloseHandle(ShellStdinPipe); CloseHandle(ShellStdoutPipe); // // Check result of shell start // if (Session->ProcessHandle == NULL) { holler("Failed to execute shell", NULL, NULL, NULL, NULL, NULL, NULL); goto Failure; } // // The session is not connected, initialize variables to indicate that // Session->ClientSocket = INVALID_SOCKET; // // Success, return the session pointer as a handle // return(Session); Failure: // // We get here for any failure case. // Free up any resources and exit // if (ShellStdinPipe != NULL) CloseHandle(ShellStdinPipe); if (ShellStdoutPipe != NULL) CloseHandle(ShellStdoutPipe); if (Session->ReadPipeHandle != NULL) CloseHandle(Session->ReadPipeHandle); if (Session->WritePipeHandle != NULL) CloseHandle(Session->WritePipeHandle); free(Session); return(NULL); }
//Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx. Process::id_type Process::open(const string_type &command, const string_type &path) { if(open_stdin) stdin_fd=std::unique_ptr<fd_type>(new fd_type(NULL)); if(read_stdout) stdout_fd=std::unique_ptr<fd_type>(new fd_type(NULL)); if(read_stderr) stderr_fd=std::unique_ptr<fd_type>(new fd_type(NULL)); Handle stdin_rd_p; Handle stdin_wr_p; Handle stdout_rd_p; Handle stdout_wr_p; Handle stderr_rd_p; Handle stderr_wr_p; SECURITY_ATTRIBUTES security_attributes; security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); security_attributes.bInheritHandle = TRUE; security_attributes.lpSecurityDescriptor = nullptr; std::lock_guard<std::mutex> lock(create_process_mutex); if(stdin_fd) { if (!CreatePipe(&stdin_rd_p, &stdin_wr_p, &security_attributes, 0) || !SetHandleInformation(stdin_wr_p, HANDLE_FLAG_INHERIT, 0)) return 0; } if(stdout_fd) { if (!CreatePipe(&stdout_rd_p, &stdout_wr_p, &security_attributes, 0) || !SetHandleInformation(stdout_rd_p, HANDLE_FLAG_INHERIT, 0)) { return 0; } } if(stderr_fd) { if (!CreatePipe(&stderr_rd_p, &stderr_wr_p, &security_attributes, 0) || !SetHandleInformation(stderr_rd_p, HANDLE_FLAG_INHERIT, 0)) { return 0; } } PROCESS_INFORMATION process_info; STARTUPINFO startup_info; ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION)); ZeroMemory(&startup_info, sizeof(STARTUPINFO)); startup_info.cb = sizeof(STARTUPINFO); startup_info.hStdInput = stdin_rd_p; startup_info.hStdOutput = stdout_wr_p; startup_info.hStdError = stderr_wr_p; if(stdin_fd || stdout_fd || stderr_fd) startup_info.dwFlags |= STARTF_USESTDHANDLES; string_type process_command=command; #ifdef MSYS_PROCESS_USE_SH size_t pos=0; while((pos=process_command.find('\\', pos))!=string_type::npos) { process_command.replace(pos, 1, "\\\\\\\\"); pos+=4; } pos=0; while((pos=process_command.find('\"', pos))!=string_type::npos) { process_command.replace(pos, 1, "\\\""); pos+=2; } process_command.insert(0, "sh -c \""); process_command+="\""; #endif BOOL bSuccess = CreateProcess(nullptr, process_command.empty()?nullptr:&process_command[0], nullptr, nullptr, TRUE, 0, nullptr, path.empty()?nullptr:path.c_str(), &startup_info, &process_info); if(!bSuccess) { CloseHandle(process_info.hProcess); CloseHandle(process_info.hThread); return 0; } else { CloseHandle(process_info.hThread); } if(stdin_fd) *stdin_fd=stdin_wr_p.detach(); if(stdout_fd) *stdout_fd=stdout_rd_p.detach(); if(stderr_fd) *stderr_fd=stderr_rd_p.detach(); closed=false; data.id=process_info.dwProcessId; data.handle=process_info.hProcess; return process_info.dwProcessId; }
deBool deProcess_start (deProcess* process, const char* commandLine, const char* workingDirectory) { SECURITY_ATTRIBUTES securityAttr; STARTUPINFO startInfo; /* Pipes. */ HANDLE stdInRead = DE_NULL; HANDLE stdInWrite = DE_NULL; HANDLE stdOutRead = DE_NULL; HANDLE stdOutWrite = DE_NULL; HANDLE stdErrRead = DE_NULL; HANDLE stdErrWrite = DE_NULL; if (process->state == PROCESSSTATE_RUNNING) { deProcess_setError(process, "Process already running"); return DE_FALSE; } else if (process->state == PROCESSSTATE_FINISHED) { /* Process finished, clean up old cruft. */ deProcess_cleanupHandles(process); process->state = PROCESSSTATE_NOT_STARTED; } deMemset(&startInfo, 0, sizeof(startInfo)); deMemset(&securityAttr, 0, sizeof(securityAttr)); /* Security attributes for inheriting handle. */ securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES); securityAttr.bInheritHandle = TRUE; securityAttr.lpSecurityDescriptor = DE_NULL; /* Create pipes. \todo [2011-10-03 pyry] Clean up handles on error! */ if (!CreatePipe(&stdInRead, &stdInWrite, &securityAttr, 0) || !SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0)) { deProcess_setErrorFromWin32(process, "CreatePipe() failed"); CloseHandle(stdInRead); CloseHandle(stdInWrite); return DE_FALSE; } if (!CreatePipe(&stdOutRead, &stdOutWrite, &securityAttr, 0) || !SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0)) { deProcess_setErrorFromWin32(process, "CreatePipe() failed"); CloseHandle(stdInRead); CloseHandle(stdInWrite); CloseHandle(stdOutRead); CloseHandle(stdOutWrite); return DE_FALSE; } if (!CreatePipe(&stdErrRead, &stdErrWrite, &securityAttr, 0) || !SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0)) { deProcess_setErrorFromWin32(process, "CreatePipe() failed"); CloseHandle(stdInRead); CloseHandle(stdInWrite); CloseHandle(stdOutRead); CloseHandle(stdOutWrite); CloseHandle(stdErrRead); CloseHandle(stdErrWrite); return DE_FALSE; } /* Setup startup info. */ startInfo.cb = sizeof(startInfo); startInfo.hStdError = stdErrWrite; startInfo.hStdOutput = stdOutWrite; startInfo.hStdInput = stdInRead; startInfo.dwFlags |= STARTF_USESTDHANDLES; if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL, workingDirectory, &startInfo, &process->procInfo)) { /* Store error info. */ deProcess_setErrorFromWin32(process, "CreateProcess() failed"); /* Close all handles. */ CloseHandle(stdInRead); CloseHandle(stdInWrite); CloseHandle(stdOutRead); CloseHandle(stdOutWrite); CloseHandle(stdErrRead); CloseHandle(stdErrWrite); return DE_FALSE; } process->state = PROCESSSTATE_RUNNING; /* Close our ends of handles.*/ CloseHandle(stdErrWrite); CloseHandle(stdOutWrite); CloseHandle(stdInRead); /* Construct stdio file objects \note May fail, not detected. */ process->standardIn = deFile_createFromHandle((deUintptr)stdInWrite); process->standardOut = deFile_createFromHandle((deUintptr)stdOutRead); process->standardErr = deFile_createFromHandle((deUintptr)stdErrRead); return DE_TRUE; }
/*static*/ IProcess* WinProcessImpl::Execute(wxEvtHandler *parent, const wxString& cmd, wxString &errMsg, IProcessCreateFlags flags, const wxString &workingDir, IProcessCallback* cb) { SECURITY_ATTRIBUTES saAttr; BOOL fSuccess; MyDirGuard dg; wxString wd(workingDir); if (workingDir.IsEmpty()) { wd = wxGetCwd(); } wxSetWorkingDirectory( wd ); // Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; WinProcessImpl *prc = new WinProcessImpl(parent); prc->LinkCallback( cb ); prc->m_flags = flags; // The steps for redirecting child process's STDOUT: // 1. Save current STDOUT, to be restored later. // 2. Create anonymous pipe to be STDOUT for child process. // 3. Set STDOUT of the parent process to be write handle to // the pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the read handle and // close the inheritable read handle. // Save the handle to the current STDOUT. prc->hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Create a pipe for the child process's STDOUT. if ( !CreatePipe( &prc->hChildStdoutRd, &prc->hChildStdoutWr, &saAttr, 0) ) { delete prc; return NULL; } // Set a write handle to the pipe to be STDOUT. if ( !SetStdHandle(STD_OUTPUT_HANDLE, prc->hChildStdoutWr) ) { delete prc; return NULL; } // Create noninheritable read handle and close the inheritable read handle. fSuccess = DuplicateHandle( GetCurrentProcess(), prc->hChildStdoutRd, GetCurrentProcess(), &prc->hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS ); if ( !fSuccess ) { delete prc; return NULL; } CloseHandle( prc->hChildStdoutRd ); // The steps for redirecting child process's STDERR: // 1. Save current STDERR, to be restored later. // 2. Create anonymous pipe to be STDERR for child process. // 3. Set STDERR of the parent process to be write handle to // the pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the read handle and // close the inheritable read handle. // Save the handle to the current STDERR. prc->hSaveStderr = GetStdHandle(STD_ERROR_HANDLE); // Create a pipe for the child process's STDERR. if ( !CreatePipe( &prc->hChildStderrRd, &prc->hChildStderrWr, &saAttr, 0) ) { delete prc; return NULL; } // Set a write handle to the pipe to be STDERR. if ( !SetStdHandle(STD_ERROR_HANDLE, prc->hChildStderrWr) ) { delete prc; return NULL; } // Create noninheritable read handle and close the inheritable read handle. fSuccess = DuplicateHandle( GetCurrentProcess(), prc->hChildStderrRd, GetCurrentProcess(), &prc->hChildStderrRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS ); if ( !fSuccess ) { delete prc; return NULL; } CloseHandle( prc->hChildStderrRd ); // The steps for redirecting child process's STDIN: // 1. Save current STDIN, to be restored later. // 2. Create anonymous pipe to be STDIN for child process. // 3. Set STDIN of the parent to be the read handle to the // pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the write handle, // and close the inheritable write handle. // Save the handle to the current STDIN. prc->hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); // Create a pipe for the child process's STDIN. if ( !CreatePipe(&prc->hChildStdinRd, &prc->hChildStdinWr, &saAttr, 0) ) { delete prc; return NULL; } // Set a read handle to the pipe to be STDIN. if ( !SetStdHandle(STD_INPUT_HANDLE, prc->hChildStdinRd) ) { delete prc; return NULL; } // Duplicate the write handle to the pipe so it is not inherited. fSuccess = DuplicateHandle(GetCurrentProcess(), prc->hChildStdinWr, GetCurrentProcess(), &prc->hChildStdinWrDup, 0, FALSE, // not inherited DUPLICATE_SAME_ACCESS ); if ( !fSuccess ) { delete prc; return NULL; } CloseHandle(prc->hChildStdinWr); // Execute the child process STARTUPINFO siStartInfo; // Set up members of STARTUPINFO structure. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; ; siStartInfo.hStdInput = prc->hChildStdinRd; siStartInfo.hStdOutput = prc->hChildStdoutWr; siStartInfo.hStdError = prc->hChildStderrWr; // Set the window to hide siStartInfo.wShowWindow = flags & IProcessCreateConsole ? SW_SHOW : SW_HIDE; DWORD creationFlags = flags & IProcessCreateConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW; if(flags & IProcessCreateWithHiddenConsole) { siStartInfo.wShowWindow = SW_HIDE; creationFlags = CREATE_NEW_CONSOLE|CREATE_NEW_PROCESS_GROUP; } BOOL ret = CreateProcess( NULL, cmd.wchar_str(), // shell line execution command NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited creationFlags, // creation flags NULL, // use parent's environment NULL, // CD to tmp dir &siStartInfo, // STARTUPINFO pointer &prc->piProcInfo); // receives PROCESS_INFORMATION if ( ret ) { prc->dwProcessId = prc->piProcInfo.dwProcessId; } else { int err = GetLastError(); wxUnusedVar(err); delete prc; return NULL; } // After process creation, restore the saved STDIN and STDOUT. if ( !SetStdHandle(STD_INPUT_HANDLE, prc->hSaveStdin) ) { delete prc; return NULL; } if ( !SetStdHandle(STD_OUTPUT_HANDLE, prc->hSaveStdout) ) { delete prc; return NULL; } if ( !SetStdHandle(STD_OUTPUT_HANDLE, prc->hSaveStderr) ) { delete prc; return NULL; } if ( prc->m_flags & IProcessCreateConsole || prc->m_flags & IProcessCreateWithHiddenConsole ) { ConsoleAttacher ca(prc->GetPid()); if ( ca.isAttached ) { freopen("CONOUT$","wb", stdout); // reopen stout handle as console window output freopen("CONOUT$","wb", stderr); // reopen stderr handle as console window output } } prc->SetPid( prc->dwProcessId ); prc->StartReaderThread(); return prc; }
/* Execute a command as a "user". The command is run as cmd.exe /c <command> The command is executed from the user's HOME (as determined by the user profile) Input, Output & Err streams are redirected. */ void *win_execute_command(wchar_t *shell, wchar_t *command, wchar_t *user, wchar_t *password, wchar_t *domain, wchar_t *root, int pty_mode) { SECURITY_ATTRIBUTES sa; STARTUPINFOW si; HANDLE out_rd_tmp, in_wr_tmp, out_wr, in_rd, in_wr, err_wr; exec_ctx *ctx; HANDLE ttok, ntok; int ret; ZeroMemory(&sa, sizeof(sa)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; ctx = malloc(sizeof(*ctx)); ZeroMemory(ctx, sizeof(*ctx)); ctx->pty_mode = pty_mode; /* setup the parent child plumbing */ if (!CreatePipe(&in_rd, &in_wr_tmp, &sa, 0)) { printf("Couldn't set up in pipe to child %s", get_error_msg(GetLastError())); free(ctx); return NULL; } if (!CreatePipe(&out_rd_tmp, &out_wr, &sa, 0)) { printf("Couldn't set up stdout pipe to child %s", get_error_msg(GetLastError())); free(ctx); return NULL; } if (!DuplicateHandle(GetCurrentProcess(), out_wr, GetCurrentProcess(), &err_wr, 0, TRUE, DUPLICATE_SAME_ACCESS)) { printf("Couldn't set up stderr pipe to child %s", get_error_msg(GetLastError())); free(ctx); return NULL; } if (!DuplicateHandle(GetCurrentProcess(), out_rd_tmp, GetCurrentProcess(), &ctx->out_rd, 0, FALSE, DUPLICATE_SAME_ACCESS)) { return NULL; } if (!DuplicateHandle(GetCurrentProcess(), in_wr_tmp, GetCurrentProcess(), &in_wr, 0, FALSE, DUPLICATE_SAME_ACCESS)) { return NULL; } CloseHandle(out_rd_tmp); CloseHandle(in_wr_tmp); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = in_rd; si.hStdOutput = out_wr; si.hStdError = err_wr; /* if (!CreateProcessWithLogonW(user, domain, password, LOGON_WITH_PROFILE, shell, command, 0, NULL, root, &si, &ctx->pi)) { */ ret = LogonUserW(user, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &ttok); if (!ret) { CloseHandle(ttok); INFO(GetLastError(), "Login failed for user"); return NULL; } ret = DuplicateTokenEx(ttok, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &ntok); if (!ret) { CloseHandle(ttok); INFO(GetLastError(), "Can't impersonate user"); return NULL; } CloseHandle(ttok); if (!CreateProcessAsUserW(ntok, shell, command, NULL, NULL, TRUE, 0, NULL, root, &si, &ctx->pi)) { int ecode = GetLastError(); INFO(GetLastError(), "CreateProcess failed"); free(ctx); CloseHandle(ntok); return NULL; } CloseHandle(ntok); CloseHandle(out_wr); CloseHandle(err_wr); CloseHandle(in_rd); return ctx; }
/* * The runtime library's popen() on win32 does not work when being * called from a service when running on windows <= 2000, because * there is no stdin/stdout/stderr. * * Executing a command in a pipe and reading the first line from it * is all we need. */ static char * pipe_read_line(char *cmd, char *line, int maxsize) { #ifndef WIN32 FILE *pgver; /* flush output buffers in case popen does not... */ fflush(stdout); fflush(stderr); if ((pgver = popen(cmd, "r")) == NULL) return NULL; if (fgets(line, maxsize, pgver) == NULL) { perror("fgets failure"); pclose(pgver); /* no error checking */ return NULL; } if (pclose_check(pgver)) return NULL; return line; #else /* WIN32 */ SECURITY_ATTRIBUTES sattr; HANDLE childstdoutrd, childstdoutwr, childstdoutrddup; PROCESS_INFORMATION pi; STARTUPINFO si; char *retval = NULL; sattr.nLength = sizeof(SECURITY_ATTRIBUTES); sattr.bInheritHandle = TRUE; sattr.lpSecurityDescriptor = NULL; if (!CreatePipe(&childstdoutrd, &childstdoutwr, &sattr, 0)) return NULL; if (!DuplicateHandle(GetCurrentProcess(), childstdoutrd, GetCurrentProcess(), &childstdoutrddup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { CloseHandle(childstdoutrd); CloseHandle(childstdoutwr); return NULL; } CloseHandle(childstdoutrd); ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdError = childstdoutwr; si.hStdOutput = childstdoutwr; si.hStdInput = INVALID_HANDLE_VALUE; if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { /* Successfully started the process */ char *lineptr; ZeroMemory(line, maxsize); /* Try to read at least one line from the pipe */ /* This may require more than one wait/read attempt */ for (lineptr = line; lineptr < line + maxsize - 1;) { DWORD bytesread = 0; /* Let's see if we can read */ if (WaitForSingleObject(childstdoutrddup, 10000) != WAIT_OBJECT_0) break; /* Timeout, but perhaps we got a line already */ if (!ReadFile(childstdoutrddup, lineptr, maxsize - (lineptr - line), &bytesread, NULL)) break; /* Error, but perhaps we got a line already */ lineptr += strlen(lineptr); if (!bytesread) break; /* EOF */ if (strchr(line, '\n')) break; /* One or more lines read */ } if (lineptr != line) { /* OK, we read some data */ int len; /* If we got more than one line, cut off after the first \n */ lineptr = strchr(line, '\n'); if (lineptr) *(lineptr + 1) = '\0'; len = strlen(line); /* * If EOL is \r\n, convert to just \n. Because stdout is a * text-mode stream, the \n output by the child process is * received as \r\n, so we convert it to \n. The server main.c * sets setvbuf(stdout, NULL, _IONBF, 0) which has the effect of * disabling \n to \r\n expansion for stdout. */ if (len >= 2 && line[len - 2] == '\r' && line[len - 1] == '\n') { line[len - 2] = '\n'; line[len - 1] = '\0'; len--; } /* * We emulate fgets() behaviour. So if there is no newline at the * end, we add one... */ if (len == 0 || line[len - 1] != '\n') strcat(line, "\n"); retval = line; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } CloseHandle(childstdoutwr); CloseHandle(childstdoutrddup); return retval; #endif /* WIN32 */ }
int startCcd(const char* titleId) { STARTUPINFO si; wchar_t *ccd_dir = NULL; std::wstring progPathStr, appDataPathStr, commandLineStr; SECURITY_ATTRIBUTES saAttr; int rv = 0; rv = checkRunningCcd(); if (rv != 0) { LOG_ERROR("An active CCD detected. Please kill the CCD first"); return -1; } ccd_dir = _wgetenv(L"DX_CCD_EXE_PATH"); if (ccd_dir != NULL) { progPathStr.assign(ccd_dir); } else { progPathStr.assign(L"."); } progPathStr.append(L"\\ccd.exe"); // DEFAULT_CCD_APP_DATA_PATH rv = _getCcdAppDataWPath(appDataPathStr); if (rv != 0) { LOG_ERROR("Fail to get ccd app data path: rv %d", rv); return rv; } if (testInstanceNum) { std::wostringstream instanceSuffix; instanceSuffix << L"_" << testInstanceNum; appDataPathStr += instanceSuffix.str(); } std::wstring w_titleId; if (titleId) { std::string titleIdIdString(titleId); w_titleId.assign(titleIdIdString.begin(), titleIdIdString.end()); } wprintf(L"CCD Executable Path: %s\n", progPathStr.c_str()); wprintf(L"AppData Path: %s\n", appDataPathStr.c_str()); commandLineStr = progPathStr + L" \"" + appDataPathStr + L"\"" + L" \"\"" + L" \"\"" + L" \"\"" + L" \"\"" + L" \"" + w_titleId + L"\""; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) { LOG_ERROR("Fail StdoutRd CreatePipe"); } if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { LOG_ERROR("Fail Stdout SetHandleInformation"); } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.hStdOutput = g_hChildStd_OUT_Wr; si.hStdError = g_hChildStd_OUT_Wr; si.dwFlags |= STARTF_USESTDHANDLES; ZeroMemory(&pi, sizeof(pi)); // Issue 1: It is important to detach CCD from the current console window, otherwise it will be // terminated when the console window is closed. // Issue 2: An unfortunate consequence of DETACHED_PROCESS is that certain types of crashes cause // the process to immediately close instead of popping up the "just-in-time debugger" dialog. // Using CREATE_NEW_PROCESS_GROUP doesn't help with issue 1. // Using CREATE_NO_WINDOW doesn't help with issue 2. // Using CREATE_NEW_CONSOLE might be good enough for developers, so allow setting it via the // environment variable, DX_CREATE_NEW_CONSOLE. DWORD processCreationFlags; if (_wgetenv(L"DX_CREATE_NEW_CONSOLE") != NULL) { processCreationFlags = CREATE_NEW_CONSOLE; } else { processCreationFlags = DETACHED_PROCESS; } wprintf(L"CreateProcess(%s)\n", commandLineStr.c_str()); if (!CreateProcess(NULL, (LPTSTR) commandLineStr.c_str(), NULL, NULL, FALSE, processCreationFlags, NULL, NULL, &si, &pi)) { LOG_ERROR("CreateProcess for CCD failed (%d).", GetLastError()); LOG_ERROR("Please make sure CCD.exe is in current folder or set"); LOG_ERROR("DX_CCD_EXE_PATH to the directory that contains CCD.exe"); return -1; } return 0; }
Socket platform_new_connection(SockAddr addr, char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, conf); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); { char *msg = dupprintf("Starting local proxy command: %s", cmd); /* We're allowed to pass NULL here, because we're part of the Windows * front end so we know logevent doesn't expect any data. */ logevent(NULL, msg); sfree(msg); } /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); return ret; } if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); return ret; } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); si.cb = sizeof(si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.cbReserved2 = 0; si.lpReserved2 = NULL; si.hStdInput = cmd_from_us; si.hStdOutput = cmd_to_us; si.hStdError = NULL; CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); sfree(cmd); CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); return make_handle_socket(us_to_cmd, us_from_cmd, plug, FALSE); }
/*-------------------------------------------------------------------------- Launches NetShell, waits for Netshell and all of NetShell's launched processes to die and then relaunches NetShell if nothing exited with non-zero exit status. --------------------------------------------------------------------------*/ int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE hinstExePrev, LPSTR lpszCmdLine, int nCmdShow) { int firsttime = 1; char cmd[2*MAX_PATH]; char args[MAX_PATH]; char cwd[MAX_PATH]; char strhandle[MAX_HSTR]; DWORD nhandles = 0; DWORD exitCode = 0; DWORD dwThreadId, iSignal; HANDLE hpipeRead, hpipeWrite, hSelf; HANDLE *hArray, *hStartArr; SECURITY_ATTRIBUTES saAttr; STARTUPINFO si; PROCESS_INFORMATION pi; #ifdef DEBUG #ifndef PRINT_STDOUT { char logfile[MAX_PATH]; sprintf(logfile, "%x", time(NULL)); strcat(logfile, ".log"); flog = fopen(logfile, "w"); } #endif #endif /* Pick random session id for benefit of serial and modem drivers */ sprintf(strhandle, "%x", GetTickCount()); if (!SetEnvironmentVariable(DPSTUBID, strhandle)) { DPRINT(("stub: set environment variable error %x.\n", GetLastError())); exit(1); } hArray = (HANDLE *)malloc(MAXIMUM_WAIT_OBJECTS * sizeof(HANDLE)); hStartArr = hArray; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hSelf, 0, TRUE, DUPLICATE_SAME_ACCESS)) { DPRINT(("stub: error duplicating own handle\n")); exit(1); } sprintf(strhandle, "%x", hSelf); if (!SetEnvironmentVariable(DPSTUB, strhandle)) { DPRINT(("stub: set environment variable error %x.\n", GetLastError())); exit(1); } // DPRINT(("stub: current process handle is %s\n", strhandle)); /* create event so read thread can signal when it's read a new process */ if (!(hreadEvent = CreateEvent(NULL, FALSE, FALSE, "ReadEvent"))) { DPRINT(("stub: create read event error %x.\n", GetLastError())); exit(1); } *hArray++ = hreadEvent; nhandles++; // DPRINT(("stub: read event handle is %x\n", *(hArray - 1))); /* create event so read thread knows main thread has finished processing hSpawn and can continue to get new processes */ if (!(hcontEvent = CreateEvent(NULL, FALSE, FALSE, "ContinueReadEvent"))) { DPRINT(("stub: create continue read event error %x.\n", GetLastError())); exit(1); } // DPRINT(("stub: continue read event handle is %x\n", hcontEvent)); /* create a pipe with read end uninheritable and write end inheritable*/ if(!CreatePipe(&hpipeRead, &hpipeWrite, &saAttr, sizeof(HANDLE))) { DPRINT(("stub: create pipe error %x.\n", GetLastError())); exit(1); } sprintf(strhandle, "%x", hpipeWrite); if (!SetEnvironmentVariable(DPSTUBWPIPE, strhandle)) { DPRINT(("stub: set environment variable error %x.\n", GetLastError())); exit(1); } if (!DuplicateHandle(GetCurrentProcess(), hpipeRead, GetCurrentProcess(), &hpipeReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DPRINT(("stub: error duplicating uninheritable handle\n")); exit(1); } CloseHandle(hpipeRead); // DPRINT(("stub: uninheritable pipe handle is %x.\n", hpipeReadDup)); /* create a thread to read from pipe about new processes*/ if (CreateThread(NULL, 0, readThread, 0, 0, &dwThreadId) < 0) { DPRINT(("stub: create thread error %x.\n", GetLastError())); exit(1); } /* set command and current working directory for CreateProcess() */ { char *buf; char path[2*MAX_PATH]; char cmdline[1024]; if (getinfo(path, args, cwd) != 0) { CHAR title[TITLELEN]; CHAR msg[MSGLEN]; LoadString(NULL, IDS_NO_JRE_TITLE, title, TITLELEN); LoadString(NULL, IDS_NO_JRE_MSG, msg, MSGLEN); MessageBox(NULL, msg, title, MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); exit(1); } strcat(cmd, "\""); strcat(cmd, path); strcat(cmd, "\" "); strcat(cmd, args); buf = GetCommandLine(); if (!buf) { DPRINT(("stub: error getting commandline args; quitting\n")); exit(1); } strcpy(cmdline, buf); #ifdef DEFAULTARGS /* If no switches given, append default args */ if (!strstr(cmdline, " -")) { strcat(cmdline, " "); strcat(cmdline, DEFAULTARGS); } #endif buf = cmdline; DPRINT(("args: %s\n", buf)); { OSVERSIONINFO VersionInfo; VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&VersionInfo)) { DPRINT(("stub: cannot determine OS; quitting\n")); exit(1); } if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT || VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { while (' ' == *buf || '\t' == *buf) buf++; if (*buf == '\"') { buf++; if (!(buf = strchr(buf, '\"'))) { DPRINT(("stub: cannot get commandline args; quitting\n")); exit(1); } buf++; } else { if (buf = strchr(buf, ' ')) { buf++; } else { buf = "\0"; } } } else { CHAR title[TITLELEN]; CHAR msg[MSGLEN]; LoadString(NULL, IDS_UNSP_OS_TITLE, title, TITLELEN); LoadString(NULL, IDS_UNSP_OS_MSG, msg, MSGLEN); MessageBox(NULL, msg, title, MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); DPRINT(("OS not supported; quitting\n")); exit(1); } while (' ' == *buf || '\t' == *buf) buf++; if (2 * MAX_PATH < strlen(cmd) + strlen(buf) + 2) { DPRINT(("stub: cmd buffer not large enough to hold args; quitting\n")); exit(1); } strcat(cmd, " "); strcat(cmd, buf); } } DPRINT(("cmd: %s\n", cmd)); /* launch NetShell then wait for NetShell and all its launched processes to die, then if all exit status are zero, relaunch NetShell */ do { memset(&pi, 0, sizeof(pi)); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); /* launch NetShell */ DPRINT(("stub: Launching %s from %s.\n", cmd, cwd)); if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, cwd, &si, &pi)) { DPRINT(("stub: Error launching %s from %s; quitting\n", cmd, cwd)); DPRINT(("stub: GetLastError returns %x", GetLastError())); exit(1); } if (firsttime) { char *buf = " -r"; if (2 * MAX_PATH < strlen(cmd) + strlen(buf) + 1) { DPRINT(("stub: cmd buffer not large enough to hold args\n")); exit(1); } strcat(cmd, buf); firsttime = 0; } CloseHandle(pi.hThread); *hArray++ = pi.hProcess; nhandles++; DPRINT(("stub: Launch complete; shell handle %x.\n", *(hArray-1))); /* Wait for NetShell and all its launched processes to exit */ do { iSignal = WaitForMultipleObjects(nhandles, hStartArr, FALSE, INFINITE); if (WAIT_FAILED == iSignal) { DPRINT(("stub: wait error %x.\n", GetLastError())); exit(1); } iSignal -= WAIT_OBJECT_0; if (iSignal >= 0 && iSignal < nhandles) { if (*(hStartArr + iSignal) != hreadEvent) { if (!GetExitCodeProcess(*(hStartArr + iSignal), &exitCode)) { DPRINT(("stub: Error reading spawned process\n")); exit(1); } DPRINT(("stub: deleting handle %x, exit code %d.\n", *(hStartArr + iSignal), exitCode)); if (exitCode) break; CloseHandle(*(hStartArr + iSignal)); if (nhandles && iSignal < nhandles - 1) { *(hStartArr + iSignal) = *(hStartArr + nhandles - 1); } nhandles--; hArray = hStartArr + nhandles; } else { // DPRINT(("stub: got new handle %x\n", hSpawn)); if (hSpawn != 0) { if (hSpawn < 0) { DPRINT(("stub: Error reading spawned process; hSpawn %x\n", hSpawn)); exit(1); } DPRINT(("stub: adding handle %x.\n", hSpawn)); *hArray++ = hSpawn; nhandles++; hSpawn = 0; } else if (hSerial != 0) { char *pstrhandle; if (hSerial < 0 && hSerial != INVALID_HANDLE_VALUE) { DPRINT(("stub: Error reading serial handle; hSerial %x\n", hSerial)); exit(1); } if (hSerial == INVALID_HANDLE_VALUE) { if (GetEnvironmentVariable(DPSTUBMODEM, strhandle, 256)) { HANDLE baseadr; sscanf(strhandle, "%x", &baseadr); CloseHandle(baseadr); DPRINT(("stub: deleted serial h:%x\n",baseadr)); pstrhandle = NULL; } } else { DPRINT(("stub: setting serial h:%x.\n", hSerial)); sprintf(strhandle, "%x", hSerial); pstrhandle = strhandle; } if (!SetEnvironmentVariable(DPSTUBMODEM, pstrhandle)) { DPRINT(("stub: set environment variable error %x.\n", GetLastError())); exit(1); } hSerial = 0; } else { DPRINT(("stub: Error no handle set\n")); exit(1); } if (!SetEvent(hcontEvent)) { DPRINT(("stub: set continue read event error %x.\n", GetLastError())); exit(1); } } } else { DPRINT(("stub: error wait returned invalid handle %d\n", iSignal)); exit(1); } // DPRINT(("stub: nhandles = %d\n", nhandles)); } while (nhandles > 1); // DPRINT(("stub: exited inside loop\n")); #ifdef NOLOOP break; #endif } while (!exitCode); return 0; }
int __cdecl main(int argc, char *argv[]) { const int MAPPINGSIZE = 2048; HANDLE hFileMapping; LPVOID lpMapViewAddress; HANDLE hReadPipe = NULL; HANDLE hWritePipe = NULL; BOOL bRetVal; SECURITY_ATTRIBUTES lpPipeAttributes; /* Initialize the PAL environment. */ if(0 != PAL_Initialize(argc, argv)) { return FAIL; } /* Attempt to create a MapViewOfFile with a NULL handle. */ hFileMapping = NULL; lpMapViewAddress = MapViewOfFile( hFileMapping, FILE_MAP_WRITE, /* access code */ 0, /* high order offset */ 0, /* low order offset */ MAPPINGSIZE); /* number of bytes for map */ if((NULL != lpMapViewAddress) && (GetLastError() != ERROR_INVALID_HANDLE)) { Trace("ERROR:%u: Able to create a MapViewOfFile with " "hFileMapping=0x%lx.\n", GetLastError()); UnmapViewOfFile(lpMapViewAddress); Fail(""); } /* Attempt to create a MapViewOfFile with an invalid handle. */ hFileMapping = INVALID_HANDLE_VALUE; lpMapViewAddress = MapViewOfFile( hFileMapping, FILE_MAP_WRITE, /* access code */ 0, /* high order offset */ 0, /* low order offset */ MAPPINGSIZE); /* number of bytes for map */ if((NULL != lpMapViewAddress) && (GetLastError() != ERROR_INVALID_HANDLE)) { Trace("ERROR:%u: Able to create a MapViewOfFile with " "hFileMapping=0x%lx.\n", GetLastError()); UnmapViewOfFile(lpMapViewAddress); Fail(""); } /* Setup SECURITY_ATTRIBUTES structure for CreatePipe. */ lpPipeAttributes.nLength = sizeof(lpPipeAttributes); lpPipeAttributes.lpSecurityDescriptor = NULL; lpPipeAttributes.bInheritHandle = TRUE; /* Create a Pipe. */ bRetVal = CreatePipe(&hReadPipe, /* read handle*/ &hWritePipe, /* write handle */ &lpPipeAttributes,/* security attributes*/ 0); /* pipe size*/ if (bRetVal == FALSE) { Fail("ERROR: %ld :Unable to create pipe\n", GetLastError()); } /* Attempt creating a MapViewOfFile with a Pipe Handle. */ lpMapViewAddress = MapViewOfFile( hReadPipe, FILE_MAP_WRITE, /* access code */ 0, /* high order offset */ 0, /* low order offset */ MAPPINGSIZE); /* number of bytes for map */ if((NULL != lpMapViewAddress) && (GetLastError() != ERROR_INVALID_HANDLE)) { Trace("ERROR:%u: Able to create a MapViewOfFile with " "hFileMapping=0x%lx.\n", GetLastError()); CloseHandle(hReadPipe); CloseHandle(hWritePipe); UnmapViewOfFile(lpMapViewAddress); Fail(""); } /* Clean-up and Terminate the PAL. */ CloseHandle(hReadPipe); CloseHandle(hWritePipe); PAL_Terminate(); return PASS; }
DWORD WINAPI ThreadProc(LPVOID p) // thread that will start & monitor makensis { TCHAR buf[1024]; char iobuf[1024]; //i/o buffer STARTUPINFO si={sizeof(si),}; SECURITY_ATTRIBUTES sa={sizeof(sa),}; SECURITY_DESCRIPTOR sd={0,}; //security information for pipes PROCESS_INFORMATION pi={0,}; HANDLE newstdout=0,read_stdout=0; //pipe handles OSVERSIONINFO osv={sizeof(osv)}; GetVersionEx(&osv); if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) //initialize security descriptor (Windows NT) { InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, true, NULL, false); sa.lpSecurityDescriptor = &sd; } else sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = true; //allow inheritable handles if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //create stdout pipe { ErrorMessage(_T("CreatePipe")); PostMessage(g_hwnd,WM_USER+1203,0,1); return 1; } GetStartupInfo(&si); //set startupinfo for the spawned process /* The dwFlags member tells CreateProcess how to make the process. STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW validates the wShowWindow member. */ si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdOutput = newstdout; si.hStdError = newstdout; //set the new handles for the child process // ******************************************************************* // If there is a command line in the config file, use it for create process //spawn the child process if (!CreateProcess(NULL,g_cmdline,NULL,NULL,TRUE,CREATE_NEW_CONSOLE, NULL,tempzip_path,&si,&pi)) { ErrorMessage(_T("CreateProcess")); wnd_printf(_T("\r\nPlease make sure the path to makensis.exe is correct.")); CloseHandle(newstdout); CloseHandle(read_stdout); PostMessage(g_hwnd,WM_USER+1203,0,1); return 1; } CloseHandle(newstdout); // close this handle (duplicated in subprocess) now so we get ERROR_BROKEN_PIPE DWORD dwLeft = 0, dwRead = 0; while (ReadFile(read_stdout, iobuf+dwLeft, sizeof(iobuf)-dwLeft-1, &dwRead, NULL)) //wait for buffer, or fails with ERROR_BROKEN_PIPE when subprocess exits { dwRead += dwLeft; iobuf[dwRead] = '\0'; #ifdef _UNICODE // this tweak is to prevent LogMessage from cutting in the middle of an UTF-8 sequence // we print only up to the latest \n of the buffer, and keep the remaining for the next loop char* lastLF = strrchr(iobuf,'\n'); if (lastLF == NULL) lastLF = iobuf+dwRead-1; char ch = *++lastLF; *lastLF = '\0'; MultiByteToWideChar(CP_UTF8,0,iobuf,lastLF+1-iobuf,buf,COUNTOF(buf)); wnd_printf(buf); *lastLF = ch; dwLeft = iobuf+dwRead-lastLF; memmove(iobuf, lastLF, dwLeft); #else wnd_printf(iobuf); #endif } #ifdef _UNICODE // because of UTF-8 tweak, in rare case there can be some data remaining dwRead += dwLeft; iobuf[dwRead] = 0; MultiByteToWideChar(CP_UTF8,0,iobuf,dwRead+1,buf,COUNTOF(buf)); wnd_printf(buf); #endif CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(read_stdout); wsprintf(buf,_T("(source ZIP size was %d bytes)\r\n"),g_zipfile_size); wnd_printf(buf); PostMessage(g_hwnd,WM_USER+1203,0,0); return 0; }
Socket platform_new_connection(SockAddr addr, char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, const Config *cfg) { char *cmd; static const struct socket_function_table socket_fn_table = { sk_localproxy_plug, sk_localproxy_close, sk_localproxy_write, sk_localproxy_write_oob, sk_localproxy_flush, sk_localproxy_set_private_ptr, sk_localproxy_get_private_ptr, sk_localproxy_set_frozen, sk_localproxy_socket_error }; Local_Proxy_Socket ret; HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; if (cfg->proxy_type != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, cfg); { char *msg = dupprintf("Starting local proxy command: %s", cmd); /* We're allowed to pass NULL here, because we're part of the Windows * front end so we know logevent doesn't expect any data. */ logevent(NULL, msg); sfree(msg); } ret = snew(struct Socket_localproxy_tag); ret->fn = &socket_fn_table; ret->plug = plug; ret->error = NULL; /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { ret->error = dupprintf("Unable to create pipes for proxy command"); return (Socket)ret; } if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); ret->error = dupprintf("Unable to create pipes for proxy command"); return (Socket)ret; } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); si.cb = sizeof(si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.cbReserved2 = 0; si.lpReserved2 = NULL; si.hStdInput = cmd_from_us; si.hStdOutput = cmd_to_us; si.hStdError = NULL; CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); sfree(cmd); CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); ret->to_cmd_H = us_to_cmd; ret->from_cmd_H = us_from_cmd; ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, ret, 0); ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata, ret, 0); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); return (Socket) ret; }
/* Run a command and redirect its input and output handles to a pair of anonymous pipes. The process handle and pipe handles are returned in the info struct. Returns the PID of the new process, or -1 on error. */ static int run_command_redirected(char *cmdexec, struct subprocess_info *info) { /* Each named pipe we create has to have a unique name. */ static int pipe_serial_no = 0; char pipe_name[32]; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; setup_environment(&info->fdn); /* Make the pipe handles inheritable. */ sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* The child's input pipe is an ordinary blocking pipe. */ if (CreatePipe(&info->child_in_r, &info->child_in_w, &sa, 0) == 0) { if (o.verbose) logdebug("Error in CreatePipe: %d\n", GetLastError()); return -1; } /* Pipe names must have this special form. */ Snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\ncat-%d-%d", GetCurrentProcessId(), pipe_serial_no); if (o.debug > 1) logdebug("Creating named pipe \"%s\"\n", pipe_name); /* The output pipe has to be nonblocking, which requires this complicated setup. */ info->child_out_r = CreateNamedPipe(pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 4096, 4096, 1000, &sa); if (info->child_out_r == 0) { if (o.verbose) logdebug("Error in CreateNamedPipe: %d\n", GetLastError()); CloseHandle(info->child_in_r); CloseHandle(info->child_in_w); return -1; } info->child_out_w = CreateFile(pipe_name, GENERIC_WRITE, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (info->child_out_w == 0) { CloseHandle(info->child_in_r); CloseHandle(info->child_in_w); CloseHandle(info->child_out_r); return -1; } pipe_serial_no++; /* Don't inherit our end of the pipes. */ SetHandleInformation(info->child_in_w, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(info->child_out_r, HANDLE_FLAG_INHERIT, 0); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.hStdInput = info->child_in_r; si.hStdOutput = info->child_out_w; si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.dwFlags |= STARTF_USESTDHANDLES; memset(&pi, 0, sizeof(pi)); if (CreateProcess(NULL, cmdexec, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0) { if (o.verbose) logdebug("Error in CreateProcess: %d\n", GetLastError()); CloseHandle(info->child_in_r); CloseHandle(info->child_in_w); CloseHandle(info->child_out_r); CloseHandle(info->child_out_w); return -1; } /* Close hThread here because we have no use for it. hProcess is closed in subprocess_info_close. */ CloseHandle(pi.hThread); info->proc = pi.hProcess; return pi.dwProcessId; }
int Helium::Execute( const tstring& command, tstring& output, bool showWindow ) { HANDLE hReadPipe; HANDLE hWritePipe; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if( !CreatePipe( &hReadPipe, &hWritePipe, &sa, 0 ) ) { return -1; } STARTUPINFO si; memset( &si, 0, sizeof(si) ); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = static_cast<int>( showWindow ); si.hStdOutput = hWritePipe; si.hStdError = hWritePipe; PROCESS_INFORMATION pi; memset( &pi, 0, sizeof( pi ) ); if( !CreateProcess( NULL, // filename (tchar*) command.c_str(), // command line for child NULL, // process security descriptor NULL, // thread security descriptor TRUE, // inherit handles? showWindow ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW, // creation flags NULL, // inherited environment address NULL, // startup dir; NULL = start in current &si, // pointer to startup info (input) &pi ) ) // pointer to process info (output) { ::CloseHandle( hReadPipe ); ::CloseHandle( hWritePipe ); return -1; } // close the write end of the pipe so the child will terminate it with EOF ::CloseHandle( hWritePipe ); // read from the pipe until EOF condition reached tchar buffer[80]; unsigned long count; tstringstream stream; BOOL success = TRUE; do { while ( success = ReadFile( hReadPipe, buffer, sizeof(buffer), &count, NULL ) ) { if( success ) { stream.write( buffer, count ); } else { if ( ::GetLastError() == ERROR_BROKEN_PIPE ) { break; } else { return -1; } } } } while( success && count ); // done reading, close our read pipe ::CloseHandle( hReadPipe ); // copy output string output = stream.str(); // get exit code DWORD result = 0; BOOL codeResult = ::GetExitCodeProcess( pi.hProcess, &result ); HELIUM_ASSERT( codeResult ); // close the process handle ::CloseHandle( pi.hProcess ); ::CloseHandle( pi.hThread ); return result; }
/* ** CreateAsc( ) --- Create an association. ** ** Inputs: ** asipc ASSOC_IPC for association ** name name of server creating association. ** Output: ** returns TRUE if succeeds. ** ** GClisten( ) calls CreateAsc( ) when a server wishes to create ** a new association. CrateAsc( ) allocates the resources required by ** the association, and exposes shared information available to other processes. ** The only requirements are that it create four handles in the ASSOC_IPC: ** standard send, standard receive, expedited send, and expeditied receive. ** These handles are the only members created here used by gcacl. In ** this implementation handles to anonymous pipes are used. ** ** If there are no existing connections to the server spicified in the ** name parameter, CreateAsc( ) creates the server specific resources and ** adds the server to the internally maintained list of servers. A memory mapped ** mapped file is created for passing information between the client and ** server. This file contains a temporary area for passing process id and ** handles which the client needs to copy to its own ASSOC_IPC. It also ** contains and array of assoc_info structures. These structures contain ** information that must be shared per connection for the duration of each ** association. A mutex is created to protect access to the temporary area. ** The temporary area is only used when a connectionis first established ** to copy handles to the pipes and other information to the requester's ** ASSOC_IPC. ** ** Two events are also created to arbitrate the connection process. When ** a server is ready for a connection, it signals a "listening event". ** and waits for a client to set a requesting event. Before connecting ** a client waits on the listening event before trying to connect. When ** the client tries to connect it sets a requesting event to tell the server ** that a client has connected. ** ** The names for the memory mapped file, the mutex, and the events are ** based on the server name. ** ** History: ** 10-Dec-98 (lunbr01) Bug 94183 ** Eliminate use of *Ct fields (using PeekNamedPipe instead). */ BOOL CreateAsc(ASSOC_IPC * asipc, char *name ) { HANDLE hMapping; /* for memory mapped file */ static HANDLE hMutex; /* for memory mapped file */ ASSOC_IPC *asipc_temp; ASSOC_INFO *assoc_info; struct _Asc_ipc_area *svr_ipc_area; SERVER_ENTRY *server; short i; SECURITY_ATTRIBUTES sa; /* Set up security attributes */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* If there are no existing connections to this server. Open the ** memory mapped file, events, and mutex for this server. */ if( NULL == ( server = LookUpServer( name ) ) ) { char ReqEventName[MAXPNAME + 4 ]; char LstEventName[MAXPNAME + 4 ]; if ((hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sizeof( struct _Asc_ipc_area ), name )) == NULL) { DWORD err = GetLastError( ); return FALSE ; } if (NULL == (svr_ipc_area= (struct _Asc_ipc_area *)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 ) ) ) { return FALSE; } /* Create an event that will be signaled when an ** association is requested. */ wsprintf( ReqEventName, "%s-%s", name, "req" ); wsprintf( LstEventName, "%s-%s", name, "lst" ); /* Create SERVER_ENTRY */ server = AddServer( name, svr_ipc_area, hMapping, CreateEvent( &sa, FALSE, FALSE, ReqEventName ), CreateEvent( &sa, FALSE, FALSE, LstEventName ) ); /* Create a mutex to coordinate access to asipc_temp */ hMutex = CreateMutex( &sa, FALSE, name ); /* Create a proces handle so other processes can use DuplicateHandle */ svr_ipc_area->nProcId = GetCurrentProcessId( ); } /* Get a pointer to the Memory mapped file for this server. */ svr_ipc_area = server->lpMapping; if ( server->nConnections == MAX_ASSOCS ) /* no more assocs allowed */ return FALSE ; asipc_temp = &( svr_ipc_area->asipc ); assoc_info = (ASSOC_INFO *)&( svr_ipc_area->assoc_info ); /* Make sure that it is safe to change temporary connection info. ** Copy the connection information the local ASSOC_IPC. */ WaitForSingleObject( hMutex, INFINITE ); /* Find a valid id and set up the assoc_info. */ for( i = 0; i < MAX_ASSOCS; i++ ) { if ( assoc_info[i].refs == 0 ) break; } asipc->IpcInternal.hMapping = hMapping; /* for save and restore */ asipc->IpcInternal.AssocInfo = &assoc_info[i]; asipc_temp->IpcInternal.AscID = asipc->IpcInternal.AscID = i; assoc_info[i].bPipesClosed = FALSE; assoc_info[i].refs++; /* Set the AssocInfo */ assoc_info[i].out_buffer_size = Pipe_buffer_size; assoc_info[i].in_buffer_size = Pipe_buffer_size; if(!CreatePipe( &asipc->RcvStdChan, &asipc_temp->SndStdChan, &sa, Pipe_buffer_size ) || !CreatePipe( &asipc_temp->RcvStdChan, &asipc->SndStdChan, &sa, Pipe_buffer_size ) || !CreatePipe( &asipc->RcvExpChan, &asipc_temp->SndExpChan, &sa, Pipe_buffer_size ) || !CreatePipe( &asipc_temp->RcvExpChan, &asipc->SndExpChan, &sa, Pipe_buffer_size ) ) { CloseAsc( asipc ); CloseAsc( asipc_temp ); return FALSE ; } /* We need to duplicate the client side of standard read handle asipc_temp->RcvStdChan for PeekNamedPipe() because it gets closed by the DUPLICATE_CLOSE_SOURCE option of DuplicateHandle() after a front end client connects to the server and duplicates it into their address space. */ if (!DuplicateHandle( GetCurrentProcess(), asipc_temp->RcvStdChan, GetCurrentProcess(), &asipc->ClientReadHandle, GENERIC_READ, TRUE, DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); CloseAsc( asipc_temp ); return FALSE ; } /* We need to duplicate the server side of standard read handle asipc->RcvStdChan for PeekNamedPipe() in the client because it gets closed by the DUPLICATE_CLOSE_SOURCE option of DuplicateHandle() after a front end client connects to the server and duplicates it into their address space. */ if (!DuplicateHandle( GetCurrentProcess(), asipc->RcvStdChan, GetCurrentProcess(), &asipc_temp->ClientReadHandle, GENERIC_READ, TRUE, DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); CloseAsc( asipc_temp ); return FALSE ; } ReleaseMutex( hMutex ); /* ** Set up pointer to server and increment the number of connections. */ asipc->IpcInternal.server = server; asipc->IpcInternal.server->nConnections++; 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; }
int TestPipeCreatePipe(int argc, char* argv[]) { BOOL status; DWORD dwRead; DWORD dwWrite; HANDLE hReadPipe; HANDLE hWritePipe; BYTE readBuffer[BUFFER_SIZE]; BYTE writeBuffer[BUFFER_SIZE]; status = CreatePipe(&hReadPipe, &hWritePipe, NULL, BUFFER_SIZE * 2); if (!status) { _tprintf(_T("CreatePipe failed\n")); return -1; } FillMemory(writeBuffer, sizeof(writeBuffer), 0xAA); status = WriteFile(hWritePipe, &writeBuffer, sizeof(writeBuffer), &dwWrite, NULL); if (!status) { _tprintf(_T("WriteFile failed\n")); return -1; } if (dwWrite != sizeof(writeBuffer)) { _tprintf(_T("WriteFile: unexpected number of bytes written: Actual: %ld, Expected: %ld\n"), dwWrite, (long int)sizeof(writeBuffer)); return -1; } ZeroMemory(readBuffer, sizeof(readBuffer)); status = ReadFile(hReadPipe, &readBuffer, sizeof(readBuffer), &dwRead, NULL); if (!status) { _tprintf(_T("ReadFile failed\n")); return -1; } if (dwRead != sizeof(readBuffer)) { _tprintf(_T("ReadFile: unexpected number of bytes read: Actual: %ld, Expected: %ld\n"), dwWrite, (long int)sizeof(readBuffer)); return -1; } if (memcmp(readBuffer, writeBuffer, BUFFER_SIZE) != 0) { _tprintf(_T("ReadFile: read buffer is different from write buffer\n")); return -1; } CloseHandle(hReadPipe); CloseHandle(hWritePipe); return 0; }
static NBBOOL session_attach_process(sessions_t *sessions, session_t *session, char *process) { #ifdef WIN32 STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; SECURITY_ATTRIBUTES sa; session_group_t *session_group = (session_group_t*) safe_malloc(sizeof(session_group_t)); session_group->session = session; session_group->sessions = sessions; /* Create a security attributes structure. This is required to inherit handles. */ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the anonymous pipes. */ if(!CreatePipe(&session->exec_stdin[PIPE_READ], &session->exec_stdin[PIPE_WRITE], &sa, 0)) nbdie("exec: Couldn't create pipe for stdin"); if(!CreatePipe(&session->exec_stdout[PIPE_READ], &session->exec_stdout[PIPE_WRITE], &sa, 0)) nbdie("exec: Couldn't create pipe for stdout"); fprintf(stderr, "Attempting to load the program: %s\n", process); /* Initialize the STARTUPINFO structure. */ ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); startupInfo.cb = sizeof(STARTUPINFO); startupInfo.dwFlags = STARTF_USESTDHANDLES; startupInfo.hStdInput = session->exec_stdin[PIPE_READ]; startupInfo.hStdOutput = session->exec_stdout[PIPE_WRITE]; if(!sessions->exec_no_stderr) startupInfo.hStdError = session->exec_stdout[PIPE_WRITE]; /* Initialize the PROCESS_INFORMATION structure. */ ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION)); /* Create the actual process with an overly-complicated CreateProcess function. */ if(!CreateProcessA(NULL, process, 0, &sa, TRUE, CREATE_NO_WINDOW, 0, NULL, &startupInfo, &processInformation)) { fprintf(stderr, "Failed to create the process"); exit(1); } /* Save the process id and the handle. */ session->pid = processInformation.dwProcessId; session->exec_handle = processInformation.hProcess; session->socket_id = --sessions->current_socket_id; /* Close the duplicate pipes we created -- this lets us detect the proicess termination. */ CloseHandle(session->exec_stdin[PIPE_READ]); CloseHandle(session->exec_stdout[PIPE_WRITE]); if(!sessions->exec_no_stderr) CloseHandle(session->exec_stdout[PIPE_WRITE]); fprintf(stderr, "Successfully created the process!\n\n"); /* On Windows, add the sub-process's stdout as a pipe. */ select_group_add_pipe(sessions->select_group, session->socket_id, session->exec_stdout[PIPE_READ], session_group); select_set_recv(sessions->select_group, session->socket_id, exec_callback); select_set_closed(sessions->select_group, session->socket_id, exec_closed_callback); #else session_group_t *session_group = (session_group_t*) safe_malloc(sizeof(session_group_t)); session_group->session = session; session_group->sessions = sessions; fprintf(stderr, "Attempting to start process '%s' for session %s\n", process, session->name); /* Create communication channels. */ if(pipe(session->exec_stdin) == -1) nbdie("exec: couldn't create pipe for STDIN"); if(pipe(session->exec_stdout) == -1) nbdie("exec: couldn't create pipe for STDOUT"); session->pid = fork(); if(session->pid == -1) nbdie("exec: couldn't create process"); if(session->pid == 0) { /* Copy the pipes. */ if(dup2(session->exec_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(session->exec_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(sessions->exec_no_stderr) { session->exec_stdout[PIPE_WRITE] = 0; } else { if(dup2(session->exec_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); } /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", process, (char*) NULL); /* If execlp returns, bad stuff happened. */ fprintf(stderr, "exec: execlp failed"); return FALSE; } fprintf(stderr, "Started: %s (pid: %d)\n", process, session->pid); close(session->exec_stdin[PIPE_READ]); close(session->exec_stdout[PIPE_WRITE]); /* On Linux, add the sub-process's stdout as a socket. */ select_group_add_socket(sessions->select_group, session->exec_stdout[PIPE_READ], SOCKET_TYPE_STREAM, session_group); select_set_recv(sessions->select_group, session->exec_stdout[PIPE_READ], exec_callback); select_set_closed(sessions->select_group, session->exec_stdout[PIPE_READ], exec_closed_callback); #endif return TRUE; }
static int rar_open(char *rarname, mode_t m, stream_t *stream) { stream_0day_priv_t *p; char RarTag[7], method, *pp, type = 0; WORD w, n, flag; int h = open(rarname, m); if (h < 0) return h; read(h, RarTag, 7); /* Read Rar!... Tag */ if (strncmp(RarTag, "Rar!", 4)) { lseek(h, 0, SEEK_SET); /* Not a RAR */ return h; } p = (stream_0day_priv_t*)malloc(sizeof(stream_0day_priv_t)); memset(p, 0, sizeof(stream_0day_priv_t)); p->headSize = 7; while (type != 0x74) { lseek(h, 2, SEEK_CUR); /* CRC */ read(h, &type, 1); /* Type */ read(h, (char*)&flag, 2); /* Flag */ read(h, (char*)&w, 2); /* Size */ p->headSize += w; if (type == 0x73) { /* main header */ p->naming = flag & 0x10; } else if (type == 0x74) { /* file header */ read(h, (char*)&(p->packSize), 4); read(h, (char*)&(p->fileSize), 4); lseek(h, 10, SEEK_CUR); /* Skip OS/CRC/Time/Ver */ read(h, &method, 1); /* Compression Method */ read(h, (char*)&n, 2); /* Size of rarname */ if (w == n + 0x2D) { /* fileSize is 64bit */ lseek(h, 8, SEEK_CUR); read(h, ((char*)&(p->fileSize))+4, 4); } else { lseek(h, 4, SEEK_CUR); /* Attr */ } p->filename = (char *)malloc(n + 1); read(h, p->filename, n); /* filename */ p->filename[n] = 0; } else if (type == 0x7A) { /* comment header */ read(h, (char*)&w, 2); /* Size of comment */ p->headSize += w; } lseek(h, p->headSize, SEEK_SET); /* Seek to next header */ } mp_msg(MSGT_STREAM,MSGL_INFO, "File Flags=%04x\tCompression Method=%x\n", flag, method); if (!(flag & 0x04) && (method == 0x30)) { /* 0day stream */ n = strlen(rarname); p->basename = strdup(rarname); if (p->naming) { p->naming = rarname + n - strrchr(rarname, 't') - 5; n -= (p->naming + 4); } else { n -= 3; } p->basename[n] = 0; close(h); h = open_0day_volume(p, 0); if (h < 0) { free(p->filename); free(p->basename); free(p); } else { /* reget packSize, avoid got the last volume's packSize */ type = 0; n = 7; lseek(h, 7, SEEK_SET); while (type != 0x74) { lseek(h, 2, SEEK_CUR); /* CRC */ read(h, &type, 1); /* Type */ read(h, (char*)&flag, 2); /* Flag */ read(h, (char*)&w, 2); /* Size */ n += w; if (type == 0x74) { /* file header */ read(h, (char*)&(p->packSize), 4); } else if (type == 0x7A) { /* comment header */ read(h, (char*)&w, 2); /* Size of comment */ n += w; } lseek(h, n, SEEK_SET); /* Seek to next header */ } stream->priv = (void*)p; stream->close = close_0day; stream->seek = seek_0day; stream->fill_buffer = fill_buffer_0day; stream->end_pos = p->fileSize; stream->type = STREAMTYPE_FILE; } return h; } free(p); if (unrardll) { /* rar stream */ struct RAROpenArchiveDataEx OpenArchiveData; struct RARHeaderDataEx HeaderData; HANDLE hPipeRead, hPipeWrite; int hArcData; memset(&OpenArchiveData,0,sizeof(OpenArchiveData)); OpenArchiveData.ArcName=rarname; OpenArchiveData.OpenMode=RAR_OM_EXTRACT; hArcData=(*RAROpenArchiveEx)(&OpenArchiveData); if (!OpenArchiveData.OpenResult) { HeaderData.CmtBuf=NULL; if (!(*RARReadHeaderEx)(hArcData,&HeaderData)) { if (HeaderData.Flags & 0x04) { /* Request password */ if (DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_PASSWORD), GetForegroundWindow(), unrar_pw_dlgproc) == IDOK) { (*RARSetPassword)(hArcData, pw); } else { close(h); h = -2; goto rar_open_break; } } if (CreatePipe(&hPipeRead, &hPipeWrite, 0, 0x10000)) { stream_rar_priv_t *p; (*RARSetCallback)(hArcData, unrar_callback, (int)hPipeWrite); p = (stream_rar_priv_t*)malloc(sizeof(stream_rar_priv_t)); p->filename = strdup(HeaderData.FileName); p->hArcData = hArcData; p->hPipeWrite = hPipeWrite; if (_beginthread((void (*)())unrar_thread, 0, (void*)p) != -1) { stream->priv = (void*)p; stream->close = close_rar; close(h); return (int)hPipeRead; } else { free(p->filename); free(p); CloseHandle(hPipeRead); CloseHandle(hPipeWrite); } } } rar_open_break: (*RARCloseArchive)(hArcData); } } return h; }
// // Invoke() // // invoke the GIB program and return the recommended play // int CGIB::Invoke(CPlayer* pPlayer, CHandHoldings* pHand, CHandHoldings* pDummyHand, CPlayerStatusDialog* pStatusDlg) { SECURITY_ATTRIBUTES saAttr; // // create the GIB monitor dialog // CGIBDialog gibDialog(pMAINFRAME); int nProcessingTime = theApp.GetValue(tnGIBAnalysisTime); gibDialog.m_nProcessTime = nProcessingTime; // gibDialog.m_hEventCancel = m_hEventCancel; // Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // // create input and output pipes for the child process // // Create a pipe for the child process's STDOUT. if (!CreatePipe(&m_hChildStdoutRd, // returns the pipe's input handle &m_hChildStdoutWr, // returns the pipe's output handle &saAttr, 0)) { CString strError = "Stdout pipe creation failed\n"; TRACE(strError); pMAINFRAME->SetGIBMonitorText(strError); return ExitGracefully(-5); } // then create a pipe for the child process's STDIN. if (!CreatePipe(&m_hChildStdinRd, &m_hChildStdinWr, &saAttr, 0)) { CString strError = "Stdin pipe creation failed\n"; TRACE(strError); pMAINFRAME->SetGIBMonitorText(strError); return ExitGracefully(-5); } // // Now create the child process (GIB) // PROCESS_INFORMATION piProcInfo; if (!LaunchProgram(piProcInfo)) { TRACE("Create process failed"); return ExitGracefully(-1); } HANDLE hGIBProcess = piProcInfo.hProcess; DWORD nGIBProcessID = piProcInfo.dwProcessId; // now close the readable handle to the child's stdin SafeCloseHandle(m_hChildStdinRd); // and the writable handle to the child's stdout SafeCloseHandle(m_hChildStdoutWr); // //------------------------------------------------------------------ // // create the GIB input file // CFile file; CFileException fileException; CString strTempFile, strTempPath; GetTempPath(1024, strTempPath.GetBuffer(1024)); strTempPath.ReleaseBuffer(); GetTempFileName(strTempPath, "ezb", 0, strTempFile.GetBuffer(2048)); strTempFile.ReleaseBuffer(); // strTempFile.Format("%s\\%s", theApp.GetValueString(tszProgramDirectory), tszGIBTempFilename); /* LPTSTR szBuffer = strTempFile.GetBuffer(MAX_PATH); GetTempFileName(theApp.GetValueString(tszProgramDirectory), "ezb", 0, szBuffer); strTempFile.ReleaseBuffer(); */ // CString strInput; // strInput.Format("-T %d %s\n",theApp.GetValue(tnGIBAnalysisTime),strTempFile); int nCode = file.Open(strTempFile, CFile::modeWrite | CFile::modeCreate | CFile::shareDenyWrite, &fileException); if (nCode == 0) { CString strError = "Error opening temporary input file for GIB"; TRACE(strError); pMAINFRAME->SetGIBMonitorText(strError); return ExitGracefully(-2); } // CString strFileContents; CreateGIBInputFile(file, pPlayer, pHand, pDummyHand, strFileContents); file.Close(); // then send the parameters line CString strParameters, strShortParameters; strParameters.Format("-T %d %s\n",nProcessingTime,strTempFile); strShortParameters.Format("-T %d",nProcessingTime); DWORD dwWritten; int nErrCode; if (!WriteFile(m_hChildStdinWr, (LPCTSTR)strParameters, strParameters.GetLength(), &dwWritten, NULL)) { CString strError = "Error providing parameters to GIB"; TRACE(strError); pMAINFRAME->SetGIBMonitorText(strError); nErrCode = GetLastError(); return ExitGracefully(-3); } // // update the GIB monitor window // CString strGIBText = "========================================\n"; strGIBText += FormString("Launching %s %s\n", theApp.GetValueString(tszGIBPath), strShortParameters); // strGIBText += FormString("Input file contents:\n%s", strFileContents); strGIBText += "Awaiting Responses...\n"; strGIBText += "----------------------------------------\n"; // pMAINFRAME->SetGIBMonitorText(strGIBText); pMAINFRAME->AppendGIBMonitorText(strGIBText); // //------------------------------------------------------------ // // now set up the wait loop and the cancel dialog, // then sit and wait for the process to run or for a cancel message // /* // // create the "Cancel GIB" dialog thread // (this is a user interface thread) // CGIBMonitorThread* pMonitorThread = new CGIBMonitorThread(m_hEventFinished, m_hEventCancel, nProcessingTime); pMonitorThread->CreateThread(CREATE_SUSPENDED); pMonitorThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL); pMonitorThread->ResumeThread(); // wait for the monitor thread to initialize DWORD nCode0 = WaitForSingleObject(m_hEventFinished, INFINITE); */ // // create the wait thread // (this is a worker thread) // GIBStruct gibData; gibData.hReadHandle = m_hChildStdoutRd; gibData.pGIBDialog = &gibDialog; CWinThread* pWaitThread = AfxBeginThread(CGIB::ReadGIBOutput, &gibData, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); // copy its handle se that we can check its exit code later HANDLE hWaitThread; BOOL bCode = ::DuplicateHandle(GetCurrentProcess(), pWaitThread->m_hThread, GetCurrentProcess(), &hWaitThread, 0, FALSE, DUPLICATE_SAME_ACCESS); // and launch the threads // MonitorThread->ResumeThread(); pWaitThread->ResumeThread(); // // Show the Wait/Cancel dialog // m_bGIBPending = TRUE; // mark dialog as active bCode = gibDialog.DoModal(); // see if the user cancelled if (!bCode) { /* // lock out the wait thread and cancel operations if (ClearGIBPending()) { */ // pMAINFRAME->SetStatusText("GIB cancelled."); // TerminateProcess(hGIBProcess, 0); TerminateThread(hWaitThread, 0); // wait for the read thread to end WaitForSingleObject(hWaitThread, INFINITE); // close the wait thread handle CloseHandle(hWaitThread); CloseHandle(hGIBProcess); // and delete the thread object delete pWaitThread; // close pipe handles SafeCloseHandle(m_hChildStdinWr); SafeCloseHandle(m_hChildStdoutRd); // and throw an exception throw CGIBException(); // } } /* // set up events HANDLE eventArray[2]; eventArray[0] = m_hEventCancel; eventArray[1] = pWaitThread->m_hThread; // // then sit back and wait for the thread(s) // for(;;) { // wait for the cancelled or finished messages DWORD nCode = WaitForMultipleObjects(2, // 2 events to wait for eventArray, // events array FALSE, // not all at once INFINITE); // wait 4-ever // if (nCode == WAIT_FAILED) { ASSERT(FALSE); break; } else if (nCode == WAIT_OBJECT_0) { // got the cancel message, so kill GIB & the wait thread // the following is very dangersous -- // so kids, don't try this at home TerminateThread(pWaitThread, 0); TerminateProcess(hGIBProcess, 0); return GIB_CANCEL; } else if (nCode == WAIT_OBJECT_0 + 1) { // GIB finished message // signal the GIB monitor that GIB has finished SetEvent(m_hEventFinished); break; } } */ // //------------------------------------------------------------ // // presumably, GIB has finished running // // wait for the GIB thread to exit, then get the card code DWORD nCardPlayed, nErrorCode; bCode = WaitForSingleObject(hWaitThread, INFINITE); bCode = GetExitCodeThread(hWaitThread, &nCardPlayed); if (!bCode) nErrorCode = GetLastError(); // close the wait thread handle CloseHandle(hWaitThread); // delete the temporary file DeleteFile(strTempFile); // and kill the child process // first send a Ctrl-C to the app // (this doesn't seem to do anything) CString strInput = "\03"; // Ctrl-C if (!WriteFile(m_hChildStdinWr, (LPCTSTR)strInput, strInput.GetLength(), &dwWritten, NULL)) { CString strError = "Error stopping GIB"; TRACE(strError); pMAINFRAME->SetGIBMonitorText(strError); nErrCode = GetLastError(); return ExitGracefully(-4); } // close the writable handle to the child's stdin SafeCloseHandle(m_hChildStdinWr); // then call terminateProcess TerminateProcess(hGIBProcess, 0); CloseHandle(hGIBProcess); // then close the readable handle to the child's stdout SafeCloseHandle(m_hChildStdoutRd); // // done // return nCardPlayed; }
int get_exec_pipes (char *cmd, int *fdIn, int *fdOut, netsnmp_pid_t * pid) { /* Alexander Prömel, [email protected] 08/24/2006 The following code, is tested on picotux rev. 1.01. I think, it will be better to put the named pipes, into /var/run or make it selectable via CONFIG file. If the pipe file already exist, the creation will fail. I put the pipes into /flash, the pipepath has to change in ucd-snmp/pass_persist.c too, if you change it here. */ #if HAVE_EXECV #ifdef __uClinux__ /* HAVE uClinux */ int in, out; char fifo_in_path[256]; char fifo_out_path[256]; pid_t tpid; if ((tpid = vfork ()) == 0) { /*temp child */ execve (cmd, NULL, NULL); perror (cmd); exit (1); } else { if (tpid > 0) { /*initialize workspace */ snprintf (fifo_in_path, 256, "/flash/cp_%d", tpid); snprintf (fifo_out_path, 256, "/flash/pc_%d", tpid); in = mkfifo (fifo_in_path, S_IRWXU); /*Create Input Pipe, 700 */ if (in) { perror ("parent: inpipe"); exit (0); } out = mkfifo (fifo_out_path, S_IRWXU); /*Create Output Pipe, 700 */ if (out) { perror ("parent: outpipe"); exit (0); } in = open (fifo_in_path, O_RDONLY); /*open the Input Pipe read Only */ if (in < 0) { perror ("parent: input"); exit (0); } out = open (fifo_out_path, O_WRONLY); /*open the Output Pipe write Only */ if (out < 0) { perror ("parent: output"); exit (0); } *fdIn = in; /*read */ *fdOut = out; /*write */ *pid = tpid; return (1); /* We are returning 0 for error... */ } else { /*pid < 0 */ setPerrorstatus ("vfork"); return 0; } } #else /*HAVE x86 */ int fd[2][2], i, cnt; char ctmp[STRMAX], *cptr1, *cptr2, argvs[STRMAX], **argv, **aptr; /* * Setup our pipes */ if (pipe (fd[0]) || pipe (fd[1])) { setPerrorstatus ("pipe"); return 0; } if ((*pid = fork ()) == 0) { /* First handle for the child */ close (0); if (dup (fd[0][0]) != 0) { setPerrorstatus ("dup 0"); return 0; } close (1); if (dup (fd[1][1]) != 1) { setPerrorstatus ("dup 1"); return 0; } /* * write standard output and standard error to pipe. */ /* * close all non-standard open file descriptors */ for (cnt = getdtablesize () - 1; cnt >= 2; --cnt) (void) close (cnt); (void) dup (1); /* stderr */ for (cnt = 1, cptr1 = cmd, cptr2 = argvs; *cptr1 != 0; cptr2++, cptr1++) { *cptr2 = *cptr1; if (*cptr1 == ' ') { *(cptr2++) = 0; if ((cptr1 = skip_white (cptr1)) == NULL) break; *cptr2 = *cptr1; if (*cptr1 != 0) cnt++; } } *cptr2 = 0; *(cptr2 + 1) = 0; argv = (char **) malloc ((cnt + 2) * sizeof (char *)); if (argv == NULL) return 0; /* memory alloc error */ aptr = argv; *(aptr++) = argvs; for (cptr2 = argvs, i = 1; i != cnt; cptr2++) if (*cptr2 == 0) { *(aptr++) = cptr2 + 1; i++; } while (*cptr2 != 0) cptr2++; *(aptr++) = NULL; copy_nword (cmd, ctmp, sizeof (ctmp)); execv (ctmp, argv); perror (ctmp); exit (1); } else { close (fd[0][0]); close (fd[1][1]); if (*pid < 0) { close (fd[0][1]); close (fd[1][0]); setPerrorstatus ("fork"); return 0; } *fdIn = fd[1][0]; *fdOut = fd[0][1]; return (1); /* We are returning 0 for error... */ } #endif /* uClinux or x86 */ #endif /* !HAVE_EXECV */ #if defined(WIN32) && !defined (mingw32) && !defined(HAVE_EXECV) /* MSVC (MinGW not working but should use this code). Cygwin already works as it has execv and fork */ /* Reference: MS tech note: 190351 */ HANDLE hInputWriteTmp, hInputRead, hInputWrite = NULL; HANDLE hOutputReadTmp, hOutputRead, hOutputWrite = NULL; HANDLE hErrorWrite; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Child temporary output pipe with Inheritance on (sa.bInheritHandle is true) */ if (!CreatePipe (&hOutputReadTmp, &hOutputWrite, &sa, 0)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CreatePipe ChildOut: %d\n", GetLastError ())); return 0; } /* Child temporary input pipe with Inheritance on (sa.bInheritHandle is true) */ if (!CreatePipe (&hInputRead, &hInputWriteTmp, &sa, 0)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CreatePipe ChildIn: %d\n", GetLastError ())); return 0; } /* Copy the stdout handle to the stderr handle in case the child closes one of * its stdout handles. */ if (!DuplicateHandle (GetCurrentProcess (), hOutputWrite, GetCurrentProcess (), &hErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes DuplicateHandle: %d\n", GetLastError ())); return 0; } /* Create new copies of the input and output handles but set bInheritHandle to * FALSE so the new handle can not be inherited. Otherwise the handles can not * be closed. */ if (!DuplicateHandle (GetCurrentProcess (), hOutputReadTmp, GetCurrentProcess (), &hOutputRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes DupliateHandle ChildOut: %d\n", GetLastError ())); CloseHandle (hErrorWrite); return 0; } if (!DuplicateHandle (GetCurrentProcess (), hInputWriteTmp, GetCurrentProcess (), &hInputWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes DupliateHandle ChildIn: %d\n", GetLastError ())); CloseHandle (hErrorWrite); CloseHandle (hOutputRead); return 0; } /* Close the temporary output and input handles */ if (!CloseHandle (hOutputReadTmp)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CloseHandle (hOutputReadTmp): %d\n", GetLastError ())); CloseHandle (hErrorWrite); CloseHandle (hOutputRead); CloseHandle (hInputWrite); return 0; } if (!CloseHandle (hInputWriteTmp)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CloseHandle (hInputWriteTmp): %d\n", GetLastError ())); CloseHandle (hErrorWrite); CloseHandle (hOutputRead); CloseHandle (hInputWrite); return 0; } /* Associates a C run-time file descriptor with an existing operating-system file handle. */ *fdIn = _open_osfhandle ((long) hOutputRead, 0); *fdOut = _open_osfhandle ((long) hInputWrite, 0); /* Set up STARTUPINFO for CreateProcess with the handles and have it hide the window * for the new process. */ ZeroMemory (&si, sizeof (STARTUPINFO)); si.cb = sizeof (STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdOutput = hOutputWrite; si.hStdInput = hInputRead; si.hStdError = hErrorWrite; si.wShowWindow = SW_HIDE; /* Launch the process that you want to redirect. Example snmpd.conf pass_persist: * pass_persist .1.3.6.1.4.1.2021.255 c:/perl/bin/perl c:/temp/pass_persisttest */ if (!CreateProcess (NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CreateProcess:'%s' %d\n", cmd, GetLastError ())); CloseHandle (hErrorWrite); CloseHandle (hOutputRead); CloseHandle (hInputWrite); return 0; } DEBUGMSGTL (("util_funcs", "child hProcess (stored in pid): %d\n", (int) pi.hProcess)); DEBUGMSGTL (("util_funcs", "child dwProcessId (task manager): %d\n", (int) pi.dwProcessId)); /* Set global child process handle */ *pid = pi.hProcess; /* Cleanup */ if (!CloseHandle (pi.hThread)) DEBUGMSGTL (("util_funcs", "get_exec_pipes CloseHandle pi.hThread: %d\n", cmd)); /* Close pipe handles 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 any calls to ReadFile * will hang. */ if (!CloseHandle (hOutputWrite)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CloseHandle hOutputWrite: %d\n", cmd, GetLastError ())); return 0; } if (!CloseHandle (hInputRead)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CloseHandle hInputRead: %d\n", cmd, GetLastError ())); return 0; } if (!CloseHandle (hErrorWrite)) { DEBUGMSGTL (("util_funcs", "get_exec_pipes CloseHandle hErrorWrite: %d\n", cmd, GetLastError ())); return 0; } return 1; #endif /* WIN32 */ return 0; }
int main(VOID) { HANDLE ReadHandle, WriteHandle; STARTUPINFO si; PROCESS_INFORMATION pi; char message[BUFFER_SIZE] = "Greetings"; DWORD written; /* set up security attributes so that pipe handles are inherited */ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL,TRUE}; /* allocate memory */ ZeroMemory(&pi, sizeof(pi)); /* create the pipe */ if ( !CreatePipe(&ReadHandle, &WriteHandle, &sa, 0)) { fprintf(stderr,"Create Pipe Failed\n"); return 1; } /* establish the START_INFO structure for the child process */ GetStartupInfo(&si); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); /* redirect the standard input to the read end of the pipe */ si.hStdInput = ReadHandle; si.dwFlags = STARTF_USESTDHANDLES; /* we do not want the child to inherit the write end of the pipe */ SetHandleInformation( WriteHandle, HANDLE_FLAG_INHERIT, 0); /* create the child process */ if (!CreateProcess(NULL, ".\\child.exe", NULL, NULL, TRUE, /* inherit handles */ 0, NULL, NULL, &si, &pi)) { fprintf(stderr, "Process Creation Failed\n"); return -1; } /* close the unused end of the pipe */ CloseHandle(ReadHandle); /* the parent now wants to write to the pipe */ if (!WriteFile (WriteHandle, message, BUFFER_SIZE, &written, NULL)) fprintf(stderr, "Error writing to pipe\n"); /* close the write end of the pipe */ CloseHandle(WriteHandle); /* wait for the child to exit */ WaitForSingleObject(pi.hProcess, INFINITE); /* close all handles */ CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
/* Start child program with redirected standard input and output */ int ijs_exec_server(const char *server_cmd, int *pfd_to, int *pfd_from, int *pchild_pid) { SECURITY_ATTRIBUTES saAttr; STARTUPINFO siStartInfo; LPVOID env; HANDLE hPipeTemp; HANDLE hChildStdinRd = INVALID_HANDLE_VALUE; HANDLE hChildStdinWr = INVALID_HANDLE_VALUE; HANDLE hChildStdoutRd = INVALID_HANDLE_VALUE; HANDLE hChildStdoutWr = INVALID_HANDLE_VALUE; PROCESS_INFORMATION piProcInfo; BOOL flag; int fd_stdin_wr = -1; int fd_stdout_rd = -1; /* Set the bInheritHandle flag so pipe handles are inherited. */ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* Create anonymous inheritable pipes for STDIN and STDOUT * for child. For each pipe, create a noninheritable duplicate handle * of our end of the pipe, then close the inheritable handle. * Do not redirect STDERR. */ flag = CreatePipe(&hChildStdinRd, &hPipeTemp, &saAttr, 0); if (flag) { flag = DuplicateHandle(GetCurrentProcess(), hPipeTemp, GetCurrentProcess(), &hChildStdinWr, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); CloseHandle(hPipeTemp); } if (flag) flag = CreatePipe(&hPipeTemp, &hChildStdoutWr, &saAttr, 0); if (flag) { flag = DuplicateHandle(GetCurrentProcess(), hPipeTemp, GetCurrentProcess(), &hChildStdoutRd, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); CloseHandle(hPipeTemp); } if (flag) flag = (fd_stdin_wr = _open_osfhandle((LONG)hChildStdinWr, 0)) != -1; if (flag) flag = (fd_stdout_rd = _open_osfhandle((LONG)hChildStdoutRd, 0)) != -1; /* Now create the child process. */ if (flag) { /* Set up members of STARTUPINFO structure. */ siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.lpReserved = NULL; siStartInfo.lpDesktop = NULL; siStartInfo.lpTitle = NULL; /* use executable name as title */ siStartInfo.dwX = siStartInfo.dwY = CW_USEDEFAULT; /* ignored */ siStartInfo.dwXSize = siStartInfo.dwYSize = CW_USEDEFAULT;/* ignored */ siStartInfo.dwXCountChars = 80; siStartInfo.dwYCountChars = 25; siStartInfo.dwFillAttribute = 0; /* ignored */ siStartInfo.dwFlags = STARTF_USESTDHANDLES; #ifdef VERBOSE siStartInfo.wShowWindow = SW_SHOWNORMAL; siStartInfo.dwFlags |= STARTF_USESHOWWINDOW; #else siStartInfo.wShowWindow = SW_HIDE; #endif siStartInfo.cbReserved2 = 0; siStartInfo.lpReserved2 = NULL; siStartInfo.hStdInput = hChildStdinRd; siStartInfo.hStdOutput = hChildStdoutWr; siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); env = NULL; /* Create the child process. */ flag = CreateProcess(server_cmd, NULL, /* command line */ NULL, /* process security attributes */ NULL, /* primary thread security attributes */ TRUE, /* handles are inherited */ 0, /* creation flags */ env, /* environment */ NULL, /* use parent's current directory */ &siStartInfo, /* STARTUPINFO pointer */ &piProcInfo); /* receives PROCESS_INFORMATION */ if (flag) { CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); } } if (hChildStdinRd != INVALID_HANDLE_VALUE) CloseHandle(hChildStdinRd); if (hChildStdoutWr != INVALID_HANDLE_VALUE) CloseHandle(hChildStdoutWr); if (flag) { *pfd_to = fd_stdin_wr; *pfd_from = fd_stdout_rd; *pchild_pid = (int)piProcInfo.dwProcessId; } else { if (fd_stdin_wr != -1) close(fd_stdin_wr); else if (hChildStdinWr != INVALID_HANDLE_VALUE) CloseHandle(hChildStdinWr); if (fd_stdout_rd != -1) close(fd_stdout_rd); else if (hChildStdoutRd != INVALID_HANDLE_VALUE) CloseHandle(hChildStdoutRd); return -1; } return flag ? 0 : -1; }
bool PipeWindows::init(const string &enginePath) { initialized = false; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = true; saAttr.lpSecurityDescriptor = NULL; if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) { fatal("StdoutRd CreatePipe"); return initialized; } if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { fatal("Stdout SetHandleInformation"); return initialized; } if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) { fatal("StdoutRd err CreatePipe"); return initialized; } if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { fatal("Stderr SetHandleInformation"); return initialized; } if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) { fatal("Stdin CreatePipe"); return initialized; } if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) { fatal("Stdin SetHandleInformation"); return initialized; } /////////// TCHAR szCmdline[1024]; strcpy(szCmdline, enginePath.c_str()); PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; bool bSuccess = false; ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = g_hChildStd_ERR_Wr; siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; siStartInfo.hStdInput = g_hChildStd_IN_Rd; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; bSuccess = CreateProcess(NULL, szCmdline, // command line NULL, // process security attributes NULL, // primary thread security attributes true, // handles are inherited 0, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo); // receives PROCESS_INFORMATION if (bSuccess) { CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); } initialized = true; return initialized; }