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_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
202 EXTENDED_STARTUPINFO_PRESENT;
204 flags |= DEBUG_ONLY_THIS_PROCESS;
206 if (launch_info.
GetFlags().
Test(eLaunchFlagDisableSTDIO) ||
208 flags &= ~CREATE_NEW_CONSOLE;
210 std::vector<wchar_t> environment =
213 auto wcommandLineOrErr =
215 if (!wcommandLineOrErr) {
219 std::wstring wcommandLine = *wcommandLineOrErr;
223 WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
225 std::wstring wexecutable, wworkingDirectory;
231 PROCESS_INFORMATION pi = {};
233 BOOL result = ::CreateProcessW(
234 wexecutable.c_str(), pwcommandLine, NULL, NULL,
235 !inherited_handles.empty() ||
237 flags, environment.data(),
238 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
239 reinterpret_cast<STARTUPINFOW *
>(&startupinfoex), &pi);
251 ::CloseHandle(pi.hThread);
253 launch_info.
GetPTY().CloseAnonymousPipes();
265 std::vector<HANDLE> inherited_handles;
267 startupinfoex.StartupInfo.hStdError =
268 stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
269 startupinfoex.StartupInfo.hStdInput =
270 stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
271 startupinfoex.StartupInfo.hStdOutput =
272 stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
274 if (startupinfoex.StartupInfo.hStdError)
275 inherited_handles.push_back(startupinfoex.StartupInfo.hStdError);
276 if (startupinfoex.StartupInfo.hStdInput)
277 inherited_handles.push_back(startupinfoex.StartupInfo.hStdInput);
278 if (startupinfoex.StartupInfo.hStdOutput)
279 inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
285 if (std::find(inherited_handles.begin(), inherited_handles.end(),
286 act->
GetHandle()) != inherited_handles.end())
292 inherited_handles.push_back(act->
GetHandle());
295 inherited_handles.push_back(act->
GetHandle());
299 if (inherited_handles.empty())
300 return inherited_handles;
302 if (!UpdateProcThreadAttribute(
303 startupinfoex.lpAttributeList, 0,
304 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
305 inherited_handles.size() *
sizeof(
HANDLE),
307 return llvm::mapWindowsError(::GetLastError());
309 return inherited_handles;
327 SECURITY_ATTRIBUTES secattr = {};
328 secattr.nLength =
sizeof(SECURITY_ATTRIBUTES);
329 secattr.bInheritHandle = TRUE;
332 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
337 access = GENERIC_READ;
338 create = OPEN_EXISTING;
339 flags = FILE_ATTRIBUTE_READONLY;
342 flags = FILE_FLAG_WRITE_THROUGH;
344 access = GENERIC_WRITE;
345 create = CREATE_ALWAYS;
352 llvm::ConvertUTF8toWide(path, wpath);
353 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
355 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...