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