42 std::vector<std::wstring> env_entries;
43 for (
const auto &KV : env) {
46 env_entries.push_back(std::move(wentry));
48 std::sort(env_entries.begin(), env_entries.end(),
49 [](
const std::wstring &a,
const std::wstring &b) {
50 return _wcsicmp(a.c_str(), b.c_str()) < 0;
53 std::vector<wchar_t> buffer;
54 for (
const auto &env_entry : env_entries) {
55 buffer.insert(buffer.end(), env_entry.begin(), env_entry.end());
56 buffer.push_back(L
'\0');
60 buffer.push_back(L
'\0');
62 buffer.push_back(L
'\0');
93 SIZE_T attributelist_size = 0;
94 InitializeProcThreadAttributeList(
nullptr,
98 startupinfoex.lpAttributeList =
99 static_cast<LPPROC_THREAD_ATTRIBUTE_LIST
>(malloc(attributelist_size));
101 if (!startupinfoex.lpAttributeList)
102 return llvm::mapWindowsError(ERROR_OUTOFMEMORY);
104 if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
106 0, &attributelist_size)) {
107 free(startupinfoex.lpAttributeList);
108 return llvm::mapWindowsError(GetLastError());
128 STARTUPINFOEXW startupinfoex = {};
129 startupinfoex.StartupInfo.cb =
sizeof(STARTUPINFOEXW);
130 startupinfoex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
133 ? launch_info.
GetPTY().GetMode()
139 llvm::scope_exit close_handles([&] {
141 ::CloseHandle(stdin_handle);
143 ::CloseHandle(stdout_handle);
145 ::CloseHandle(stderr_handle);
149 if (!attributelist_or_err) {
150 error = attributelist_or_err.getError();
155 std::vector<HANDLE> inherited_handles;
158 HPCON hPC = launch_info.
GetPTY().GetPseudoTerminalHandle();
171 if (!UpdateProcThreadAttribute(
172 startupinfoex.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
173 inherited_handles.data(), inherited_handles.size() *
sizeof(
HANDLE),
181 auto inherited_handles_or_err =
183 stderr_handle, stdin_handle);
184 if (!inherited_handles_or_err) {
185 error =
Status(inherited_handles_or_err.getError());
188 inherited_handles = std::move(*inherited_handles_or_err);
193 const char *hide_console_var =
194 getenv(
"LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
195 if (hide_console_var &&
196 llvm::StringRef(hide_console_var).equals_insensitive(
"true")) {
197 startupinfoex.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
198 startupinfoex.StartupInfo.wShowWindow = SW_HIDE;
201 DWORD flags = CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT;
202 const bool stdio_redirected = launch_info.
IsFDRedirected(STDIN_FILENO) &&
205 if (stdio_redirected)
206 flags |= CREATE_NO_WINDOW;
207 else if (!launch_info.
GetFlags().
Test(eLaunchFlagDisableSTDIO) &&
209 flags |= CREATE_NEW_CONSOLE;
212 flags |= DEBUG_ONLY_THIS_PROCESS;
214 std::vector<wchar_t> environment =
217 auto wcommandLineOrErr =
219 if (!wcommandLineOrErr) {
223 std::wstring wcommandLine = *wcommandLineOrErr;
227 WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
229 std::wstring wexecutable, wworkingDirectory;
235 PROCESS_INFORMATION pi = {};
237 BOOL result = ::CreateProcessW(
238 wexecutable.c_str(), pwcommandLine, NULL, NULL,
239 !inherited_handles.empty() ||
241 flags, environment.data(),
242 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
243 reinterpret_cast<STARTUPINFOW *
>(&startupinfoex), &pi);
255 ::CloseHandle(pi.hThread);
257 launch_info.
GetPTY().CloseAnonymousPipes();
269 std::vector<HANDLE> inherited_handles;
271 startupinfoex.StartupInfo.hStdInput =
272 stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
273 startupinfoex.StartupInfo.hStdOutput =
274 stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
280 HANDLE effective_stderr = stderr_handle;
281 if (!effective_stderr && launch_info) {
286 effective_stderr = startupinfoex.StartupInfo.hStdOutput;
291 startupinfoex.StartupInfo.hStdError =
292 effective_stderr ? effective_stderr : GetStdHandle(STD_ERROR_HANDLE);
295 auto push_if_new = [&](
HANDLE h) {
296 if (h && std::find(inherited_handles.begin(), inherited_handles.end(), h) ==
297 inherited_handles.end())
298 inherited_handles.push_back(h);
300 push_if_new(startupinfoex.StartupInfo.hStdError);
301 push_if_new(startupinfoex.StartupInfo.hStdInput);
302 push_if_new(startupinfoex.StartupInfo.hStdOutput);
308 if (std::find(inherited_handles.begin(), inherited_handles.end(),
309 act->
GetHandle()) != inherited_handles.end())
315 inherited_handles.push_back(act->
GetHandle());
318 inherited_handles.push_back(act->
GetHandle());
322 if (inherited_handles.empty())
323 return inherited_handles;
325 if (!UpdateProcThreadAttribute(
326 startupinfoex.lpAttributeList, 0,
327 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
328 inherited_handles.size() *
sizeof(
HANDLE),
330 return llvm::mapWindowsError(::GetLastError());
332 return inherited_handles;
350 SECURITY_ATTRIBUTES secattr = {};
351 secattr.nLength =
sizeof(SECURITY_ATTRIBUTES);
352 secattr.bInheritHandle = TRUE;
355 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
360 access = GENERIC_READ;
361 create = OPEN_EXISTING;
362 flags = FILE_ATTRIBUTE_READONLY;
365 flags = FILE_FLAG_WRITE_THROUGH;
368 access = GENERIC_WRITE;
369 create = CREATE_ALWAYS;
376 llvm::ConvertUTF8toWide(path, wpath);
377 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
379 return (result == INVALID_HANDLE_VALUE) ? NULL : result;
static llvm::ErrorOr< std::vector< HANDLE > > GetInheritedHandles(STARTUPINFOEXW &startupinfoex, const ProcessLaunchInfo *launch_info=nullptr, HANDLE stdout_handle=NULL, HANDLE stderr_handle=NULL, HANDLE stdin_handle=NULL)
Get the list of Windows handles that should be inherited by the child process and update STARTUPINFOE...