xref: /aosp_15_r20/external/cronet/base/process/launch_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/process/launch.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
8*6777b538SAndroid Build Coastguard Worker #include <io.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker // windows.h must be included before shellapi.h
11*6777b538SAndroid Build Coastguard Worker #include <windows.h>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include <psapi.h>
14*6777b538SAndroid Build Coastguard Worker #include <shellapi.h>
15*6777b538SAndroid Build Coastguard Worker #include <userenv.h>
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #include <ios>
18*6777b538SAndroid Build Coastguard Worker #include <limits>
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker #include "base/debug/alias.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/process/environment_internal.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/process/kill.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/system/sys_info.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_thread_priority.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
34*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_handle.h"
35*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_process_information.h"
36*6777b538SAndroid Build Coastguard Worker #include "base/win/startup_information.h"
37*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_version.h"
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker namespace base {
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker namespace {
42*6777b538SAndroid Build Coastguard Worker 
GetAppOutputInternal(CommandLine::StringPieceType cl,bool include_stderr,std::string * output,int * exit_code)43*6777b538SAndroid Build Coastguard Worker bool GetAppOutputInternal(CommandLine::StringPieceType cl,
44*6777b538SAndroid Build Coastguard Worker                           bool include_stderr,
45*6777b538SAndroid Build Coastguard Worker                           std::string* output,
46*6777b538SAndroid Build Coastguard Worker                           int* exit_code) {
47*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "GetAppOutput");
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker   HANDLE out_read = nullptr;
50*6777b538SAndroid Build Coastguard Worker   HANDLE out_write = nullptr;
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker   SECURITY_ATTRIBUTES sa_attr;
53*6777b538SAndroid Build Coastguard Worker   // Set the bInheritHandle flag so pipe handles are inherited.
54*6777b538SAndroid Build Coastguard Worker   sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
55*6777b538SAndroid Build Coastguard Worker   sa_attr.bInheritHandle = TRUE;
56*6777b538SAndroid Build Coastguard Worker   sa_attr.lpSecurityDescriptor = nullptr;
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker   // Create the pipe for the child process's STDOUT.
59*6777b538SAndroid Build Coastguard Worker   if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
60*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Failed to create pipe";
61*6777b538SAndroid Build Coastguard Worker     return false;
62*6777b538SAndroid Build Coastguard Worker   }
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker   // Ensure we don't leak the handles.
65*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle scoped_out_read(out_read);
66*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle scoped_out_write(out_write);
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   // Ensure the read handles to the pipes are not inherited.
69*6777b538SAndroid Build Coastguard Worker   if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
70*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Failed to disabled pipe inheritance";
71*6777b538SAndroid Build Coastguard Worker     return false;
72*6777b538SAndroid Build Coastguard Worker   }
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   FilePath::StringType writable_command_line_string(cl);
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker   STARTUPINFO start_info = {};
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker   start_info.cb = sizeof(STARTUPINFO);
79*6777b538SAndroid Build Coastguard Worker   start_info.hStdOutput = out_write;
80*6777b538SAndroid Build Coastguard Worker   // Keep the normal stdin.
81*6777b538SAndroid Build Coastguard Worker   start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
82*6777b538SAndroid Build Coastguard Worker   if (include_stderr) {
83*6777b538SAndroid Build Coastguard Worker     start_info.hStdError = out_write;
84*6777b538SAndroid Build Coastguard Worker   } else {
85*6777b538SAndroid Build Coastguard Worker     start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
86*6777b538SAndroid Build Coastguard Worker   }
87*6777b538SAndroid Build Coastguard Worker   start_info.dwFlags |= STARTF_USESTDHANDLES;
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   // Create the child process.
90*6777b538SAndroid Build Coastguard Worker   PROCESS_INFORMATION temp_process_info = {};
91*6777b538SAndroid Build Coastguard Worker   if (!CreateProcess(nullptr, data(writable_command_line_string), nullptr,
92*6777b538SAndroid Build Coastguard Worker                      nullptr,
93*6777b538SAndroid Build Coastguard Worker                      TRUE,  // Handles are inherited.
94*6777b538SAndroid Build Coastguard Worker                      0, nullptr, nullptr, &start_info, &temp_process_info)) {
95*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Failed to start process";
96*6777b538SAndroid Build Coastguard Worker     return false;
97*6777b538SAndroid Build Coastguard Worker   }
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   win::ScopedProcessInformation proc_info(temp_process_info);
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   // Close our writing end of pipe now. Otherwise later read would not be able
102*6777b538SAndroid Build Coastguard Worker   // to detect end of child's output.
103*6777b538SAndroid Build Coastguard Worker   scoped_out_write.Close();
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker   // Read output from the child process's pipe for STDOUT
106*6777b538SAndroid Build Coastguard Worker   const int kBufferSize = 1024;
107*6777b538SAndroid Build Coastguard Worker   char buffer[kBufferSize];
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   for (;;) {
110*6777b538SAndroid Build Coastguard Worker     DWORD bytes_read = 0;
111*6777b538SAndroid Build Coastguard Worker     BOOL success =
112*6777b538SAndroid Build Coastguard Worker         ::ReadFile(out_read, buffer, kBufferSize, &bytes_read, nullptr);
113*6777b538SAndroid Build Coastguard Worker     if (!success || bytes_read == 0)
114*6777b538SAndroid Build Coastguard Worker       break;
115*6777b538SAndroid Build Coastguard Worker     output->append(buffer, bytes_read);
116*6777b538SAndroid Build Coastguard Worker   }
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   // Let's wait for the process to finish.
119*6777b538SAndroid Build Coastguard Worker   {
120*6777b538SAndroid Build Coastguard Worker     // It is okay to allow this process to wait on the launched process as a
121*6777b538SAndroid Build Coastguard Worker     // process launched with GetAppOutput*() shouldn't wait back on the process
122*6777b538SAndroid Build Coastguard Worker     // that launched it.
123*6777b538SAndroid Build Coastguard Worker     internal::GetAppOutputScopedAllowBaseSyncPrimitives allow_wait;
124*6777b538SAndroid Build Coastguard Worker     ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
125*6777b538SAndroid Build Coastguard Worker     WaitForSingleObject(proc_info.process_handle(), INFINITE);
126*6777b538SAndroid Build Coastguard Worker   }
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker   TerminationStatus status =
129*6777b538SAndroid Build Coastguard Worker       GetTerminationStatus(proc_info.process_handle(), exit_code);
130*6777b538SAndroid Build Coastguard Worker   return status != TERMINATION_STATUS_PROCESS_CRASHED &&
131*6777b538SAndroid Build Coastguard Worker          status != TERMINATION_STATUS_ABNORMAL_TERMINATION;
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker 
LaunchElevatedProcess(const CommandLine & cmdline,bool start_hidden,bool wait)134*6777b538SAndroid Build Coastguard Worker Process LaunchElevatedProcess(const CommandLine& cmdline,
135*6777b538SAndroid Build Coastguard Worker                               bool start_hidden,
136*6777b538SAndroid Build Coastguard Worker                               bool wait) {
137*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "LaunchElevatedProcess");
138*6777b538SAndroid Build Coastguard Worker   const FilePath::StringType file = cmdline.GetProgram().value();
139*6777b538SAndroid Build Coastguard Worker   const CommandLine::StringType arguments = cmdline.GetArgumentsString();
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   SHELLEXECUTEINFO shex_info = {};
142*6777b538SAndroid Build Coastguard Worker   shex_info.cbSize = sizeof(shex_info);
143*6777b538SAndroid Build Coastguard Worker   shex_info.fMask = SEE_MASK_NOCLOSEPROCESS;
144*6777b538SAndroid Build Coastguard Worker   shex_info.hwnd = GetActiveWindow();
145*6777b538SAndroid Build Coastguard Worker   shex_info.lpVerb = L"runas";
146*6777b538SAndroid Build Coastguard Worker   shex_info.lpFile = file.c_str();
147*6777b538SAndroid Build Coastguard Worker   shex_info.lpParameters = arguments.c_str();
148*6777b538SAndroid Build Coastguard Worker   shex_info.lpDirectory = nullptr;
149*6777b538SAndroid Build Coastguard Worker   shex_info.nShow = start_hidden ? SW_HIDE : SW_SHOWNORMAL;
150*6777b538SAndroid Build Coastguard Worker   shex_info.hInstApp = nullptr;
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker   if (!ShellExecuteEx(&shex_info)) {
153*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR);
154*6777b538SAndroid Build Coastguard Worker     return Process();
155*6777b538SAndroid Build Coastguard Worker   }
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker   if (wait) {
158*6777b538SAndroid Build Coastguard Worker     ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
159*6777b538SAndroid Build Coastguard Worker     WaitForSingleObject(shex_info.hProcess, INFINITE);
160*6777b538SAndroid Build Coastguard Worker   }
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   return Process(shex_info.hProcess);
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker }  // namespace
166*6777b538SAndroid Build Coastguard Worker 
RouteStdioToConsole(bool create_console_if_not_found)167*6777b538SAndroid Build Coastguard Worker void RouteStdioToConsole(bool create_console_if_not_found) {
168*6777b538SAndroid Build Coastguard Worker   // Don't change anything if stdout or stderr already point to a
169*6777b538SAndroid Build Coastguard Worker   // valid stream.
170*6777b538SAndroid Build Coastguard Worker   //
171*6777b538SAndroid Build Coastguard Worker   // If we are running under Buildbot or under Cygwin's default
172*6777b538SAndroid Build Coastguard Worker   // terminal (mintty), stderr and stderr will be pipe handles.  In
173*6777b538SAndroid Build Coastguard Worker   // that case, we don't want to open CONOUT$, because its output
174*6777b538SAndroid Build Coastguard Worker   // likely does not go anywhere.
175*6777b538SAndroid Build Coastguard Worker   //
176*6777b538SAndroid Build Coastguard Worker   // We don't use GetStdHandle() to check stdout/stderr here because
177*6777b538SAndroid Build Coastguard Worker   // it can return dangling IDs of handles that were never inherited
178*6777b538SAndroid Build Coastguard Worker   // by this process.  These IDs could have been reused by the time
179*6777b538SAndroid Build Coastguard Worker   // this function is called.  The CRT checks the validity of
180*6777b538SAndroid Build Coastguard Worker   // stdout/stderr on startup (before the handle IDs can be reused).
181*6777b538SAndroid Build Coastguard Worker   // _fileno(stdout) will return -2 (_NO_CONSOLE_FILENO) if stdout was
182*6777b538SAndroid Build Coastguard Worker   // invalid.
183*6777b538SAndroid Build Coastguard Worker   if (_fileno(stdout) >= 0 || _fileno(stderr) >= 0) {
184*6777b538SAndroid Build Coastguard Worker     // _fileno was broken for SUBSYSTEM:WINDOWS from VS2010 to VS2012/2013.
185*6777b538SAndroid Build Coastguard Worker     // http://crbug.com/358267. Confirm that the underlying HANDLE is valid
186*6777b538SAndroid Build Coastguard Worker     // before aborting.
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker     intptr_t stdout_handle = _get_osfhandle(_fileno(stdout));
189*6777b538SAndroid Build Coastguard Worker     intptr_t stderr_handle = _get_osfhandle(_fileno(stderr));
190*6777b538SAndroid Build Coastguard Worker     if (stdout_handle >= 0 || stderr_handle >= 0)
191*6777b538SAndroid Build Coastguard Worker       return;
192*6777b538SAndroid Build Coastguard Worker   }
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker   if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
195*6777b538SAndroid Build Coastguard Worker     unsigned int result = GetLastError();
196*6777b538SAndroid Build Coastguard Worker     // Was probably already attached.
197*6777b538SAndroid Build Coastguard Worker     if (result == ERROR_ACCESS_DENIED)
198*6777b538SAndroid Build Coastguard Worker       return;
199*6777b538SAndroid Build Coastguard Worker     // Don't bother creating a new console for each child process if the
200*6777b538SAndroid Build Coastguard Worker     // parent process is invalid (eg: crashed).
201*6777b538SAndroid Build Coastguard Worker     if (result == ERROR_GEN_FAILURE)
202*6777b538SAndroid Build Coastguard Worker       return;
203*6777b538SAndroid Build Coastguard Worker     if (create_console_if_not_found) {
204*6777b538SAndroid Build Coastguard Worker       // Make a new console if attaching to parent fails with any other error.
205*6777b538SAndroid Build Coastguard Worker       // It should be ERROR_INVALID_HANDLE at this point, which means the
206*6777b538SAndroid Build Coastguard Worker       // browser was likely not started from a console.
207*6777b538SAndroid Build Coastguard Worker       AllocConsole();
208*6777b538SAndroid Build Coastguard Worker     } else {
209*6777b538SAndroid Build Coastguard Worker       return;
210*6777b538SAndroid Build Coastguard Worker     }
211*6777b538SAndroid Build Coastguard Worker   }
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker   // Arbitrary byte count to use when buffering output lines.  More
214*6777b538SAndroid Build Coastguard Worker   // means potential waste, less means more risk of interleaved
215*6777b538SAndroid Build Coastguard Worker   // log-lines in output.
216*6777b538SAndroid Build Coastguard Worker   enum { kOutputBufferSize = 64 * 1024 };
217*6777b538SAndroid Build Coastguard Worker 
218*6777b538SAndroid Build Coastguard Worker   if (freopen("CONOUT$", "w", stdout)) {
219*6777b538SAndroid Build Coastguard Worker     setvbuf(stdout, nullptr, _IOLBF, kOutputBufferSize);
220*6777b538SAndroid Build Coastguard Worker     // Overwrite FD 1 for the benefit of any code that uses this FD
221*6777b538SAndroid Build Coastguard Worker     // directly.  This is safe because the CRT allocates FDs 0, 1 and
222*6777b538SAndroid Build Coastguard Worker     // 2 at startup even if they don't have valid underlying Windows
223*6777b538SAndroid Build Coastguard Worker     // handles.  This means we won't be overwriting an FD created by
224*6777b538SAndroid Build Coastguard Worker     // _open() after startup.
225*6777b538SAndroid Build Coastguard Worker     _dup2(_fileno(stdout), 1);
226*6777b538SAndroid Build Coastguard Worker   }
227*6777b538SAndroid Build Coastguard Worker   if (freopen("CONOUT$", "w", stderr)) {
228*6777b538SAndroid Build Coastguard Worker     setvbuf(stderr, nullptr, _IOLBF, kOutputBufferSize);
229*6777b538SAndroid Build Coastguard Worker     _dup2(_fileno(stderr), 2);
230*6777b538SAndroid Build Coastguard Worker   }
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog.
233*6777b538SAndroid Build Coastguard Worker   std::ios::sync_with_stdio();
234*6777b538SAndroid Build Coastguard Worker }
235*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const CommandLine & cmdline,const LaunchOptions & options)236*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const CommandLine& cmdline,
237*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
238*6777b538SAndroid Build Coastguard Worker   if (options.elevated)
239*6777b538SAndroid Build Coastguard Worker     return LaunchElevatedProcess(cmdline, options.start_hidden, options.wait);
240*6777b538SAndroid Build Coastguard Worker   return LaunchProcess(cmdline.GetCommandLineString(), options);
241*6777b538SAndroid Build Coastguard Worker }
242*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const CommandLine::StringType & cmdline,const LaunchOptions & options)243*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const CommandLine::StringType& cmdline,
244*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
245*6777b538SAndroid Build Coastguard Worker   // Retain the command line on the stack for investigating shutdown hangs
246*6777b538SAndroid Build Coastguard Worker   // tracked in https://crbug.com/1431378
247*6777b538SAndroid Build Coastguard Worker   DEBUG_ALIAS_FOR_WCHARCSTR(cmdline_for_debugging, cmdline.c_str(), 200);
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker   if (options.elevated) {
250*6777b538SAndroid Build Coastguard Worker     return LaunchElevatedProcess(base::CommandLine::FromString(cmdline),
251*6777b538SAndroid Build Coastguard Worker                                  options.start_hidden, options.wait);
252*6777b538SAndroid Build Coastguard Worker   }
253*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "LaunchProcess");
254*6777b538SAndroid Build Coastguard Worker   // Mitigate the issues caused by loading DLLs on a background thread
255*6777b538SAndroid Build Coastguard Worker   // (http://crbug/973868).
256*6777b538SAndroid Build Coastguard Worker   SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker   // |process_mitigations| must outlive |startup_info_wrapper|.
259*6777b538SAndroid Build Coastguard Worker   DWORD64 process_mitigations[2]{0, 0};
260*6777b538SAndroid Build Coastguard Worker   win::StartupInformation startup_info_wrapper;
261*6777b538SAndroid Build Coastguard Worker   STARTUPINFO* startup_info = startup_info_wrapper.startup_info();
262*6777b538SAndroid Build Coastguard Worker   DWORD flags = 0;
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker   // Count extended attributes before reserving space.
265*6777b538SAndroid Build Coastguard Worker   DWORD attribute_count = 0;
266*6777b538SAndroid Build Coastguard Worker   // Count PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY.
267*6777b538SAndroid Build Coastguard Worker   if (options.disable_cetcompat &&
268*6777b538SAndroid Build Coastguard Worker       base::win::GetVersion() >= base::win::Version::WIN10_20H1) {
269*6777b538SAndroid Build Coastguard Worker     ++attribute_count;
270*6777b538SAndroid Build Coastguard Worker   }
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker   // Count PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
273*6777b538SAndroid Build Coastguard Worker   if (!options.handles_to_inherit.empty())
274*6777b538SAndroid Build Coastguard Worker     ++attribute_count;
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker   // Reserve space for attributes.
277*6777b538SAndroid Build Coastguard Worker   if (attribute_count > 0) {
278*6777b538SAndroid Build Coastguard Worker     if (!startup_info_wrapper.InitializeProcThreadAttributeList(
279*6777b538SAndroid Build Coastguard Worker             attribute_count)) {
280*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR);
281*6777b538SAndroid Build Coastguard Worker       return Process();
282*6777b538SAndroid Build Coastguard Worker     }
283*6777b538SAndroid Build Coastguard Worker     flags |= EXTENDED_STARTUPINFO_PRESENT;
284*6777b538SAndroid Build Coastguard Worker   }
285*6777b538SAndroid Build Coastguard Worker 
286*6777b538SAndroid Build Coastguard Worker   // Set PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY.
287*6777b538SAndroid Build Coastguard Worker   if (options.disable_cetcompat &&
288*6777b538SAndroid Build Coastguard Worker       base::win::GetVersion() >= base::win::Version::WIN10_20H1) {
289*6777b538SAndroid Build Coastguard Worker     DCHECK_GT(attribute_count, 0u);
290*6777b538SAndroid Build Coastguard Worker     process_mitigations[1] |=
291*6777b538SAndroid Build Coastguard Worker         PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_ALWAYS_OFF;
292*6777b538SAndroid Build Coastguard Worker     if (!startup_info_wrapper.UpdateProcThreadAttribute(
293*6777b538SAndroid Build Coastguard Worker             PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &process_mitigations[0],
294*6777b538SAndroid Build Coastguard Worker             sizeof(process_mitigations))) {
295*6777b538SAndroid Build Coastguard Worker       return Process();
296*6777b538SAndroid Build Coastguard Worker     }
297*6777b538SAndroid Build Coastguard Worker   }
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker   // Set PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
300*6777b538SAndroid Build Coastguard Worker   bool inherit_handles = options.inherit_mode == LaunchOptions::Inherit::kAll;
301*6777b538SAndroid Build Coastguard Worker   if (!options.handles_to_inherit.empty()) {
302*6777b538SAndroid Build Coastguard Worker     DCHECK_GT(attribute_count, 0u);
303*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(options.inherit_mode, LaunchOptions::Inherit::kSpecific);
304*6777b538SAndroid Build Coastguard Worker 
305*6777b538SAndroid Build Coastguard Worker     if (options.handles_to_inherit.size() >
306*6777b538SAndroid Build Coastguard Worker         std::numeric_limits<DWORD>::max() / sizeof(HANDLE)) {
307*6777b538SAndroid Build Coastguard Worker       DLOG(ERROR) << "Too many handles to inherit.";
308*6777b538SAndroid Build Coastguard Worker       return Process();
309*6777b538SAndroid Build Coastguard Worker     }
310*6777b538SAndroid Build Coastguard Worker 
311*6777b538SAndroid Build Coastguard Worker     // Ensure the handles can be inherited.
312*6777b538SAndroid Build Coastguard Worker     for (HANDLE handle : options.handles_to_inherit) {
313*6777b538SAndroid Build Coastguard Worker       BOOL result = SetHandleInformation(handle, HANDLE_FLAG_INHERIT,
314*6777b538SAndroid Build Coastguard Worker                                          HANDLE_FLAG_INHERIT);
315*6777b538SAndroid Build Coastguard Worker       PCHECK(result);
316*6777b538SAndroid Build Coastguard Worker     }
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker     if (!startup_info_wrapper.UpdateProcThreadAttribute(
319*6777b538SAndroid Build Coastguard Worker             PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
320*6777b538SAndroid Build Coastguard Worker             const_cast<HANDLE*>(&options.handles_to_inherit[0]),
321*6777b538SAndroid Build Coastguard Worker             static_cast<DWORD>(options.handles_to_inherit.size() *
322*6777b538SAndroid Build Coastguard Worker                                sizeof(HANDLE)))) {
323*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR);
324*6777b538SAndroid Build Coastguard Worker       return Process();
325*6777b538SAndroid Build Coastguard Worker     }
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker     inherit_handles = true;
328*6777b538SAndroid Build Coastguard Worker   }
329*6777b538SAndroid Build Coastguard Worker 
330*6777b538SAndroid Build Coastguard Worker   if (options.feedback_cursor_off)
331*6777b538SAndroid Build Coastguard Worker     startup_info->dwFlags |= STARTF_FORCEOFFFEEDBACK;
332*6777b538SAndroid Build Coastguard Worker   if (options.empty_desktop_name)
333*6777b538SAndroid Build Coastguard Worker     startup_info->lpDesktop = const_cast<wchar_t*>(L"");
334*6777b538SAndroid Build Coastguard Worker   startup_info->dwFlags |= STARTF_USESHOWWINDOW;
335*6777b538SAndroid Build Coastguard Worker   startup_info->wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOWNORMAL;
336*6777b538SAndroid Build Coastguard Worker 
337*6777b538SAndroid Build Coastguard Worker   if (options.stdin_handle || options.stdout_handle || options.stderr_handle) {
338*6777b538SAndroid Build Coastguard Worker     DCHECK(inherit_handles);
339*6777b538SAndroid Build Coastguard Worker     // If an explicit handle inheritance list is not set, require that all
340*6777b538SAndroid Build Coastguard Worker     // stdio handle values be explicitly specified.
341*6777b538SAndroid Build Coastguard Worker     if (options.handles_to_inherit.empty()) {
342*6777b538SAndroid Build Coastguard Worker       CHECK(options.stdin_handle);
343*6777b538SAndroid Build Coastguard Worker       CHECK(options.stdout_handle);
344*6777b538SAndroid Build Coastguard Worker       CHECK(options.stderr_handle);
345*6777b538SAndroid Build Coastguard Worker     }
346*6777b538SAndroid Build Coastguard Worker     startup_info->dwFlags |= STARTF_USESTDHANDLES;
347*6777b538SAndroid Build Coastguard Worker     startup_info->hStdInput = options.stdin_handle;
348*6777b538SAndroid Build Coastguard Worker     startup_info->hStdOutput = options.stdout_handle;
349*6777b538SAndroid Build Coastguard Worker     startup_info->hStdError = options.stderr_handle;
350*6777b538SAndroid Build Coastguard Worker   }
351*6777b538SAndroid Build Coastguard Worker 
352*6777b538SAndroid Build Coastguard Worker   if (options.force_breakaway_from_job_)
353*6777b538SAndroid Build Coastguard Worker     flags |= CREATE_BREAKAWAY_FROM_JOB;
354*6777b538SAndroid Build Coastguard Worker 
355*6777b538SAndroid Build Coastguard Worker   PROCESS_INFORMATION temp_process_info = {};
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker   LPCTSTR current_directory = options.current_directory.empty()
358*6777b538SAndroid Build Coastguard Worker                                   ? nullptr
359*6777b538SAndroid Build Coastguard Worker                                   : options.current_directory.value().c_str();
360*6777b538SAndroid Build Coastguard Worker 
361*6777b538SAndroid Build Coastguard Worker   auto writable_cmdline(cmdline);
362*6777b538SAndroid Build Coastguard Worker   DCHECK(!(flags & CREATE_SUSPENDED))
363*6777b538SAndroid Build Coastguard Worker       << "Creating a suspended process can lead to hung processes if the "
364*6777b538SAndroid Build Coastguard Worker       << "launching process is killed before it assigns the process to the"
365*6777b538SAndroid Build Coastguard Worker       << "job. https://crbug.com/820996";
366*6777b538SAndroid Build Coastguard Worker   if (options.as_user) {
367*6777b538SAndroid Build Coastguard Worker     flags |= CREATE_UNICODE_ENVIRONMENT;
368*6777b538SAndroid Build Coastguard Worker     void* environment_block = nullptr;
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker     if (!CreateEnvironmentBlock(&environment_block, options.as_user, FALSE)) {
371*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR);
372*6777b538SAndroid Build Coastguard Worker       return Process();
373*6777b538SAndroid Build Coastguard Worker     }
374*6777b538SAndroid Build Coastguard Worker 
375*6777b538SAndroid Build Coastguard Worker     // Environment options are not implemented for use with |as_user|.
376*6777b538SAndroid Build Coastguard Worker     DCHECK(!options.clear_environment);
377*6777b538SAndroid Build Coastguard Worker     DCHECK(options.environment.empty());
378*6777b538SAndroid Build Coastguard Worker 
379*6777b538SAndroid Build Coastguard Worker     BOOL launched = CreateProcessAsUser(
380*6777b538SAndroid Build Coastguard Worker         options.as_user, nullptr, data(writable_cmdline), nullptr, nullptr,
381*6777b538SAndroid Build Coastguard Worker         inherit_handles, flags, environment_block, current_directory,
382*6777b538SAndroid Build Coastguard Worker         startup_info, &temp_process_info);
383*6777b538SAndroid Build Coastguard Worker     DestroyEnvironmentBlock(environment_block);
384*6777b538SAndroid Build Coastguard Worker     if (!launched) {
385*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR) << "Command line:" << std::endl
386*6777b538SAndroid Build Coastguard Worker                    << WideToUTF8(cmdline) << std::endl;
387*6777b538SAndroid Build Coastguard Worker       return Process();
388*6777b538SAndroid Build Coastguard Worker     }
389*6777b538SAndroid Build Coastguard Worker   } else {
390*6777b538SAndroid Build Coastguard Worker     wchar_t* new_environment = nullptr;
391*6777b538SAndroid Build Coastguard Worker     std::wstring env_storage;
392*6777b538SAndroid Build Coastguard Worker     if (options.clear_environment || !options.environment.empty()) {
393*6777b538SAndroid Build Coastguard Worker       if (options.clear_environment) {
394*6777b538SAndroid Build Coastguard Worker         static const wchar_t kEmptyEnvironment[] = {0};
395*6777b538SAndroid Build Coastguard Worker         env_storage =
396*6777b538SAndroid Build Coastguard Worker             internal::AlterEnvironment(kEmptyEnvironment, options.environment);
397*6777b538SAndroid Build Coastguard Worker       } else {
398*6777b538SAndroid Build Coastguard Worker         wchar_t* old_environment = GetEnvironmentStrings();
399*6777b538SAndroid Build Coastguard Worker         if (!old_environment) {
400*6777b538SAndroid Build Coastguard Worker           DPLOG(ERROR);
401*6777b538SAndroid Build Coastguard Worker           return Process();
402*6777b538SAndroid Build Coastguard Worker         }
403*6777b538SAndroid Build Coastguard Worker         env_storage =
404*6777b538SAndroid Build Coastguard Worker             internal::AlterEnvironment(old_environment, options.environment);
405*6777b538SAndroid Build Coastguard Worker         FreeEnvironmentStrings(old_environment);
406*6777b538SAndroid Build Coastguard Worker       }
407*6777b538SAndroid Build Coastguard Worker       new_environment = data(env_storage);
408*6777b538SAndroid Build Coastguard Worker       flags |= CREATE_UNICODE_ENVIRONMENT;
409*6777b538SAndroid Build Coastguard Worker     }
410*6777b538SAndroid Build Coastguard Worker 
411*6777b538SAndroid Build Coastguard Worker     if (!CreateProcess(nullptr, data(writable_cmdline), nullptr, nullptr,
412*6777b538SAndroid Build Coastguard Worker                        inherit_handles, flags, new_environment,
413*6777b538SAndroid Build Coastguard Worker                        current_directory, startup_info, &temp_process_info)) {
414*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR) << "Command line:" << std::endl << cmdline << std::endl;
415*6777b538SAndroid Build Coastguard Worker       return Process();
416*6777b538SAndroid Build Coastguard Worker     }
417*6777b538SAndroid Build Coastguard Worker   }
418*6777b538SAndroid Build Coastguard Worker   win::ScopedProcessInformation process_info(temp_process_info);
419*6777b538SAndroid Build Coastguard Worker 
420*6777b538SAndroid Build Coastguard Worker   if (options.job_handle &&
421*6777b538SAndroid Build Coastguard Worker       !AssignProcessToJobObject(options.job_handle,
422*6777b538SAndroid Build Coastguard Worker                                 process_info.process_handle())) {
423*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Could not AssignProcessToObject";
424*6777b538SAndroid Build Coastguard Worker     Process scoped_process(process_info.TakeProcessHandle());
425*6777b538SAndroid Build Coastguard Worker     scoped_process.Terminate(win::kProcessKilledExitCode, true);
426*6777b538SAndroid Build Coastguard Worker     return Process();
427*6777b538SAndroid Build Coastguard Worker   }
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker   if (options.grant_foreground_privilege &&
430*6777b538SAndroid Build Coastguard Worker       !AllowSetForegroundWindow(GetProcId(process_info.process_handle()))) {
431*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Failed to grant foreground privilege to launched process";
432*6777b538SAndroid Build Coastguard Worker   }
433*6777b538SAndroid Build Coastguard Worker 
434*6777b538SAndroid Build Coastguard Worker   if (options.wait) {
435*6777b538SAndroid Build Coastguard Worker     ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
436*6777b538SAndroid Build Coastguard Worker     WaitForSingleObject(process_info.process_handle(), INFINITE);
437*6777b538SAndroid Build Coastguard Worker   }
438*6777b538SAndroid Build Coastguard Worker 
439*6777b538SAndroid Build Coastguard Worker   return Process(process_info.TakeProcessHandle());
440*6777b538SAndroid Build Coastguard Worker }
441*6777b538SAndroid Build Coastguard Worker 
SetJobObjectLimitFlags(HANDLE job_object,DWORD limit_flags)442*6777b538SAndroid Build Coastguard Worker bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) {
443*6777b538SAndroid Build Coastguard Worker   JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {};
444*6777b538SAndroid Build Coastguard Worker   limit_info.BasicLimitInformation.LimitFlags = limit_flags;
445*6777b538SAndroid Build Coastguard Worker   return 0 != SetInformationJobObject(
446*6777b538SAndroid Build Coastguard Worker       job_object,
447*6777b538SAndroid Build Coastguard Worker       JobObjectExtendedLimitInformation,
448*6777b538SAndroid Build Coastguard Worker       &limit_info,
449*6777b538SAndroid Build Coastguard Worker       sizeof(limit_info));
450*6777b538SAndroid Build Coastguard Worker }
451*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const CommandLine & cl,std::string * output)452*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const CommandLine& cl, std::string* output) {
453*6777b538SAndroid Build Coastguard Worker   return GetAppOutput(cl.GetCommandLineString(), output);
454*6777b538SAndroid Build Coastguard Worker }
455*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const CommandLine & cl,std::string * output)456*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
457*6777b538SAndroid Build Coastguard Worker   int exit_code;
458*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(
459*6777b538SAndroid Build Coastguard Worker       cl.GetCommandLineString(), true, output, &exit_code);
460*6777b538SAndroid Build Coastguard Worker }
461*6777b538SAndroid Build Coastguard Worker 
GetAppOutputWithExitCode(const CommandLine & cl,std::string * output,int * exit_code)462*6777b538SAndroid Build Coastguard Worker bool GetAppOutputWithExitCode(const CommandLine& cl,
463*6777b538SAndroid Build Coastguard Worker                               std::string* output,
464*6777b538SAndroid Build Coastguard Worker                               int* exit_code) {
465*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(
466*6777b538SAndroid Build Coastguard Worker       cl.GetCommandLineString(), false, output, exit_code);
467*6777b538SAndroid Build Coastguard Worker }
468*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(CommandLine::StringPieceType cl,std::string * output)469*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(CommandLine::StringPieceType cl, std::string* output) {
470*6777b538SAndroid Build Coastguard Worker   int exit_code;
471*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(cl, false, output, &exit_code);
472*6777b538SAndroid Build Coastguard Worker }
473*6777b538SAndroid Build Coastguard Worker 
RaiseProcessToHighPriority()474*6777b538SAndroid Build Coastguard Worker void RaiseProcessToHighPriority() {
475*6777b538SAndroid Build Coastguard Worker   SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker 
478*6777b538SAndroid Build Coastguard Worker }  // namespace base
479