1172d37d3SZachary Turner //===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===// 2172d37d3SZachary Turner // 3172d37d3SZachary Turner // The LLVM Compiler Infrastructure 4172d37d3SZachary Turner // 5172d37d3SZachary Turner // This file is distributed under the University of Illinois Open Source 6172d37d3SZachary Turner // License. See LICENSE.TXT for details. 7172d37d3SZachary Turner // 8172d37d3SZachary Turner //===----------------------------------------------------------------------===// 9172d37d3SZachary Turner 10172d37d3SZachary Turner #include "lldb/Host/HostProcess.h" 11172d37d3SZachary Turner #include "lldb/Host/windows/ProcessLauncherWindows.h" 12172d37d3SZachary Turner #include "lldb/Target/ProcessLaunchInfo.h" 13172d37d3SZachary Turner 14172d37d3SZachary Turner #include <string> 15172d37d3SZachary Turner #include <vector> 16172d37d3SZachary Turner 17172d37d3SZachary Turner using namespace lldb; 18172d37d3SZachary Turner using namespace lldb_private; 19172d37d3SZachary Turner 20172d37d3SZachary Turner HostProcess 21172d37d3SZachary Turner ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) 22172d37d3SZachary Turner { 23172d37d3SZachary Turner error.Clear(); 24172d37d3SZachary Turner 25172d37d3SZachary Turner std::string executable; 26172d37d3SZachary Turner std::string commandLine; 27172d37d3SZachary Turner std::vector<char> environment; 28172d37d3SZachary Turner STARTUPINFO startupinfo = {0}; 29172d37d3SZachary Turner PROCESS_INFORMATION pi = {0}; 30172d37d3SZachary Turner 31172d37d3SZachary Turner HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); 32172d37d3SZachary Turner HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); 33172d37d3SZachary Turner HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); 34172d37d3SZachary Turner 35172d37d3SZachary Turner startupinfo.cb = sizeof(startupinfo); 36172d37d3SZachary Turner startupinfo.dwFlags |= STARTF_USESTDHANDLES; 37*e1adc7bcSAdrian McCarthy startupinfo.hStdError = stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); 38*e1adc7bcSAdrian McCarthy startupinfo.hStdInput = stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); 39*e1adc7bcSAdrian McCarthy startupinfo.hStdOutput = stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); 40172d37d3SZachary Turner 41555a7a6aSZachary Turner const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); 42555a7a6aSZachary Turner if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true")) 43555a7a6aSZachary Turner { 44555a7a6aSZachary Turner startupinfo.dwFlags |= STARTF_USESHOWWINDOW; 45555a7a6aSZachary Turner startupinfo.wShowWindow = SW_HIDE; 46555a7a6aSZachary Turner } 47555a7a6aSZachary Turner 48742346a2SZachary Turner DWORD flags = CREATE_NEW_CONSOLE; 49742346a2SZachary Turner if (launch_info.GetFlags().Test(eLaunchFlagDebug)) 50742346a2SZachary Turner flags |= DEBUG_ONLY_THIS_PROCESS; 51742346a2SZachary Turner 52172d37d3SZachary Turner executable = launch_info.GetExecutableFile().GetPath(); 53172d37d3SZachary Turner launch_info.GetArguments().GetQuotedCommandString(commandLine); 54742346a2SZachary Turner BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags, NULL, 55d3173f34SChaoren Lin launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi); 56172d37d3SZachary Turner if (result) 57172d37d3SZachary Turner { 58172d37d3SZachary Turner // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. 59172d37d3SZachary Turner ::CloseHandle(pi.hThread); 60172d37d3SZachary Turner } 61172d37d3SZachary Turner 62172d37d3SZachary Turner if (stdin_handle) 63172d37d3SZachary Turner ::CloseHandle(stdin_handle); 64172d37d3SZachary Turner if (stdout_handle) 65172d37d3SZachary Turner ::CloseHandle(stdout_handle); 66172d37d3SZachary Turner if (stderr_handle) 67172d37d3SZachary Turner ::CloseHandle(stderr_handle); 68172d37d3SZachary Turner 69172d37d3SZachary Turner if (!result) 70172d37d3SZachary Turner error.SetError(::GetLastError(), eErrorTypeWin32); 71172d37d3SZachary Turner return HostProcess(pi.hProcess); 72172d37d3SZachary Turner } 73172d37d3SZachary Turner 74172d37d3SZachary Turner HANDLE 75172d37d3SZachary Turner ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) 76172d37d3SZachary Turner { 77172d37d3SZachary Turner const FileAction *action = launch_info.GetFileActionForFD(fd); 78172d37d3SZachary Turner if (action == nullptr) 79172d37d3SZachary Turner return NULL; 80172d37d3SZachary Turner SECURITY_ATTRIBUTES secattr = {0}; 81172d37d3SZachary Turner secattr.nLength = sizeof(SECURITY_ATTRIBUTES); 82172d37d3SZachary Turner secattr.bInheritHandle = TRUE; 83172d37d3SZachary Turner 84172d37d3SZachary Turner const char *path = action->GetPath(); 85172d37d3SZachary Turner DWORD access = 0; 86172d37d3SZachary Turner DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE; 87172d37d3SZachary Turner DWORD create = 0; 88172d37d3SZachary Turner DWORD flags = 0; 89172d37d3SZachary Turner if (fd == STDIN_FILENO) 90172d37d3SZachary Turner { 91172d37d3SZachary Turner access = GENERIC_READ; 92172d37d3SZachary Turner create = OPEN_EXISTING; 93172d37d3SZachary Turner flags = FILE_ATTRIBUTE_READONLY; 94172d37d3SZachary Turner } 95172d37d3SZachary Turner if (fd == STDOUT_FILENO || fd == STDERR_FILENO) 96172d37d3SZachary Turner { 97172d37d3SZachary Turner access = GENERIC_WRITE; 98172d37d3SZachary Turner create = CREATE_ALWAYS; 99172d37d3SZachary Turner if (fd == STDERR_FILENO) 100172d37d3SZachary Turner flags = FILE_FLAG_WRITE_THROUGH; 101172d37d3SZachary Turner } 102172d37d3SZachary Turner 103172d37d3SZachary Turner HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL); 104172d37d3SZachary Turner return (result == INVALID_HANDLE_VALUE) ? NULL : result; 105172d37d3SZachary Turner } 106