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();
96 bool use_pty = hPC != INVALID_HANDLE_VALUE &&
98 launch_info.
GetFlags().
Test(lldb::eLaunchFlagLaunchInTTY);
103 auto close_handles = llvm::make_scope_exit([&] {
105 ::CloseHandle(stdin_handle);
107 ::CloseHandle(stdout_handle);
109 ::CloseHandle(stderr_handle);
112 SIZE_T attributelist_size = 0;
113 InitializeProcThreadAttributeList(
nullptr,
115 &attributelist_size);
117 startupinfoex.lpAttributeList =
118 static_cast<LPPROC_THREAD_ATTRIBUTE_LIST
>(malloc(attributelist_size));
119 auto free_attributelist =
120 llvm::make_scope_exit([&] { free(startupinfoex.lpAttributeList); });
121 if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
123 &attributelist_size)) {
127 auto delete_attributelist = llvm::make_scope_exit(
128 [&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
130 std::vector<HANDLE> inherited_handles;
132 if (!UpdateProcThreadAttribute(startupinfoex.lpAttributeList, 0,
134 sizeof(hPC), NULL, NULL)) {
140 launch_info, startupinfoex, stdout_handle, stderr_handle, stdin_handle);
141 if (!inherited_handles_or_err) {
142 error =
Status(inherited_handles_or_err.getError());
145 inherited_handles = std::move(*inherited_handles_or_err);
148 const char *hide_console_var =
149 getenv(
"LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
150 if (hide_console_var &&
151 llvm::StringRef(hide_console_var).equals_insensitive(
"true")) {
152 startupinfoex.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
153 startupinfoex.StartupInfo.wShowWindow = SW_HIDE;
156 DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
157 EXTENDED_STARTUPINFO_PRESENT;
159 flags |= DEBUG_ONLY_THIS_PROCESS;
161 if (launch_info.
GetFlags().
Test(eLaunchFlagDisableSTDIO) || use_pty)
162 flags &= ~CREATE_NEW_CONSOLE;
164 std::vector<wchar_t> environment =
167 auto wcommandLineOrErr =
169 if (!wcommandLineOrErr) {
173 std::wstring wcommandLine = *wcommandLineOrErr;
177 WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
179 std::wstring wexecutable, wworkingDirectory;
185 PROCESS_INFORMATION pi = {};
187 BOOL result = ::CreateProcessW(
188 wexecutable.c_str(), pwcommandLine, NULL, NULL,
189 !inherited_handles.empty(), flags, environment.data(),
190 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
191 reinterpret_cast<STARTUPINFOW *
>(&startupinfoex), &pi);
203 ::CloseHandle(pi.hThread);
215 std::vector<HANDLE> inherited_handles;
217 startupinfoex.StartupInfo.hStdError =
218 stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
219 startupinfoex.StartupInfo.hStdInput =
220 stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
221 startupinfoex.StartupInfo.hStdOutput =
222 stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
224 if (startupinfoex.StartupInfo.hStdError)
225 inherited_handles.push_back(startupinfoex.StartupInfo.hStdError);
226 if (startupinfoex.StartupInfo.hStdInput)
227 inherited_handles.push_back(startupinfoex.StartupInfo.hStdInput);
228 if (startupinfoex.StartupInfo.hStdOutput)
229 inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
235 inherited_handles.push_back(
reinterpret_cast<HANDLE>(act->
GetFD()));
238 if (inherited_handles.empty())
239 return inherited_handles;
241 if (!UpdateProcThreadAttribute(
242 startupinfoex.lpAttributeList, 0,
243 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
244 inherited_handles.size() *
sizeof(
HANDLE),
246 return llvm::mapWindowsError(::GetLastError());
248 return inherited_handles;
255 if (action ==
nullptr)
257 SECURITY_ATTRIBUTES secattr = {};
258 secattr.nLength =
sizeof(SECURITY_ATTRIBUTES);
259 secattr.bInheritHandle = TRUE;
262 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
265 if (fd == STDIN_FILENO) {
266 access = GENERIC_READ;
267 create = OPEN_EXISTING;
268 flags = FILE_ATTRIBUTE_READONLY;
270 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
271 access = GENERIC_WRITE;
272 create = CREATE_ALWAYS;
273 if (fd == STDERR_FILENO)
274 flags = FILE_FLAG_WRITE_THROUGH;
279 llvm::ConvertUTF8toWide(path, wpath);
280 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
282 return (result == INVALID_HANDLE_VALUE) ? NULL : result;