xref: /llvm-project/lldb/source/Host/windows/ProcessLauncherWindows.cpp (revision 172d37d3b92ca70e65f11f9a7caf7af4c8a5e44f)
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