1 //===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Host/HostProcess.h" 11 #include "lldb/Host/windows/ProcessLauncherWindows.h" 12 #include "lldb/Target/ProcessLaunchInfo.h" 13 14 #include <string> 15 #include <vector> 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 HostProcess 21 ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) 22 { 23 error.Clear(); 24 25 std::string executable; 26 std::string commandLine; 27 std::vector<char> environment; 28 STARTUPINFO startupinfo = {0}; 29 PROCESS_INFORMATION pi = {0}; 30 31 HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); 32 HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); 33 HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); 34 35 startupinfo.cb = sizeof(startupinfo); 36 startupinfo.dwFlags |= STARTF_USESTDHANDLES; 37 startupinfo.hStdError = stderr_handle; 38 startupinfo.hStdInput = stdin_handle; 39 startupinfo.hStdOutput = stdout_handle; 40 41 executable = launch_info.GetExecutableFile().GetPath(); 42 launch_info.GetArguments().GetQuotedCommandString(commandLine); 43 BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, 44 launch_info.GetWorkingDirectory(), &startupinfo, &pi); 45 if (result) 46 { 47 // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. 48 ::CloseHandle(pi.hThread); 49 } 50 51 if (stdin_handle) 52 ::CloseHandle(stdin_handle); 53 if (stdout_handle) 54 ::CloseHandle(stdout_handle); 55 if (stderr_handle) 56 ::CloseHandle(stderr_handle); 57 58 if (!result) 59 error.SetError(::GetLastError(), eErrorTypeWin32); 60 return HostProcess(pi.hProcess); 61 } 62 63 HANDLE 64 ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) 65 { 66 const FileAction *action = launch_info.GetFileActionForFD(fd); 67 if (action == nullptr) 68 return NULL; 69 SECURITY_ATTRIBUTES secattr = {0}; 70 secattr.nLength = sizeof(SECURITY_ATTRIBUTES); 71 secattr.bInheritHandle = TRUE; 72 73 const char *path = action->GetPath(); 74 DWORD access = 0; 75 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE; 76 DWORD create = 0; 77 DWORD flags = 0; 78 if (fd == STDIN_FILENO) 79 { 80 access = GENERIC_READ; 81 create = OPEN_EXISTING; 82 flags = FILE_ATTRIBUTE_READONLY; 83 } 84 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) 85 { 86 access = GENERIC_WRITE; 87 create = CREATE_ALWAYS; 88 if (fd == STDERR_FILENO) 89 flags = FILE_FLAG_WRITE_THROUGH; 90 } 91 92 HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL); 93 return (result == INVALID_HANDLE_VALUE) ? NULL : result; 94 } 95