blob: a99faa227f784c479470900f81fd76d03b6b86b4 [file] [log] [blame]
Zachary Turner172d37d2014-10-14 21:55:08 +00001//===-- 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
17using namespace lldb;
18using namespace lldb_private;
19
Zachary Turner19e2ea82016-01-13 21:21:49 +000020namespace
21{
22void
23CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer)
24{
25 if (env.GetArgumentCount() == 0)
26 return;
27
28 int bytes = 0;
29 for (int i = 0; i < env.GetArgumentCount(); ++i)
30 bytes += strlen(env.GetArgumentAtIndex(i)) + sizeof(char);
31 bytes += sizeof(char);
32 buffer.resize(bytes);
33 char *cur_entry = &buffer[0];
34 for (int i = 0; i < env.GetArgumentCount(); ++i)
35 {
36 ::strcpy(cur_entry, env.GetArgumentAtIndex(i));
37 cur_entry += strlen(cur_entry) + sizeof(char);
38 }
39 // Environment buffer is a null terminated list of null terminated
40 // strings, so it is terminated by two null bytes.
41 buffer.back() = 0;
42}
43}
44
Zachary Turner172d37d2014-10-14 21:55:08 +000045HostProcess
46ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
47{
48 error.Clear();
49
50 std::string executable;
51 std::string commandLine;
52 std::vector<char> environment;
53 STARTUPINFO startupinfo = {0};
54 PROCESS_INFORMATION pi = {0};
55
56 HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
57 HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
58 HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
59
60 startupinfo.cb = sizeof(startupinfo);
61 startupinfo.dwFlags |= STARTF_USESTDHANDLES;
Adrian McCarthye1adc7b2015-05-29 23:01:25 +000062 startupinfo.hStdError = stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
63 startupinfo.hStdInput = stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
64 startupinfo.hStdOutput = stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
Zachary Turner172d37d2014-10-14 21:55:08 +000065
Zachary Turner555a7a62014-12-12 18:10:52 +000066 const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
67 if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true"))
68 {
69 startupinfo.dwFlags |= STARTF_USESHOWWINDOW;
70 startupinfo.wShowWindow = SW_HIDE;
71 }
72
Zachary Turner742346a2014-11-05 22:16:28 +000073 DWORD flags = CREATE_NEW_CONSOLE;
74 if (launch_info.GetFlags().Test(eLaunchFlagDebug))
75 flags |= DEBUG_ONLY_THIS_PROCESS;
76
Zachary Turner19e2ea82016-01-13 21:21:49 +000077 auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries());
78 LPVOID env_block = nullptr;
79 ::CreateEnvironmentBuffer(env, environment);
80 if (!environment.empty())
81 env_block = environment.data();
82
Zachary Turner172d37d2014-10-14 21:55:08 +000083 executable = launch_info.GetExecutableFile().GetPath();
84 launch_info.GetArguments().GetQuotedCommandString(commandLine);
Zachary Turner19e2ea82016-01-13 21:21:49 +000085 BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags,
86 env_block, launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi);
Zachary Turner172d37d2014-10-14 21:55:08 +000087 if (result)
88 {
89 // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
90 ::CloseHandle(pi.hThread);
91 }
92
93 if (stdin_handle)
94 ::CloseHandle(stdin_handle);
95 if (stdout_handle)
96 ::CloseHandle(stdout_handle);
97 if (stderr_handle)
98 ::CloseHandle(stderr_handle);
99
100 if (!result)
101 error.SetError(::GetLastError(), eErrorTypeWin32);
102 return HostProcess(pi.hProcess);
103}
104
105HANDLE
106ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd)
107{
108 const FileAction *action = launch_info.GetFileActionForFD(fd);
109 if (action == nullptr)
110 return NULL;
111 SECURITY_ATTRIBUTES secattr = {0};
112 secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
113 secattr.bInheritHandle = TRUE;
114
115 const char *path = action->GetPath();
116 DWORD access = 0;
Zachary Turner022c3c82015-09-02 17:59:19 +0000117 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
Zachary Turner172d37d2014-10-14 21:55:08 +0000118 DWORD create = 0;
119 DWORD flags = 0;
120 if (fd == STDIN_FILENO)
121 {
122 access = GENERIC_READ;
123 create = OPEN_EXISTING;
124 flags = FILE_ATTRIBUTE_READONLY;
125 }
126 if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
127 {
128 access = GENERIC_WRITE;
129 create = CREATE_ALWAYS;
130 if (fd == STDERR_FILENO)
131 flags = FILE_FLAG_WRITE_THROUGH;
132 }
133
134 HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
135 return (result == INVALID_HANDLE_VALUE) ? NULL : result;
136}