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