43 std::vector<std::wstring> env_entries;
44 for (
const auto &KV : env) {
47 env_entries.push_back(std::move(wentry));
49 std::sort(env_entries.begin(), env_entries.end(),
50 [](
const std::wstring &a,
const std::wstring &b) {
51 return _wcsicmp(a.c_str(), b.c_str()) < 0;
54 std::vector<wchar_t> buffer;
55 for (
const auto &env_entry : env_entries) {
56 buffer.insert(buffer.end(), env_entry.begin(), env_entry.end());
57 buffer.push_back(L
'\0');
61 buffer.push_back(L
'\0');
63 buffer.push_back(L
'\0');
91 STARTUPINFOEXW startupinfoex = {};
92 startupinfoex.StartupInfo.cb =
sizeof(STARTUPINFOEXW);
93 startupinfoex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
95 HPCON hPC = launch_info.
GetPTY().GetPseudoTerminalHandle();
102 auto close_handles = llvm::make_scope_exit([&] {
104 ::CloseHandle(stdin_handle);
106 ::CloseHandle(stdout_handle);
108 ::CloseHandle(stderr_handle);
111 SIZE_T attributelist_size = 0;
112 InitializeProcThreadAttributeList(
nullptr,
114 &attributelist_size);
116 startupinfoex.lpAttributeList =
117 static_cast<LPPROC_THREAD_ATTRIBUTE_LIST
>(malloc(attributelist_size));
118 auto free_attributelist =
119 llvm::make_scope_exit([&] { free(startupinfoex.lpAttributeList); });
120 if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
122 &attributelist_size)) {
126 auto delete_attributelist = llvm::make_scope_exit(
127 [&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
129 std::vector<HANDLE> inherited_handles;
131 if (!UpdateProcThreadAttribute(startupinfoex.lpAttributeList, 0,
133 sizeof(hPC), NULL, NULL)) {
139 launch_info, startupinfoex, stdout_handle, stderr_handle, stdin_handle);
140 if (!inherited_handles_or_err) {
141 error =
Status(inherited_handles_or_err.getError());
144 inherited_handles = std::move(*inherited_handles_or_err);
147 const char *hide_console_var =
148 getenv(
"LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
149 if (hide_console_var &&
150 llvm::StringRef(hide_console_var).equals_insensitive(
"true")) {
151 startupinfoex.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
152 startupinfoex.StartupInfo.wShowWindow = SW_HIDE;
155 DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
156 EXTENDED_STARTUPINFO_PRESENT;
158 flags |= DEBUG_ONLY_THIS_PROCESS;
160 if (launch_info.
GetFlags().
Test(eLaunchFlagDisableSTDIO) || use_pty)
161 flags &= ~CREATE_NEW_CONSOLE;
163 std::vector<wchar_t> environment =
166 auto wcommandLineOrErr =
168 if (!wcommandLineOrErr) {
172 std::wstring wcommandLine = *wcommandLineOrErr;
176 WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
178 std::wstring wexecutable, wworkingDirectory;
184 PROCESS_INFORMATION pi = {};
186 BOOL result = ::CreateProcessW(
187 wexecutable.c_str(), pwcommandLine, NULL, NULL,
188 !inherited_handles.empty(), flags, environment.data(),
189 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
190 reinterpret_cast<STARTUPINFOW *
>(&startupinfoex), &pi);
202 ::CloseHandle(pi.hThread);
214 std::vector<HANDLE> inherited_handles;
216 startupinfoex.StartupInfo.hStdError =
217 stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
218 startupinfoex.StartupInfo.hStdInput =
219 stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
220 startupinfoex.StartupInfo.hStdOutput =
221 stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
223 if (startupinfoex.StartupInfo.hStdError)
224 inherited_handles.push_back(startupinfoex.StartupInfo.hStdError);
225 if (startupinfoex.StartupInfo.hStdInput)
226 inherited_handles.push_back(startupinfoex.StartupInfo.hStdInput);
227 if (startupinfoex.StartupInfo.hStdOutput)
228 inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
234 inherited_handles.push_back(
reinterpret_cast<HANDLE>(act->
GetFD()));
237 if (inherited_handles.empty())
238 return inherited_handles;
240 if (!UpdateProcThreadAttribute(
241 startupinfoex.lpAttributeList, 0,
242 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
243 inherited_handles.size() *
sizeof(
HANDLE),
245 return llvm::mapWindowsError(::GetLastError());
247 return inherited_handles;
254 if (action ==
nullptr)
256 SECURITY_ATTRIBUTES secattr = {};
257 secattr.nLength =
sizeof(SECURITY_ATTRIBUTES);
258 secattr.bInheritHandle = TRUE;
261 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
264 if (fd == STDIN_FILENO) {
265 access = GENERIC_READ;
266 create = OPEN_EXISTING;
267 flags = FILE_ATTRIBUTE_READONLY;
269 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
270 access = GENERIC_WRITE;
271 create = CREATE_ALWAYS;
272 if (fd == STDERR_FILENO)
273 flags = FILE_FLAG_WRITE_THROUGH;
278 llvm::ConvertUTF8toWide(path, wpath);
279 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
281 return (result == INVALID_HANDLE_VALUE) ? NULL : result;