/* * Setup and run the server. This is called from Init via the loader. */ DWORD server_setup( SOCKET fd ) { Remote * remote = NULL; char cStationName[256] = {0}; char cDesktopName[256] = {0}; DWORD res = 0; dprintf("[SERVER] Initializing..."); #ifdef _UNIX int local_error = 0; #endif // if hAppInstance is still == NULL it means that we havent been // reflectivly loaded so we must patch in the hAppInstance value // for use with loading server extensions later. InitAppInstance(); srand( (unsigned int)time(NULL) ); __try { do { dprintf( "[SERVER] module loaded at 0x%08X", hAppInstance ); // Open a THREAD item for the servers main thread, we use this to manage migration later. serverThread = thread_open(); dprintf( "[SERVER] main server thread: handle=0x%08X id=0x%08X sigterm=0x%08X", serverThread->handle, serverThread->id, serverThread->sigterm ); if( !(remote = remote_allocate(fd)) ) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); break; } // Do not allow the file descriptor to be inherited by child processes SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); dprintf("[SERVER] Initializing tokens..."); // Store our thread handle remote->hServerThread = serverThread->handle; #ifdef _WIN32 // Store our process token if (!OpenThreadToken(remote->hServerThread, TOKEN_ALL_ACCESS, TRUE, &remote->hServerToken)) OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &remote->hServerToken); // Copy it to the thread token remote->hThreadToken = remote->hServerToken; // Save the initial session/station/desktop names... remote->dwOrigSessionId = server_sessionid(); remote->dwCurrentSessionId = remote->dwOrigSessionId; GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &cStationName, 256, NULL ); remote->cpOrigStationName = _strdup( cStationName ); remote->cpCurrentStationName = _strdup( cStationName ); GetUserObjectInformation( GetThreadDesktop( GetCurrentThreadId() ), UOI_NAME, &cDesktopName, 256, NULL ); remote->cpOrigDesktopName = _strdup( cDesktopName ); remote->cpCurrentDesktopName = _strdup( cDesktopName ); #endif dprintf("[SERVER] Flushing the socket handle..."); server_socket_flush( remote ); dprintf("[SERVER] Initializing SSL..."); if( !server_initialize_ssl( remote ) ) break; dprintf("[SERVER] Negotiating SSL..."); if( !server_negotiate_ssl( remote ) ) break; dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); dprintf("[SERVER] Entering the main server dispatch loop..."); server_dispatch( remote ); dprintf("[SERVER] Deregistering dispatch routines..."); deregister_dispatch_routines(); } while (0); dprintf("[SERVER] Closing down SSL..."); server_destroy_ssl( remote ); if( remote ) remote_deallocate( remote ); } __except( exceptionfilter(GetExceptionCode(), GetExceptionInformation()) ) { dprintf("[SERVER] *** exception triggered!"); thread_kill( serverThread ); } dprintf("[SERVER] Finished."); return res; }
// Returns -1 if we could not make the socket pair successfully int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_) { #if defined ZMQ_HAVE_EVENTFD fd_t fd = eventfd (0, 0); if (fd == -1) { errno_assert (errno == ENFILE || errno == EMFILE); *w_ = *r_ = -1; return -1; } else { *w_ = *r_ = fd; return 0; } #elif defined ZMQ_HAVE_WINDOWS # if !defined _WIN32_WCE // Windows CE does not manage security attributes SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; memset (&sd, 0, sizeof (sd)); memset (&sa, 0, sizeof (sa)); InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = &sd; # endif // This function has to be in a system-wide critical section so that // two instances of the library don't accidentally create signaler // crossing the process boundary. // We'll use named event object to implement the critical section. // Note that if the event object already exists, the CreateEvent requests // EVENT_ALL_ACCESS access right. If this fails, we try to open // the event object asking for SYNCHRONIZE access only. HANDLE sync = NULL; // Create critical section only if using fixed signaler port // Use problematic Event implementation for compatibility if using old port 5905. // Otherwise use Mutex implementation. int event_signaler_port = 5905; if (signaler_port == event_signaler_port) { # if !defined _WIN32_WCE sync = CreateEvent (&sa, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync")); # else sync = CreateEvent (NULL, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync")); # endif if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED) sync = OpenEvent (SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, TEXT ("Global\\zmq-signaler-port-sync")); win_assert (sync != NULL); } else if (signaler_port != 0) { TCHAR mutex_name[64]; _stprintf (mutex_name, TEXT ("Global\\zmq-signaler-port-%d"), signaler_port); # if !defined _WIN32_WCE sync = CreateMutex (&sa, FALSE, mutex_name); # else sync = CreateMutex (NULL, FALSE, mutex_name); # endif if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED) sync = OpenMutex (SYNCHRONIZE, FALSE, mutex_name); win_assert (sync != NULL); } // Windows has no 'socketpair' function. CreatePipe is no good as pipe // handles cannot be polled on. Here we create the socketpair by hand. *w_ = INVALID_SOCKET; *r_ = INVALID_SOCKET; // Create listening socket. SOCKET listener; listener = open_socket (AF_INET, SOCK_STREAM, 0); wsa_assert (listener != INVALID_SOCKET); // Set SO_REUSEADDR and TCP_NODELAY on listening socket. BOOL so_reuseaddr = 1; int rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR, (char *)&so_reuseaddr, sizeof (so_reuseaddr)); wsa_assert (rc != SOCKET_ERROR); BOOL tcp_nodelay = 1; rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, (char *)&tcp_nodelay, sizeof (tcp_nodelay)); wsa_assert (rc != SOCKET_ERROR); // Init sockaddr to signaler port. struct sockaddr_in addr; memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); addr.sin_port = htons (signaler_port); // Create the writer socket. *w_ = open_socket (AF_INET, SOCK_STREAM, 0); wsa_assert (*w_ != INVALID_SOCKET); // Set TCP_NODELAY on writer socket. rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, (char *)&tcp_nodelay, sizeof (tcp_nodelay)); wsa_assert (rc != SOCKET_ERROR); if (sync != NULL) { // Enter the critical section. DWORD dwrc = WaitForSingleObject (sync, INFINITE); zmq_assert (dwrc == WAIT_OBJECT_0 || dwrc == WAIT_ABANDONED); } // Bind listening socket to signaler port. rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr)); if (rc != SOCKET_ERROR && signaler_port == 0) { // Retrieve ephemeral port number int addrlen = sizeof (addr); rc = getsockname (listener, (struct sockaddr*) &addr, &addrlen); } // Listen for incoming connections. if (rc != SOCKET_ERROR) rc = listen (listener, 1); // Connect writer to the listener. if (rc != SOCKET_ERROR) rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr)); // Accept connection from writer. if (rc != SOCKET_ERROR) *r_ = accept (listener, NULL, NULL); // Save errno if error occurred in bind/listen/connect/accept. int saved_errno = 0; if (*r_ == INVALID_SOCKET) saved_errno = WSAGetLastError (); // We don't need the listening socket anymore. Close it. closesocket (listener); if (sync != NULL) { // Exit the critical section. BOOL brc; if (signaler_port == event_signaler_port) brc = SetEvent (sync); else brc = ReleaseMutex (sync); win_assert (brc != 0); // Release the kernel object brc = CloseHandle (sync); win_assert (brc != 0); } if (*r_ != INVALID_SOCKET) { # if !defined _WIN32_WCE // On Windows, preventing sockets to be inherited by child processes. BOOL brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0); win_assert (brc); # endif return 0; } else { // Cleanup writer if connection failed if (*w_ != INVALID_SOCKET) { rc = closesocket (*w_); wsa_assert (rc != SOCKET_ERROR); *w_ = INVALID_SOCKET; } // Set errno from saved value errno = wsa_error_to_errno (saved_errno); return -1; } #elif defined ZMQ_HAVE_OPENVMS // Whilst OpenVMS supports socketpair - it maps to AF_INET only. Further, // it does not set the socket options TCP_NODELAY and TCP_NODELACK which // can lead to performance problems. // // The bug will be fixed in V5.6 ECO4 and beyond. In the meantime, we'll // create the socket pair manually. struct sockaddr_in lcladdr; memset (&lcladdr, 0, sizeof (lcladdr)); lcladdr.sin_family = AF_INET; lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); lcladdr.sin_port = 0; int listener = open_socket (AF_INET, SOCK_STREAM, 0); errno_assert (listener != -1); int on = 1; int rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)); errno_assert (rc != -1); rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on)); errno_assert (rc != -1); rc = bind (listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr)); errno_assert (rc != -1); socklen_t lcladdr_len = sizeof (lcladdr); rc = getsockname (listener, (struct sockaddr*) &lcladdr, &lcladdr_len); errno_assert (rc != -1); rc = listen (listener, 1); errno_assert (rc != -1); *w_ = open_socket (AF_INET, SOCK_STREAM, 0); errno_assert (*w_ != -1); rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)); errno_assert (rc != -1); rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on)); errno_assert (rc != -1); rc = connect (*w_, (struct sockaddr*) &lcladdr, sizeof (lcladdr)); errno_assert (rc != -1); *r_ = accept (listener, NULL, NULL); errno_assert (*r_ != -1); close (listener); return 0; #else // All other implementations support socketpair() int sv [2]; int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv); if (rc == -1) { errno_assert (errno == ENFILE || errno == EMFILE); *w_ = *r_ = -1; return -1; } else { *w_ = sv [0]; *r_ = sv [1]; return 0; } #endif }
/// Do 'execute' instruction. /// /// \param sCommand_line fully command line, after modify /// /// Return AGENT_RET_SUCCESS if succeed, or AGENT_RET_FAIL if fail static MBA_AGENT_RETURN execute_cmd(char *sCmdline) { // Child : hOutputWrite, hInputRead, hErrorWrite // Parent : hOutputRead, hInputWrite HANDLE hOutputRead, hOutputWrite; HANDLE hInputRead, hInputWrite; HANDLE hErrorWrite; // Thread handler HANDLE hThread; DWORD dTid; DWORD dEndSize = 0; WSAPROTOCOL_INFO protoInfo; SECURITY_ATTRIBUTES pipeAttr; // Set up the security attributes struct. pipeAttr.nLength = sizeof(SECURITY_ATTRIBUTES); pipeAttr.lpSecurityDescriptor = NULL; pipeAttr.bInheritHandle = TRUE; // Create the child output pipe. if (!CreatePipe(&hOutputRead, &hOutputWrite, &pipeAttr, 0)) { display_error("execute_cmd - CreatePipe", TRUE); return AGENT_RET_FAIL; } // Create a duplicate of the output write handle for the std error write handle. // This is necessary in case the child application closes one of its std output handles. if ( !DuplicateHandle( GetCurrentProcess(), hOutputWrite, GetCurrentProcess(), &hErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS) ) { display_error("execute_cmd - DuplicateHandle : hErrorWrite -> hOutputWrite", TRUE); return AGENT_RET_FAIL; } // Create the child input pipe. if ( !CreatePipe( &hInputRead, &hInputWrite, &pipeAttr,0) ){ display_error("execute_cmd - CreatePipe", TRUE); return AGENT_RET_FAIL; } // Ensure the handle for reading from child stdout pipe is not inherited if ( !SetHandleInformation( hOutputRead, HANDLE_FLAG_INHERIT, 0) ) { display_error("execute_cmd - SetHandleInformation : Child read", TRUE); return AGENT_RET_FAIL; } // Ensure the handle for writing to child stdin pipe is not inherited if ( !SetHandleInformation( hInputWrite, HANDLE_FLAG_INHERIT, 0) ) { display_error("execute_cmd - SetHandleInformation : Child write", TRUE); return AGENT_RET_FAIL; } // Sets up STARTUPINFO structure, and launches redirected child. prep_and_launch_redirected_child(sCmdline, hOutputWrite, hInputRead, hErrorWrite); // Close pipe handles (do not continue to modify in the parent). if (!CloseHandle(hOutputWrite)) { display_error("execute_cmd - CloseHandle : Child Write", TRUE); return AGENT_RET_FAIL; } if (!CloseHandle(hInputRead)) { display_error("execute_cmd - CloseHandle : Child Read", TRUE); return AGENT_RET_FAIL; } if (!CloseHandle(hErrorWrite)) { display_error("execute_cmd - CloseHandle : Child Error", TRUE); return AGENT_RET_FAIL; } // Duplicate ClientSocket for thread WSADuplicateSocket( g_sClientSocket, GetCurrentProcessId(), &protoInfo ); g_sClientDupSocket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, &protoInfo, 0, 0 ); if( g_sClientDupSocket == INVALID_SOCKET ) { display_error("execute_cmd - WSASocket : Dup ClientSocket", TRUE ); return AGENT_RET_FAIL; } // Launch the thread that gets the input and sends it to the child. hThread = CreateThread( NULL, // a pointer to a SECURITY_ATTRIBUTES structure 0, // the initial size of the stack, in bytes get_and_send_input_thread, // a pointer to the application-defined function to be executed by the thread (LPVOID)hInputWrite, // a pointer to a variable to be passed to the thread. 0, // the flags that control the creation of the thread &dTid); // a pointer to a variable that receives the thread identifier. // If this parameter is NULL, the thread identifier is not returned. if (hThread == NULL) { display_error("execute_cmd - CreateThread : Write", TRUE); return AGENT_RET_FAIL; } // Read the child's output read_and_handle_output( hOutputRead ); // Redirection is complete // Tell the thread to exit and wait for thread to die. closesocket( g_sClientDupSocket ); // send out the zero-sized message to terminate agent 'exec' action send(g_sClientSocket, (const char*)&dEndSize, sizeof(dEndSize), 0); // Wait Thread which keep receiving & forwarding commands if (WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) { display_error("WaitForSingleObject", TRUE); return AGENT_RET_FAIL; } // Close input and output handle if (!CloseHandle(hOutputRead)) { display_error("execute_cmd - CloseHandle : hOutputRead", TRUE); return AGENT_RET_FAIL; } if (!CloseHandle(hInputWrite)) { display_error("execute_cmd - CloseHandle : hInputWrite", TRUE); return AGENT_RET_FAIL; } return AGENT_RET_SUCCESS; }
void Process::run() { SECURITY_ATTRIBUTES saAttr; // Set the bInheritHandle flag so pipe handles are inherited. 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) ) ErrorExit(TEXT("StdoutRd CreatePipe")); // Ensure the read handle to the pipe for STDOUT is not inherited. if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) ErrorExit(TEXT("Stdout SetHandleInformation")); // Create a pipe for the child process's STDIN. if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) ErrorExit(TEXT("Stdin CreatePipe")); // Ensure the write handle to the pipe for STDIN is not inherited. if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) ErrorExit(TEXT("Stdin SetHandleInformation")); std::string mycmd = "cmd.exe /D /c " + cmd; //Create child process PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; BOOL bSuccess = FALSE; // Set up members of the PROCESS_INFORMATION structure. ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); // Set up members of the STARTUPINFO structure. // This structure specifies the STDIN and STDOUT handles for redirection. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = g_hChildStd_OUT_Wr; siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; siStartInfo.hStdInput = g_hChildStd_IN_Rd; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; // Create the child process. bSuccess = CreateProcess( NULL, (LPSTR)cmd.c_str(), // 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 an error occurs, exit the application. if ( ! bSuccess ) ErrorExit(TEXT("CreateProcess")); else { running = true; /******************************************************************************** * IF YOU PLAN TO ATTACH TO YOUR'S BOTS PROCESS, UNCOMMENT OUT THIS CODE TO HELP. * IT WILL PAUSE UNTIL YOU TYPE A KEY AND HIT ENTER * ********************************************************************************/ //if( cmd == "C:\\planetwars\\cpp_framework\\albertz-planet_wars-cpp-2fc1dda\\VC\\Debug\\alcsbot.exe" ) //{ // std::cout << "Attach to mybot.exe process, type some char and hit enter when ready"; // char n; // std::cin >> n; //} //CloseHandle(piProcInfo.hProcess); hProcess = piProcInfo.hProcess; CloseHandle(piProcInfo.hThread); } }
void MythSystemWindows::Fork(time_t timeout) { QString LOC_ERR = QString("myth_system('%1'): Error: ").arg(GetLogCmd()); // For use in the child char locerr[MAX_BUFLEN]; strncpy(locerr, (const char *)LOC_ERR.toUtf8().constData(), MAX_BUFLEN); locerr[MAX_BUFLEN-1] = '\0'; LOG(VB_SYSTEM, LOG_DEBUG, QString("Launching: %1").arg(GetLogCmd())); GetBuffer(0)->setBuffer(0); GetBuffer(1)->setBuffer(0); GetBuffer(2)->setBuffer(0); HANDLE p_stdin[2] = { NULL, NULL }; HANDLE p_stdout[2] = { NULL, NULL }; HANDLE p_stderr[2] = { NULL, NULL }; SECURITY_ATTRIBUTES saAttr; STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); // Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* set up pipes */ if( GetSetting("UseStdin") ) { if (!CreatePipe(&p_stdin[0], &p_stdin[1], &saAttr, 0)) { LOG(VB_GENERAL, LOG_ERR, "stdin pipe() failed"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { // Ensure the write handle to the pipe for STDIN is not inherited. if (!SetHandleInformation(p_stdin[1], HANDLE_FLAG_INHERIT, 0)) { LOG(VB_SYSTEM, LOG_ERR, "stdin inheritance error"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { si.hStdInput = p_stdin[0]; si.dwFlags |= STARTF_USESTDHANDLES; } } } if( GetSetting("UseStdout") ) { if (!CreatePipe(&p_stdout[0], &p_stdout[1], &saAttr, 0)) { LOG(VB_SYSTEM, LOG_ERR, "stdout pipe() failed"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { // Ensure the read handle to the pipe for STDOUT is not inherited. if (!SetHandleInformation(p_stdout[0], HANDLE_FLAG_INHERIT, 0)) { LOG(VB_SYSTEM, LOG_ERR, "stdout inheritance error"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { si.hStdOutput = p_stdout[1]; si.dwFlags |= STARTF_USESTDHANDLES; } } } if( GetSetting("UseStderr") ) { if (!CreatePipe(&p_stderr[0], &p_stderr[1], &saAttr, 0)) { LOG(VB_SYSTEM, LOG_ERR, "stderr pipe() failed"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { // Ensure the read handle to the pipe for STDERR is not inherited. if (!SetHandleInformation(p_stderr[0], HANDLE_FLAG_INHERIT, 0)) { LOG(VB_SYSTEM, LOG_ERR, "stderr inheritance error"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { si.hStdError = p_stderr[1]; si.dwFlags |= STARTF_USESTDHANDLES; } } } // set up command args QString cmd = GetCommand() + " " + GetArgs().join(" "); if (GetSetting("UseShell")) cmd.prepend("cmd.exe /c "); SetCommand( cmd ); QByteArray cmdUTF8 = GetCommand().toUtf8(); TCHAR *command = TEXT((char *)cmdUTF8.constData()); const char *directory = NULL; QString dir = GetDirectory(); if (GetSetting("SetDirectory") && !dir.isEmpty()) directory = strdup(dir.toUtf8().constData()); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); m_timeout = timeout; if( timeout ) m_timeout += time(NULL); bool success = CreateProcess(NULL, command, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited 0, // creation flags NULL, // use parent's environment directory, // use parent's current directory &si, // STARTUPINFO pointer &pi); // receives PROCESS_INFORMATION if (!success) { LOG(VB_SYSTEM, LOG_ERR, "CreateProcess() failed"); SetStatus( GENERIC_EXIT_NOT_OK ); } else { /* parent */ m_child = pi.hProcess; SetStatus( GENERIC_EXIT_RUNNING ); LOG(VB_SYSTEM, LOG_INFO, QString("Managed child (Handle: %1) has started! " "%2%3 command=%4, timeout=%5") .arg((long long)m_child) .arg(GetSetting("UseShell") ? "*" : "") .arg(GetSetting("RunInBackground") ? "&" : "") .arg(GetLogCmd()) .arg(timeout)); /* close unused pipe ends */ CLOSE(p_stdin[0]); CLOSE(p_stdout[1]); CLOSE(p_stderr[1]); // store the rest m_stdpipe[0] = p_stdin[1]; m_stdpipe[1] = p_stdout[0]; m_stdpipe[2] = p_stderr[0]; // clean up the memory use if( directory ) free((void *)directory); } /* Parent */ if( GetStatus() != GENERIC_EXIT_RUNNING ) { CLOSE(p_stdin[0]); CLOSE(p_stdin[1]); CLOSE(p_stdout[0]); CLOSE(p_stdout[1]); CLOSE(p_stderr[0]); CLOSE(p_stderr[1]); } }
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int imported) { DWORD yes = 1; int non_ifs_lsp; assert(handle->socket == INVALID_SOCKET); /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { uv__set_sys_error(loop, WSAGetLastError()); return -1; } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(loop, GetLastError()); return -1; } /* Associate it with the I/O completion port. */ /* Use uv_handle_t pointer as completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, 0) == NULL) { if (imported) { handle->flags |= UV_HANDLE_EMULATE_IOCP; } else { uv__set_sys_error(loop, GetLastError()); return -1; } } non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : uv_tcp_non_ifs_lsp_ipv4; if (pSetFileCompletionNotificationModes && !non_ifs_lsp) { if (pSetFileCompletionNotificationModes((HANDLE) socket, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; } else if (GetLastError() != ERROR_INVALID_FUNCTION) { uv__set_sys_error(loop, GetLastError()); return -1; } } if ((handle->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(handle, socket, 1)) { return -1; } /* TODO: Use stored delay. */ if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) && uv__tcp_keepalive(handle, socket, 1, 60)) { return -1; } handle->socket = socket; return 0; }
/* 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; /* 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; }
CResourceCompilerHelper::ERcCallResult CResourceCompilerHelper::CallResourceCompiler( const char* szFileName, const char* szAdditionalSettings, IResourceCompilerListener* listener, bool bMayShowWindow, CResourceCompilerHelper::ERcExePath rcExePath, bool bSilent, bool bNoUserDialog, const wchar_t* szWorkingDirectory, const wchar_t* szRootPath) { // make command for execution SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH*3> wRemoteCmdLine; if (!szAdditionalSettings) { szAdditionalSettings = ""; } wchar_t szRemoteDirectory[512]; { wchar_t pathBuffer[512]; switch (rcExePath) { case eRcExePath_registry: GetRootPathUtf16(true, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer))); break; case eRcExePath_settingsManager: GetRootPathUtf16(false, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer))); break; case eRcExePath_currentFolder: wcscpy(pathBuffer, L"."); break; case eRcExePath_customPath: wcscpy(pathBuffer, szRootPath); break; default: return eRcCallResult_notFound; } if (!pathBuffer[0]) { wcscpy(pathBuffer, L"."); } swprintf_s(szRemoteDirectory, L"%s/Bin32/rc", pathBuffer); } if (!szFileName) { wRemoteCmdLine.appendAscii("\""); wRemoteCmdLine.append(szRemoteDirectory); wRemoteCmdLine.appendAscii("/rc.exe\" /userdialog=0 "); wRemoteCmdLine.appendAscii(szAdditionalSettings); } else { wRemoteCmdLine.appendAscii("\""); wRemoteCmdLine.append(szRemoteDirectory); wRemoteCmdLine.appendAscii("/rc.exe\" \""); wRemoteCmdLine.appendAscii(szFileName); wRemoteCmdLine.appendAscii("\" "); wRemoteCmdLine.appendAscii(bNoUserDialog ? "/userdialog=0 " : "/userdialog=1 "); wRemoteCmdLine.appendAscii(szAdditionalSettings); } // Create a pipe to read the stdout of the RC. SECURITY_ATTRIBUTES saAttr; ::memset(&saAttr, 0, sizeof(saAttr)); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = 0; HANDLE hChildStdOutRd, hChildStdOutWr; CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0); SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN HANDLE hChildStdInRd, hChildStdInWr; CreatePipe(&hChildStdInRd, &hChildStdInWr, &saAttr, 0); SetHandleInformation(hChildStdInWr, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN STARTUPINFOW si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwX = 100; si.dwY = 100; si.hStdError = hChildStdOutWr; si.hStdOutput = hChildStdOutWr; si.hStdInput = hChildStdInRd; si.dwFlags = STARTF_USEPOSITION | STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); bool bShowWindow = false; { wchar_t buffer[20]; g_pSettingsManager->GetValueByRef("ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))); bShowWindow = (wcscmp(buffer, L"true") == 0); } if (!CreateProcessW( NULL, // No module name (use command line). const_cast<wchar_t*>(wRemoteCmdLine.c_str()), // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. TRUE, // Set handle inheritance to TRUE. (bMayShowWindow && bShowWindow) ? 0 : CREATE_NO_WINDOW, // creation flags. NULL, // Use parent's environment block. szWorkingDirectory?szWorkingDirectory:szRemoteDirectory, // Set starting directory. &si, // Pointer to STARTUPINFO structure. &pi )) // Pointer to PROCESS_INFORMATION structure. { /* This code block is commented out instead of being deleted because it's good to have at hand for a debugging session. const size_t charsInMessageBuffer = 32768; // msdn about FormatMessage(): "The output buffer cannot be larger than 64K bytes." wchar_t szMessageBuffer[charsInMessageBuffer] = L""; FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szMessageBuffer, charsInMessageBuffer, NULL); GetCurrentDirectoryW(charsInMessageBuffer, szMessageBuffer); */ if (!bSilent) { MessageBoxA(0, "ResourceCompiler was not found.\n\nPlease verify CryENGINE RootPath.", "Error", MB_ICONERROR|MB_OK); } return eRcCallResult_notFound; } // Close the pipe that writes to the child process, since we don't actually have any input for it. CloseHandle(hChildStdInWr); // Read all the output from the child process. CloseHandle(hChildStdOutWr); ResourceCompilerLineHandler lineHandler(listener); LineStreamBuffer lineBuffer(&lineHandler, &ResourceCompilerLineHandler::HandleLine); for (;;) { char buffer[2048]; DWORD bytesRead; if (!ReadFile(hChildStdOutRd, buffer, sizeof(buffer), &bytesRead, NULL) || (bytesRead == 0)) { break; } lineBuffer.HandleText(buffer, bytesRead); } // Wait until child process exits. WaitForSingleObject(pi.hProcess, INFINITE); bool ok = true; DWORD exitCode = 1; { if ((GetExitCodeProcess(pi.hProcess, &exitCode) == 0) || (exitCode != 0)) { ok = false; } } // Close process and thread handles. CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (exitCode == eRcExitCode_Crash) { return eRcCallResult_crash; } if (lineBuffer.IsTruncated()) { return eRcCallResult_error; } return ok ? eRcCallResult_success : eRcCallResult_error; }
int launch_server() { #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); 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); adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", 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; }
static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { uv_loop_t* loop = handle->loop; BOOL success; DWORD bytes; SOCKET accept_socket; short family; assert(handle->flags & UV_HANDLE_LISTENING); assert(req->accept_socket == INVALID_SOCKET); /* choose family and extension function */ if (handle->flags & UV_HANDLE_IPV6) { family = AF_INET6; } else { family = AF_INET; } /* Open a socket for the accepted connection. */ accept_socket = socket(family, SOCK_STREAM, 0); if (accept_socket == INVALID_SOCKET) { SET_REQ_ERROR(req, WSAGetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; return; } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; closesocket(accept_socket); return; } /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } success = handle->func_acceptex(handle->socket, accept_socket, (void*)req->accept_buffer, 0, sizeof(struct sockaddr_storage), sizeof(struct sockaddr_storage), &bytes, &req->overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { /* Process the req without IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { /* The req will be processed with IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; if (handle->flags & UV_HANDLE_EMULATE_IOCP && req->wait_handle == INVALID_HANDLE_VALUE && !RegisterWaitForSingleObject(&req->wait_handle, req->event_handle, post_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; return; } } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; /* Destroy the preallocated client socket. */ closesocket(accept_socket); /* Destroy the event handle */ if (handle->flags & UV_HANDLE_EMULATE_IOCP) { CloseHandle(req->overlapped.hEvent); req->event_handle = NULL; } } }
uint64 TZipIn::GetFLen(const TStr& ZipFNm) { #ifdef GLib_WIN HANDLE ZipStdoutRd, ZipStdoutWr; // create pipes SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. const int PipeBufferSz = 32*1024; EAssertR(CreatePipe(&ZipStdoutRd, &ZipStdoutWr, &saAttr, PipeBufferSz), "Stdout pipe creation failed"); // Ensure the read handle to the pipe for STDOUT is not inherited. SetHandleInformation(ZipStdoutRd, HANDLE_FLAG_INHERIT, 0); //CreateZipProcess(GetCmd(FNm), FNm); { const TStr CmdLine = TStr::Fmt("7z.exe l %s", ZipFNm.CStr()); PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory( &siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdOutput = ZipStdoutWr; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; // Create the child process. const BOOL FuncRetn = CreateProcess(NULL, (LPSTR) CmdLine.CStr(), NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo); EAssertR(FuncRetn!=0, TStr::Fmt("Can not execute '%s'", CmdLine.CStr()).CStr()); CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); } #else const TStr CmdLine = TStr::Fmt("7za l %s", ZipFNm.CStr()); FILE* ZipStdoutRd = popen(CmdLine.CStr(), "r"); if (ZipStdoutRd == NULL) { // try using SevenZipPath ZipStdoutRd = popen((TZipIn::SevenZipPath+"/"+CmdLine).CStr(), "r"); } EAssertR(ZipStdoutRd != NULL, TStr::Fmt("Can not execute '%s'", CmdLine.CStr()).CStr()); #endif // Read output from the child process const int BfSz = 32*1024; char* Bf = new char [BfSz]; int BfC=0, BfL=0; memset(Bf, 0, BfSz); #ifdef GLib_WIN DWORD BytesRead; EAssert(ReadFile(ZipStdoutRd, Bf, MxBfL, &BytesRead, NULL) != 0); #else size_t BytesRead = fread(Bf, 1, MxBfL, ZipStdoutRd); EAssert(BytesRead != 0); EAssert(pclose(ZipStdoutRd) != -1); #endif BfL = (int) BytesRead; IAssert((BfC!=0)||(BfL!=0)); BfC = 0; Bf[BfL] = 0; // find file lenght TStr Str(Bf); delete [] Bf; TStrV StrV; Str.SplitOnWs(StrV); int n = StrV.Len()-1; while (n > 0 && ! StrV[n].IsPrefix("-----")) { n--; } if (n-7 <= 0) { WrNotify(TStr::Fmt("Corrupt file %s: MESSAGE:\n", ZipFNm.CStr()).CStr(), Str.CStr()); SaveToErrLog(TStr::Fmt("Corrupt file %s. Message:\n:%s\n", ZipFNm.CStr(), Str.CStr()).CStr()); return 0; } return StrV[n-7].GetInt64(); }
JNIEXPORT jint JNICALL Java_us_temerity_pipeline_NativeProcessLight_execNativeLight ( JNIEnv *env, jobject obj, jobjectArray jcmdarray, /* IN: command[0] and arguments[1+] */ jobjectArray jenvp, /* IN: environmental variable name=value pairs */ jstring jdir /* IN: the working directory */ ) { /* exception initialization */ char msg[2048]; jclass IOException = env->FindClass("java/io/IOException"); if(IOException == 0) { errno = EINVAL; perror("NativeProcessLight.execNative(), unable to lookup \"java/lang/IOException\""); return -1; } /* get handles for the NativeProcessLight object's fields/methods */ jclass NativeProcessLightClass = env->GetObjectClass(obj); if(NativeProcessLightClass == 0) { env->ThrowNew(IOException, "unable to lookup class: NativeProcessLight"); return -1; } jfieldID pStdInFileDesc = env->GetFieldID(NativeProcessLightClass, "pStdInFileDesc", "I"); if(pStdInFileDesc == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pStdInFileDesc"); return -1; } jfieldID pStdOutFileDesc = env->GetFieldID(NativeProcessLightClass, "pStdOutFileDesc", "I"); if(pStdOutFileDesc == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pStdOutFileDesc"); return -1; } jfieldID pStdErrFileDesc = env->GetFieldID(NativeProcessLightClass, "pStdErrFileDesc", "I"); if(pStdErrFileDesc == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pStdErrFileDesc"); return -1; } jfieldID pUTime = env->GetFieldID(NativeProcessLightClass, "pUTime", "J"); if(pUTime == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pUTime"); return -1; } jfieldID pSTime = env->GetFieldID(NativeProcessLightClass, "pSTime", "J"); if(pSTime == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pSTime"); return -1; } jfieldID pPageFaults = env->GetFieldID(NativeProcessLightClass, "pPageFaults", "J"); if(pPageFaults == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pPageFaults"); return -1; } jfieldID pVirtualSize = env->GetFieldID(NativeProcessLightClass, "pVirtualSize", "J"); if(pVirtualSize == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pVirtualSize"); return -1; } jfieldID pResidentSize = env->GetFieldID(NativeProcessLightClass, "pResidentSize", "J"); if(pResidentSize == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pResidentSize"); return -1; } jfieldID pSwappedSize = env->GetFieldID(NativeProcessLightClass, "pSwappedSize", "J"); if(pSwappedSize == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.pSwappedSize"); return -1; } jmethodID setPid = env->GetMethodID(NativeProcessLightClass, "setPid", "(I)V"); if(setPid == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.setPid()"); return -1; } jmethodID setIsRunning = env->GetMethodID(NativeProcessLightClass, "setIsRunning", "(Z)V"); if(setIsRunning == 0) { env->ThrowNew(IOException, "unable to access: NativeProcessLight.setIsRunning()"); return -1; } /* repackage the arguments */ const char* dir = NULL; char* cmdline = NULL; TCHAR envbuf[32768]; { { dir = env->GetStringUTFChars(jdir, 0); if((dir == NULL) || (strlen(dir) == 0)) { env->ThrowNew(IOException,"empty working directory"); return -1; } printf("Dir = %s\n", dir); // DEBUG struct stat buf; if(stat(dir, &buf) == -1) { sprintf(msg, "stat failed for \"%s\": %s", dir, strerror(errno)); env->ReleaseStringUTFChars(jdir, dir); env->ThrowNew(IOException, msg); return -1; } else if(!(buf.st_mode & _S_IFDIR)) { sprintf(msg, "illegal working directory \"%s\"", dir); env->ReleaseStringUTFChars(jdir, dir); env->ThrowNew(IOException, msg); return -1; } } printf("Dir is OK\n"); // DEBUG { jsize len = env->GetArrayLength(jcmdarray); if(len == 0) { env->ReleaseStringUTFChars(jdir, dir); env->ThrowNew(IOException, "empty command arguments array"); return -1; } jsize i; size_t csize = 0; for(i=0; i<len; i++) { jstring s = (jstring) env->GetObjectArrayElement(jcmdarray, i); const char* arg = env->GetStringUTFChars(s, NULL); csize += strlen(arg) + ((i == 0) ? 2 : 1); env->ReleaseStringUTFChars(s, arg); } printf("Cmdline Size = %d\n", csize); // DEBUG if(csize >= 32767) { env->ReleaseStringUTFChars(jdir, dir); env->ThrowNew(IOException, "command line exceeds 32K limit on Windows!"); return -1; } cmdline = new char[csize+1]; cmdline[0] = '\0'; for(i=0; i<len; i++) { jstring s = (jstring) env->GetObjectArrayElement(jcmdarray, i); const char* arg = env->GetStringUTFChars(s, NULL); strcat(cmdline, (i == 0) ? "\"" : " "); strcat(cmdline, arg); if(i == 0) strcat(cmdline, "\""); env->ReleaseStringUTFChars(s, arg); } printf("Cmdline = %s\n", cmdline); // DEBUG } { jsize len = env->GetArrayLength(jenvp); printf("Environment:\n"); // DEBUG LPTSTR envp = envbuf; int total = 0; jsize i; for(i=0; i<len; i++) { jstring s = (jstring) env->GetObjectArrayElement(jenvp, i); const char* keyval = env->GetStringUTFChars(s, NULL); printf(" %s\n", keyval); if(lstrcpy(envp, TEXT(keyval)) == NULL) { env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; env->ThrowNew(IOException, "failed to copy environment"); return -1; } env->ReleaseStringUTFChars(s, keyval); int size = (lstrlen(envp) + 1) * sizeof(TCHAR); total += size; if(total > 32768) { env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; env->ThrowNew(IOException, "environment exceeds 32K limit on Windows!"); return -1; } envp += size; } *envp = '\0'; } } /* create pipes to communicate with the child process */ HANDLE child_stdin, child_stdout, child_stderr; HANDLE parent_stdin, parent_stdout, parent_stderr; { /* security attributes which allow handles to be inherited by the child process */ SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* create a pipe to the child's STDIN */ if(!CreatePipe(&child_stdin, &parent_stdin, &saAttr, 0)) { env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; env->ThrowNew(IOException, "unable to create the STDIN pipe!"); return -1; } /* create a pipe to the child's STDOUT */ if(!CreatePipe(&parent_stdout, &child_stdout, &saAttr, 0)) { env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; CloseHandle(child_stdin); env->ThrowNew(IOException, "unable to create the STDOUT pipe!"); return -1; } /* create a pipe to the child's STDERR */ if(!CreatePipe(&parent_stderr, &child_stderr, &saAttr, 0)) { env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; CloseHandle(child_stdin); CloseHandle(child_stdout); env->ThrowNew(IOException, "unable to create the STDERR pipe!"); return -1; } /* make sure parent side of STDIN STDOUT and STDERR pipes are not inherited */ SetHandleInformation(parent_stdin, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(parent_stdout, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(parent_stderr, HANDLE_FLAG_INHERIT, 0); } /* create the child process */ DWORD exitCode; { PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&startInfo, sizeof(STARTUPINFO)); startInfo.cb = sizeof(STARTUPINFO); startInfo.hStdError = child_stderr; startInfo.hStdOutput = child_stdout; startInfo.hStdInput = child_stdin; startInfo.dwFlags |= STARTF_USESTDHANDLES; if(CreateProcess(NULL, TEXT(cmdline), NULL, NULL, TRUE, 0, (LPVOID) envbuf, TEXT(dir), &startInfo, &procInfo) == 0) { env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; CloseHandle(child_stdin); CloseHandle(child_stdout); CloseHandle(child_stderr); throwWindowsIOException(env, IOException, "CreateProcessAsUser"); return -1; } env->ReleaseStringUTFChars(jdir, dir); delete[] cmdline; printf("Created Process\n"); // DEBUG /* set the process ID */ jint pid = (jint) procInfo.dwProcessId; env->CallVoidMethod(obj, setPid, pid); /* set IO fields for the parent ends of the pipes */ env->SetIntField(obj, pStdInFileDesc, (jint) parent_stdin); env->SetIntField(obj, pStdOutFileDesc, (jint) parent_stdout); env->SetIntField(obj, pStdErrFileDesc, (jint) parent_stderr); /* let Java know that the process is running */ env->CallVoidMethod(obj, setIsRunning, true); printf("Wating on PID (%d)...\n", pid); // DEBUG /* wait on the process to exit */ if(WaitForSingleObject(procInfo.hProcess, INFINITE) == WAIT_FAILED) { CloseHandle(child_stdin); CloseHandle(child_stdout); CloseHandle(child_stderr); env->ThrowNew(IOException, "failed to wait on subprocess!"); return -1; } printf("Done Wating!\n"); // DEBUG /* let Java know that the process has exited */ env->CallVoidMethod(obj, setIsRunning, false); /* get the exit code */ if(!GetExitCodeProcess(procInfo.hProcess, &exitCode)) { CloseHandle(child_stdin); CloseHandle(child_stdout); CloseHandle(child_stderr); env->ThrowNew(IOException, "failed to get subprocess exit code!"); return -1; } printf("Exit Code = %d\n", exitCode); // DEBUG /* close the child side of the STDIN pipe */ if(!CloseHandle(child_stdin)) { CloseHandle(child_stdout); CloseHandle(child_stderr); env->ThrowNew(IOException, "unable to close the child side of the STDIN pipe!"); return -1; } /* close the child side of the STDOUT pipe */ if(!CloseHandle(child_stdout)) { env->ThrowNew(IOException, "unable to close the child side of the STDOUT pipe!"); return -1; } /* close the child side of the STDERR pipe */ if(!CloseHandle(child_stderr)) { env->ThrowNew(IOException, "unable to close the child side of the STDERR pipe!"); return -1; } /* get usage statistics */ { FILETIME createTime, exitTime, sysTime, userTime; if(!GetProcessTimes(procInfo.hProcess, &createTime, &exitTime, &sysTime, &userTime)) { env->ThrowNew(IOException, "failed to get subprocess timing statistics!"); return -1; } /* 64-bit times returned by GetProcessTime are in 100ns (100/10^9), while the times reported to Java are in jiffies (1/100) of a second */ jlong denom = 100000L; { ULARGE_INTEGER li; memcpy(&li, &userTime, sizeof(FILETIME)); env->SetLongField(obj, pUTime, li.QuadPart / denom); printf("User Time = %I64u (100-ns) %I64u (jiffies)\n", li.QuadPart, li.QuadPart / denom); } { ULARGE_INTEGER li; memcpy(&li, &sysTime, sizeof(FILETIME)); env->SetLongField(obj, pSTime, li.QuadPart / denom); printf("System Time = %I64u (100-ns) %I64u (jiffies)\n", li.QuadPart, li.QuadPart / denom); } /* get process memory usage statistics */ { PROCESS_MEMORY_COUNTERS pmc; if(!GetProcessMemoryInfo(procInfo.hProcess, &pmc, sizeof(pmc))) { env->ThrowNew(IOException, "failed to get subprocess memory usage statistics!"); return -1; } // DEBUG printf("PageFaults = %I64d\n", (jlong) pmc.PageFaultCount); printf("PeakWorking Set Size = %I64d\n", (jlong) pmc.PeakWorkingSetSize); printf("PeakPagefileUsage = %I64d\n", (jlong) pmc.PeakPagefileUsage); printf("QuotaPeakPagedPoolUsage = %I64d\n", (jlong) pmc.QuotaPeakPagedPoolUsage); // DEBUG env->SetLongField(obj, pPageFaults, (jlong) pmc.PageFaultCount); env->SetLongField(obj, pResidentSize, (jlong) pmc.PeakWorkingSetSize); env->SetLongField(obj, pVirtualSize, (jlong) pmc.PeakPagefileUsage); env->SetLongField(obj, pSwappedSize, (jlong) pmc.QuotaPeakPagedPoolUsage); } } /* cleanup process/thread handles */ CloseHandle(procInfo.hProcess); CloseHandle(procInfo.hThread); } return ((jint) exitCode); }
BOOL LogServer::CreateLogPipe() { logme("LogServer::CreateLogPipe: cmd=%s", GetExternalCmd()); m_fpLog = _popen(GetExternalCmd(), "wb"); if (m_fpLog == NULL) { fprintf(stderr, "LogServer: failed to open pipe (%s). err=%d\n", GetExternalCmd(), GetLastError()); return FALSE; } return TRUE; #if 0 // Create the program HANDLE hProgStdinRd, hProgStdinWr; SECURITY_ATTRIBUTES saAttr; // Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDIN. if (! CreatePipe(&hProgStdinRd, &hProgStdinWr, &saAttr, 0)) { printf("JaxerLogger: Create Stdin pipe failed.\n"); return FALSE; } // Ensure that the write handle to the child process's pipe for STDIN is not inherited. SetHandleInformation( hProgStdinWr, HANDLE_FLAG_INHERIT, 0); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION) ); STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO) ); si.cb = sizeof(STARTUPINFO); si.hStdInput = hProgStdinRd; si.dwFlags |= STARTF_USESTDHANDLES; logme("JaxerLog: pipe cmd=%s", GetExternalCmd()); BOOL rc = CreateProcess(NULL, (TCHAR*)GetExternalCmd(), NULL, /* default process security descriptor */ NULL, /* default thread security descriptor */ TRUE, /* inherit handles */ CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB, NULL, /* inherit environment */ NULL, /* inherit current directory */ &si, &pi); if (!rc) { char s[256]; sprintf(s,"JaxerLogger: Create process (%s) failed. err=%d\n", GetExternalCmd(), GetLastError()); char *t = s; logme(s); return FALSE; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); m_fdLog = hProgStdinWr; }
static boolean runcmdshell (Handle hshell, Handle hcommand, HANDLE *hprocess, HANDLE *hout, HANDLE *herr) { /* 2006-03-09 aradke: launch the command shell as a child process. we consume hshell, but caller is responsible for closing hout if we return true. */ Handle hcmdline = nil; SECURITY_ATTRIBUTES securityinfo; STARTUPINFO startupinfo; PROCESS_INFORMATION processinfo; HANDLE houtread = nil; HANDLE houtwrite = nil; HANDLE herrread = nil; HANDLE herrwrite = nil; boolean fl; *hprocess = nil; /*create pipes for reading from command shell*/ clearbytes (&securityinfo, sizeof (securityinfo)); securityinfo.nLength = sizeof (securityinfo); securityinfo.lpSecurityDescriptor = nil; securityinfo.bInheritHandle = true; if (hout) { /*caller interested in stdout*/ if (!CreatePipe (&houtread, &houtwrite, &securityinfo, nil)) goto error; if (!SetHandleInformation (houtread, HANDLE_FLAG_INHERIT, 0)) goto error; } else houtwrite = GetStdHandle (STD_OUTPUT_HANDLE); if (herr) { /*caller interested in stderr*/ if (!CreatePipe (&herrread, &herrwrite, &securityinfo, nil)) goto error; if (!SetHandleInformation (herrread, HANDLE_FLAG_INHERIT, 0)) goto error; } else herrwrite = GetStdHandle (STD_ERROR_HANDLE); /*init structs for creating process*/ clearbytes (&startupinfo, sizeof (startupinfo)); startupinfo.cb = sizeof (startupinfo); startupinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; startupinfo.hStdInput = GetStdHandle (STD_INPUT_HANDLE); startupinfo.hStdOutput = houtwrite; startupinfo.hStdError = herrwrite; startupinfo.wShowWindow = SW_HIDE; clearbytes (&processinfo, sizeof (processinfo)); /*synthesize command string*/ if (!inserttextinhandle (hcommand, 0, "\x04" " /c ")) goto exit; if (!concathandles (hshell, hcommand, &hcmdline)) goto exit; if (!pushcharhandle (CHNULL, hshell)) goto exit; if (!pushcharhandle (CHNULL, hcmdline)) goto exit; /*check whether command shell can be accessed*/ if (!cmdshellexists (hshell)) { if (!searchcmdpath (&hshell)) /*do a search path lookup, sets error*/ goto exit; } /*create command shell process*/ lockhandle (hshell); lockhandle (hcmdline); fl = CreateProcess ( *hshell, /*IN LPCSTR lpApplicationName*/ *hcmdline, /*IN LPSTR lpCommandLine*/ nil, /*IN LPSECURITY_ATTRIBUTES lpProcessAttributes*/ nil, /*IN LPSECURITY_ATTRIBUTES lpThreadAttributes*/ true, /*IN BOOL bInheritHandles*/ 0, /*IN DWORD dwCreationFlags*/ nil, /*IN LPVOID lpEnvironment: use parent's*/ nil, /*IN LPCSTR lpCurrentDirectory: use parent's*/ &startupinfo, /*IN LPSTARTUPINFOA lpStartupInfo*/ &processinfo); /*OUT LPPROCESS_INFORMATION lpProcessInformation*/ unlockhandle (hshell); unlockhandle (hcmdline); /*handle result*/ if (!fl) goto error; CloseHandle (houtwrite); /*now inherited by child process*/ CloseHandle (herrwrite); CloseHandle (processinfo.hThread); disposehandle (hcmdline); disposehandle (hshell); *hprocess = processinfo.hProcess; if (hout) *hout = houtread; if (herr) *herr = herrread; return (true); error: winerror (); /*note fall through*/ exit: /*error is already set*/ if (hout && !houtread) CloseHandle (houtread); if (hout && !houtwrite) CloseHandle (houtwrite); if (herr && !herrread) CloseHandle (herrread); if (herr && !herrwrite) CloseHandle (herrwrite); disposehandle (hcmdline); disposehandle (hshell); return (false); } /*runcmdshell*/
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); }
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i){ jstring element = (jstring) e->GetObjectArrayElement(command, i); if(element) { // worst case, assuming every character is '"', and we escape all of them size += 2 * e->GetStringUTFLength(element) + 3; } else { throwNew(e, "java/lang/NullPointerException", strdup("null string array element")); } } RUNTIME_ARRAY(char, line, size); char* linep = RUNTIME_ARRAY_BODY(line); for (int i = 0; i < e->GetArrayLength(command); ++i) { if (i) *(linep++) = _T(' '); jstring element = (jstring) e->GetObjectArrayElement(command, i); const char* s = e->GetStringUTFChars(element, 0); copyAndEscape(&linep, s, e->GetStringUTFLength(element)); e->ReleaseStringUTFChars(element, s); } *(linep++) = _T('\0'); HANDLE in[] = { 0, 0 }; HANDLE out[] = { 0, 0 }; HANDLE err[] = { 0, 0 }; makePipe(e, in); SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 2, 1, &inDescriptor); makePipe(e, out); SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 3, 1, &outDescriptor); makePipe(e, err); SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 4, 1, &errDescriptor); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = in[1]; si.hStdInput = out[0]; si.hStdError = err[1]; BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, 0, 0, &si, &pi); CloseHandle(in[1]); CloseHandle(out[0]); CloseHandle(err[1]); if (not success) { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); return; } jlong pid = reinterpret_cast<jlong>(pi.hProcess); e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast<jlong>(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); #else throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); #endif }
static int _execIO( UThread* ut, char* cmd, UCell* res, const UBuffer* in, UBuffer* out, UBuffer* err ) { HANDLE childStdInR; HANDLE childStdInW; HANDLE childStdOutR; HANDLE childStdOutW; HANDLE childStdErrR; HANDLE childStdErrW; SECURITY_ATTRIBUTES sec; STARTUPINFO si; PROCESS_INFORMATION pi; DWORD flags = 0; sec.nLength = sizeof(SECURITY_ATTRIBUTES); sec.lpSecurityDescriptor = NULL; sec.bInheritHandle = TRUE; childStdOutR = childStdErrR = INVALID_HANDLE_VALUE; if( in ) { if( ! CreatePipe( &childStdInR, &childStdInW, &sec, 0 ) ) { fail0: return ur_error( ut, UR_ERR_INTERNAL, "CreatePipe failed\n" ); } // Child does not inherit our end of pipe. SetHandleInformation( childStdInW, HANDLE_FLAG_INHERIT, 0 ); } if( out ) { if( ! CreatePipe( &childStdOutR, &childStdOutW, &sec, 0 ) ) { fail1: if( in ) _closePipe( childStdInR, childStdInW ); goto fail0; } // Child does not inherit our end of pipe. SetHandleInformation( childStdOutR, HANDLE_FLAG_INHERIT, 0 ); flags = DETACHED_PROCESS; } if( err ) { if( ! CreatePipe( &childStdErrR, &childStdErrW, &sec, 0 ) ) { if( out ) _closePipe( childStdOutR, childStdOutW ); goto fail1; } // Child does not inherit our end of pipe. SetHandleInformation( childStdErrR, HANDLE_FLAG_INHERIT, 0 ); flags = DETACHED_PROCESS; } ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); if( in || out || err ) { si.hStdInput = in ? childStdInR : NULL; si.hStdOutput = out ? childStdOutW : GetStdHandle( STD_OUTPUT_HANDLE ); si.hStdError = err ? childStdErrW : GetStdHandle( STD_ERROR_HANDLE ); si.dwFlags = STARTF_USESTDHANDLES; } ZeroMemory( &pi, sizeof(pi) ); // Start the child process. if( ! CreateProcess( NULL, // No module name (use command line). TEXT(cmd), // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. TRUE, // Handle inheritance. flags, // 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. ) { if( in ) _closePipe( childStdInR, childStdInW ); if( out ) _closePipe( childStdOutR, childStdOutW ); if( err ) _closePipe( childStdErrR, childStdErrW ); return ur_error( ut, UR_ERR_INTERNAL, "CreateProcess failed (%d).\n", GetLastError() ); } if( in ) { DWORD nw; CloseHandle( childStdInR ); WriteFile( childStdInW, in->ptr.v, (in->type == UT_STRING) ? in->used * in->elemSize : in->used, &nw, NULL ); CloseHandle( childStdInW ); } if( out || err ) { if( out ) CloseHandle( childStdOutW ); if( err ) CloseHandle( childStdErrW ); _readPipes( childStdOutR, out, childStdErrR, err ); if( out ) CloseHandle( childStdOutR ); if( err ) CloseHandle( childStdErrR ); } { DWORD code; // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); if( GetExitCodeProcess( pi.hProcess, &code ) ) { ur_setId(res, UT_INT); ur_int(res) = code; } else { ur_setId(res, UT_NONE); } } // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return UR_OK; }
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0 (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels) { HANDLE stdHandles[3]; PROCESS_INFORMATION pi = {0}, *piCopy; STARTUPINFOW si; DWORD flags = 0; const wchar_t * cwd = NULL; LPVOID envBlk = NULL; int ret = 0; int nCmdLineLength= 0; wchar_t * szCmdLine= 0; int nBlkSize = MAX_ENV_SIZE; wchar_t * szEnvBlock = NULL; jsize nCmdTokens = 0; jsize nEnvVars = 0; int i; DWORD pid = GetCurrentProcessId(); int nPos; pProcInfo_t pCurProcInfo; // This needs to be big enough to contain the name of the event used when calling CreateEventW bellow. // It is made of a prefix (7 characters max) plus the value of a pointer that gets output in characters. // This will be bigger in the case of 64 bit. static const int MAX_EVENT_NAME_LENGTH = 50; wchar_t eventBreakName[MAX_EVENT_NAME_LENGTH]; wchar_t eventWaitName[MAX_EVENT_NAME_LENGTH]; wchar_t eventTerminateName[MAX_EVENT_NAME_LENGTH]; wchar_t eventKillName[MAX_EVENT_NAME_LENGTH]; wchar_t eventCtrlcName[MAX_EVENT_NAME_LENGTH]; #ifdef DEBUG_MONITOR wchar_t buffer[4000]; #endif int nLocalCounter; wchar_t inPipeName[PIPE_NAME_LENGTH]; wchar_t outPipeName[PIPE_NAME_LENGTH]; wchar_t errPipeName[PIPE_NAME_LENGTH]; nCmdLineLength= MAX_CMD_SIZE; szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t)); szCmdLine[0]= _T('\0'); if((HIBYTE(LOWORD(GetVersion()))) & 0x80) { ThrowByName(env, "java/io/IOException", "Does not support Windows 3.1/95/98/Me"); return 0; } if (cmdarray == 0) { ThrowByName(env, "java/lang/NullPointerException", "No command line specified"); return 0; } ZeroMemory(stdHandles, sizeof(stdHandles)); // Create pipe names EnterCriticalSection(&cs); swprintf(inPipeName, L"\\\\.\\pipe\\stdin%08i%010i", pid, nCounter); swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", pid, nCounter); swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", pid, nCounter); nLocalCounter = nCounter; ++nCounter; LeaveCriticalSection(&cs); if ((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateNamedPipeW(inPipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) || (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateNamedPipeW(outPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) || (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateNamedPipeW(errPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL)))) { CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); ThrowByName(env, "java/io/IOException", "CreatePipe"); return 0; } #ifdef DEBUG_MONITOR swprintf(buffer, _T("Opened pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName); OutputDebugStringW(buffer); #endif nCmdTokens = env->GetArrayLength(cmdarray); nEnvVars = env->GetArrayLength(envp); pCurProcInfo = createProcInfo(); if(NULL == pCurProcInfo) { ThrowByName(env, "java/io/IOException", "Too many processes"); return 0; } // Construct starter's command line swprintf(eventBreakName, L"SABreak%04x%08x", pid, nLocalCounter); swprintf(eventWaitName, L"SAWait%004x%08x", pid, nLocalCounter); swprintf(eventTerminateName, L"SATerm%004x%08x", pid, nLocalCounter); swprintf(eventKillName, L"SAKill%04x%08x", pid, nLocalCounter); swprintf(eventCtrlcName, L"SACtrlc%04x%08x", pid, nLocalCounter); pCurProcInfo->eventBreak = CreateEventW(NULL, FALSE, FALSE, eventBreakName); if(NULL == pCurProcInfo->eventBreak || GetLastError() == ERROR_ALREADY_EXISTS) { ThrowByName(env, "java/io/IOException", "Cannot create event"); return 0; } pCurProcInfo->eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName); pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName); pCurProcInfo->eventKill = CreateEventW(NULL, FALSE, FALSE, eventKillName); pCurProcInfo->eventCtrlc = CreateEventW(NULL, FALSE, FALSE, eventCtrlcName); swprintf(szCmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName, eventKillName, eventCtrlcName); nPos = wcslen(szCmdLine); // Prepare command line for(i = 0; i < nCmdTokens; ++i) { jstring item = (jstring)env->GetObjectArrayElement(cmdarray, i); jsize len = env->GetStringLength(item); int nCpyLen; const wchar_t * str = (const wchar_t *)env->GetStringChars(item, 0); if(NULL != str) { int requiredSize= nPos+len+2; if (requiredSize > 32*1024) { ThrowByName(env, "java/io/IOException", "Command line too long"); return 0; } ensureSize(&szCmdLine, &nCmdLineLength, requiredSize); if (NULL == szCmdLine) { ThrowByName(env, "java/io/IOException", "Not enough memory"); return 0; } if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, nCmdLineLength - nPos))) { ThrowByName(env, "java/io/IOException", "Command line too long"); return 0; } nPos += nCpyLen; szCmdLine[nPos] = _T(' '); ++nPos; env->ReleaseStringChars(item, (const jchar *)str); } } szCmdLine[nPos] = _T('\0'); #ifdef DEBUG_MONITOR swprintf(buffer, _T("There are %i environment variables \n"), nEnvVars); OutputDebugStringW(buffer); #endif // Prepare environment block if (nEnvVars > 0) { nPos = 0; szEnvBlock = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t)); for(i = 0; i < nEnvVars; ++i) { jstring item = (jstring)env->GetObjectArrayElement(envp, i); jsize len = env->GetStringLength(item); const wchar_t * str = (const wchar_t *)env->GetStringChars(item, 0); if(NULL != str) { while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0' { nBlkSize += MAX_ENV_SIZE; szEnvBlock = (wchar_t *)realloc(szEnvBlock, nBlkSize * sizeof(wchar_t)); if(NULL == szEnvBlock) { ThrowByName(env, "java/io/IOException", "Not enough memory"); return 0; } #ifdef DEBUG_MONITOR swprintf(buffer, _T("Realloc environment block; new length is %i \n"), nBlkSize); OutputDebugStringW(buffer); #endif } #ifdef DEBUG_MONITOR swprintf(buffer, _T("%s\n"), str); OutputDebugStringW(buffer); #endif wcsncpy(szEnvBlock + nPos, str, len); nPos += len; szEnvBlock[nPos] = _T('\0'); ++nPos; env->ReleaseStringChars(item, (const jchar *)str); } } szEnvBlock[nPos] = _T('\0'); } if (dir != 0) { const wchar_t * str = (const wchar_t *)env->GetStringChars(dir, 0); if(NULL != str) { cwd = wcsdup(str); env->ReleaseStringChars(dir, (const jchar *)str); } } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // Processes in the Process Group are hidden SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, FALSE); SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, FALSE); SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, FALSE); flags = CREATE_NEW_CONSOLE; flags |= CREATE_NO_WINDOW; flags |= CREATE_UNICODE_ENVIRONMENT; #ifdef DEBUG_MONITOR OutputDebugStringW(szCmdLine); #endif // launches starter; we need it to create another console group to correctly process // emulation of SYSint signal (Ctrl-C) ret = CreateProcessW(0, /* executable name */ szCmdLine, /* command line */ 0, /* process security attribute */ 0, /* thread security attribute */ FALSE, /* inherits system handles */ flags, /* normal attached process */ szEnvBlock, /* environment block */ cwd, /* change to the new current directory */ &si, /* (in) startup information */ &pi); /* (out) process information */ if(NULL != cwd) free((void *)cwd); if(NULL != szEnvBlock) free(szEnvBlock); if(NULL != szCmdLine) free(szCmdLine); if (!ret) // Launching error { char * lpMsgBuf; CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (char *)&lpMsgBuf, 0, NULL ); ThrowByName(env, "java/io/IOException", lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); cleanUpProcBlock(pCurProcInfo); ret = -1; } else { int file_handles[3]; HANDLE h[2]; int what; EnterCriticalSection(&cs); pCurProcInfo -> pid = pi.dwProcessId; h[0] = pCurProcInfo -> eventWait; h[1] = pi.hProcess; what = WaitForMultipleObjects(2, h, FALSE, INFINITE); if(what != WAIT_OBJECT_0) // CreateProcess failed { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Process %i failed\n"), pi.dwProcessId); OutputDebugStringW(buffer); #endif cleanUpProcBlock(pCurProcInfo); ThrowByName(env, "java/io/IOException", "Launching failed"); #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Process failed\n")); #endif } else { ret = (long)(pCurProcInfo -> uid); // Prepare stream handlers to return to java program file_handles[0] = (int)stdHandles[0]; file_handles[1] = (int)stdHandles[1]; file_handles[2] = (int)stdHandles[2]; env->SetIntArrayRegion(channels, 0, 3, (jint *)file_handles); // do the cleanup so launch the according thread // create a copy of the PROCESS_INFORMATION as this might get destroyed piCopy = (PROCESS_INFORMATION *)malloc(sizeof(PROCESS_INFORMATION)); memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION)); _beginthread(waitProcTermination, 0, (void *)piCopy); #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Process started\n")); #endif } LeaveCriticalSection(&cs); } CloseHandle(pi.hThread); return ret; }
// // Tries to call where.exe to find the location of dotnet.exe. // Will check that the bitness of dotnet matches the current // worker process bitness. // Returns true if a valid dotnet was found, else false.R // std::optional<fs::path> HOSTFXR_UTILITY::InvokeWhereToFindDotnet() { HRESULT hr = S_OK; // Arguments to call where.exe STARTUPINFOW startupInfo = { 0 }; PROCESS_INFORMATION processInformation = { 0 }; SECURITY_ATTRIBUTES securityAttributes; CHAR pzFileContents[READ_BUFFER_SIZE]; HandleWrapper<InvalidHandleTraits> hStdOutReadPipe; HandleWrapper<InvalidHandleTraits> hStdOutWritePipe; HandleWrapper<InvalidHandleTraits> hProcess; HandleWrapper<InvalidHandleTraits> hThread; CComBSTR pwzDotnetName = NULL; DWORD dwFilePointer; BOOL fIsWow64Process; BOOL fIsCurrentProcess64Bit; DWORD dwExitCode; STRU struDotnetSubstring; STRU struDotnetLocationsString; DWORD dwNumBytesRead; DWORD dwBinaryType; INT index = 0; INT prevIndex = 0; std::optional<fs::path> result; // Set the security attributes for the read/write pipe securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; securityAttributes.bInheritHandle = TRUE; LOG_INFO(L"Invoking where.exe to find dotnet.exe"); // Create a read/write pipe that will be used for reading the result of where.exe FINISHED_LAST_ERROR_IF(!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0)); FINISHED_LAST_ERROR_IF(!SetHandleInformation(hStdOutReadPipe, HANDLE_FLAG_INHERIT, 0)); // Set the stdout and err pipe to the write pipes. startupInfo.cb = sizeof(startupInfo); startupInfo.dwFlags |= STARTF_USESTDHANDLES; startupInfo.hStdOutput = hStdOutWritePipe; startupInfo.hStdError = hStdOutWritePipe; // CreateProcess requires a mutable string to be passed to commandline // See https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083/ pwzDotnetName = L"\"where.exe\" dotnet.exe"; // Create a process to invoke where.exe FINISHED_LAST_ERROR_IF(!CreateProcessW(NULL, pwzDotnetName, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInformation )); // Store handles into wrapper so they get closed automatically hProcess = processInformation.hProcess; hThread = processInformation.hThread; // Wait for where.exe to return WaitForSingleObject(processInformation.hProcess, INFINITE); // // where.exe will return 0 on success, 1 if the file is not found // and 2 if there was an error. Check if the exit code is 1 and set // a new hr result saying it couldn't find dotnet.exe // FINISHED_LAST_ERROR_IF (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode)); // // In this block, if anything fails, we will goto our fallback of // looking in C:/Program Files/ // if (dwExitCode != 0) { FINISHED_IF_FAILED(E_FAIL); } // Where succeeded. // Reset file pointer to the beginning of the file. dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN); if (dwFilePointer == INVALID_SET_FILE_POINTER) { FINISHED_IF_FAILED(E_FAIL); } // // As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang. // TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block. // FINISHED_LAST_ERROR_IF (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL)); if (dwNumBytesRead >= READ_BUFFER_SIZE) { // This shouldn't ever be this large. We could continue to call ReadFile in a loop, // however if someone had this many dotnet.exes on their machine. FINISHED_IF_FAILED(E_FAIL); } FINISHED_IF_FAILED(struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead)); LOG_INFOF(L"where.exe invocation returned: '%ls'", struDotnetLocationsString.QueryStr()); // Check the bitness of the currently running process // matches the dotnet.exe found. FINISHED_LAST_ERROR_IF (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process)); if (fIsWow64Process) { // 32 bit mode fIsCurrentProcess64Bit = FALSE; } else { // Check the SystemInfo to see if we are currently 32 or 64 bit. SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; } LOG_INFOF(L"Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit); while (TRUE) { index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex); if (index == -1) { break; } FINISHED_IF_FAILED(struDotnetSubstring.Copy(&struDotnetLocationsString.QueryStr()[prevIndex], index - prevIndex)); // \r\n is two wchars, so add 2 here. prevIndex = index + 2; LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr()); if (LOG_LAST_ERROR_IF(!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType))) { continue; } LOG_INFOF(L"Binary type %d", dwBinaryType); if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY)) { // The bitness of dotnet matched with the current worker process bitness. return std::make_optional(struDotnetSubstring.QueryStr()); } } Finished: return result; }