blob: 16805ba7df889aaa6af5bfb102c955e6fb63f377 [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
Zachary Turner172d37d2014-10-14 21:55:08 +000010#include "lldb/Host/windows/ProcessLauncherWindows.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000011#include "lldb/Host/HostProcess.h"
Zachary Turner172d37d2014-10-14 21:55:08 +000012#include "lldb/Target/ProcessLaunchInfo.h"
13
Zachary Turner190fadc2016-03-22 17:58:09 +000014#include "llvm/ADT/SmallVector.h"
15#include "llvm/Support/ConvertUTF.h"
16
Zachary Turner172d37d2014-10-14 21:55:08 +000017#include <string>
18#include <vector>
19
20using namespace lldb;
21using namespace lldb_private;
22
Kate Stoneb9c1b512016-09-06 20:57:50 +000023namespace {
24void CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) {
25 if (env.GetArgumentCount() == 0)
26 return;
Zachary Turner19e2ea82016-01-13 21:21:49 +000027
Kate Stoneb9c1b512016-09-06 20:57:50 +000028 // Environment buffer is a null terminated list of null terminated strings
Zachary Turner97d2c402016-10-05 23:40:23 +000029 for (auto &entry : env.entries()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000030 std::wstring warg;
Zachary Turner97d2c402016-10-05 23:40:23 +000031 if (llvm::ConvertUTF8toWide(entry.ref, warg)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 buffer.insert(buffer.end(), (char *)warg.c_str(),
33 (char *)(warg.c_str() + warg.size() + 1));
Zachary Turner19e2ea82016-01-13 21:21:49 +000034 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000035 }
36 // One null wchar_t (to end the block) is two null bytes
37 buffer.push_back(0);
38 buffer.push_back(0);
Zachary Turner19e2ea82016-01-13 21:21:49 +000039}
40}
41
Zachary Turner172d37d2014-10-14 21:55:08 +000042HostProcess
Kate Stoneb9c1b512016-09-06 20:57:50 +000043ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
44 Error &error) {
45 error.Clear();
Zachary Turner172d37d2014-10-14 21:55:08 +000046
Kate Stoneb9c1b512016-09-06 20:57:50 +000047 std::string executable;
48 std::string commandLine;
49 std::vector<char> environment;
Zachary Turner5a8ad4592016-10-05 17:07:34 +000050 STARTUPINFO startupinfo = {};
51 PROCESS_INFORMATION pi = {};
Zachary Turner172d37d2014-10-14 21:55:08 +000052
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
54 HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
55 HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
Zachary Turner172d37d2014-10-14 21:55:08 +000056
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 startupinfo.cb = sizeof(startupinfo);
58 startupinfo.dwFlags |= STARTF_USESTDHANDLES;
59 startupinfo.hStdError =
60 stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
61 startupinfo.hStdInput =
62 stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
63 startupinfo.hStdOutput =
64 stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
Zachary Turner172d37d2014-10-14 21:55:08 +000065
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 const char *hide_console_var =
67 getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
68 if (hide_console_var &&
69 llvm::StringRef(hide_console_var).equals_lower("true")) {
70 startupinfo.dwFlags |= STARTF_USESHOWWINDOW;
71 startupinfo.wShowWindow = SW_HIDE;
72 }
Zachary Turner555a7a62014-12-12 18:10:52 +000073
Kate Stoneb9c1b512016-09-06 20:57:50 +000074 DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
75 if (launch_info.GetFlags().Test(eLaunchFlagDebug))
76 flags |= DEBUG_ONLY_THIS_PROCESS;
Zachary Turner742346a2014-11-05 22:16:28 +000077
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries());
79 LPVOID env_block = nullptr;
80 ::CreateEnvironmentBuffer(env, environment);
81 if (!environment.empty())
82 env_block = environment.data();
Zachary Turner19e2ea82016-01-13 21:21:49 +000083
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 executable = launch_info.GetExecutableFile().GetPath();
85 launch_info.GetArguments().GetQuotedCommandString(commandLine);
Zachary Turner190fadc2016-03-22 17:58:09 +000086
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 std::wstring wexecutable, wcommandLine, wworkingDirectory;
88 llvm::ConvertUTF8toWide(executable, wexecutable);
89 llvm::ConvertUTF8toWide(commandLine, wcommandLine);
90 llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(),
91 wworkingDirectory);
Zachary Turner190fadc2016-03-22 17:58:09 +000092
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because
94 // CreateProcessW can modify it
95 BOOL result = ::CreateProcessW(
96 wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block,
97 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
98 &startupinfo, &pi);
99 if (result) {
100 // Do not call CloseHandle on pi.hProcess, since we want to pass that back
101 // through the HostProcess.
102 ::CloseHandle(pi.hThread);
103 }
Zachary Turner172d37d2014-10-14 21:55:08 +0000104
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105 if (stdin_handle)
106 ::CloseHandle(stdin_handle);
107 if (stdout_handle)
108 ::CloseHandle(stdout_handle);
109 if (stderr_handle)
110 ::CloseHandle(stderr_handle);
Zachary Turner172d37d2014-10-14 21:55:08 +0000111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 if (!result)
113 error.SetError(::GetLastError(), eErrorTypeWin32);
114 return HostProcess(pi.hProcess);
Zachary Turner172d37d2014-10-14 21:55:08 +0000115}
116
117HANDLE
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info,
119 int fd) {
120 const FileAction *action = launch_info.GetFileActionForFD(fd);
121 if (action == nullptr)
122 return NULL;
Zachary Turner5a8ad4592016-10-05 17:07:34 +0000123 SECURITY_ATTRIBUTES secattr = {};
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
125 secattr.bInheritHandle = TRUE;
Zachary Turner172d37d2014-10-14 21:55:08 +0000126
Zachary Turner27a5c2b2016-09-23 22:11:51 +0000127 llvm::StringRef path = action->GetPath();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 DWORD access = 0;
129 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
130 DWORD create = 0;
131 DWORD flags = 0;
132 if (fd == STDIN_FILENO) {
133 access = GENERIC_READ;
134 create = OPEN_EXISTING;
135 flags = FILE_ATTRIBUTE_READONLY;
136 }
137 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
138 access = GENERIC_WRITE;
139 create = CREATE_ALWAYS;
140 if (fd == STDERR_FILENO)
141 flags = FILE_FLAG_WRITE_THROUGH;
142 }
Zachary Turner172d37d2014-10-14 21:55:08 +0000143
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 std::wstring wpath;
145 llvm::ConvertUTF8toWide(path, wpath);
146 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
147 flags, NULL);
148 return (result == INVALID_HANDLE_VALUE) ? NULL : result;
Zachary Turner172d37d2014-10-14 21:55:08 +0000149}