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 const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); 42 if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true")) 43 { 44 startupinfo.dwFlags |= STARTF_USESHOWWINDOW; 45 startupinfo.wShowWindow = SW_HIDE; 46 } 47 48 DWORD flags = CREATE_NEW_CONSOLE; 49 if (launch_info.GetFlags().Test(eLaunchFlagDebug)) 50 flags |= DEBUG_ONLY_THIS_PROCESS; 51 52 executable = launch_info.GetExecutableFile().GetPath(); 53 launch_info.GetArguments().GetQuotedCommandString(commandLine); 54 BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags, NULL, 55 launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi); 56 if (result) 57 { 58 // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. 59 ::CloseHandle(pi.hThread); 60 } 61 62 if (stdin_handle) 63 ::CloseHandle(stdin_handle); 64 if (stdout_handle) 65 ::CloseHandle(stdout_handle); 66 if (stderr_handle) 67 ::CloseHandle(stderr_handle); 68 69 if (!result) 70 error.SetError(::GetLastError(), eErrorTypeWin32); 71 return HostProcess(pi.hProcess); 72 } 73 74 HANDLE 75 ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) 76 { 77 const FileAction *action = launch_info.GetFileActionForFD(fd); 78 if (action == nullptr) 79 return NULL; 80 SECURITY_ATTRIBUTES secattr = {0}; 81 secattr.nLength = sizeof(SECURITY_ATTRIBUTES); 82 secattr.bInheritHandle = TRUE; 83 84 const char *path = action->GetPath(); 85 DWORD access = 0; 86 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE; 87 DWORD create = 0; 88 DWORD flags = 0; 89 if (fd == STDIN_FILENO) 90 { 91 access = GENERIC_READ; 92 create = OPEN_EXISTING; 93 flags = FILE_ATTRIBUTE_READONLY; 94 } 95 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) 96 { 97 access = GENERIC_WRITE; 98 create = CREATE_ALWAYS; 99 if (fd == STDERR_FILENO) 100 flags = FILE_FLAG_WRITE_THROUGH; 101 } 102 103 HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL); 104 return (result == INVALID_HANDLE_VALUE) ? NULL : result; 105 } 106