Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: base/process/launch_win.cc

Issue 1809383004: Set current directory when launching Native Messaging processes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/process/launch.h ('k') | base/process/process_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/process/launch.h" 5 #include "base/process/launch.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <io.h> 8 #include <io.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #include <windows.h> 10 #include <windows.h>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 // process. It's value is obviously not that unique, and it's 42 // process. It's value is obviously not that unique, and it's
43 // surprising to me that the task manager uses this value, but it 43 // surprising to me that the task manager uses this value, but it
44 // seems to be common practice on Windows to test for it as an 44 // seems to be common practice on Windows to test for it as an
45 // indication that the task manager has killed something if the 45 // indication that the task manager has killed something if the
46 // process goes away. 46 // process goes away.
47 const DWORD kProcessKilledExitCode = 1; 47 const DWORD kProcessKilledExitCode = 1;
48 48
49 bool GetAppOutputInternal(const StringPiece16& cl, 49 bool GetAppOutputInternal(const StringPiece16& cl,
50 bool include_stderr, 50 bool include_stderr,
51 std::string* output) { 51 std::string* output) {
52 HANDLE out_read = NULL; 52 HANDLE out_read = nullptr;
53 HANDLE out_write = NULL; 53 HANDLE out_write = nullptr;
54 54
55 SECURITY_ATTRIBUTES sa_attr; 55 SECURITY_ATTRIBUTES sa_attr;
56 // Set the bInheritHandle flag so pipe handles are inherited. 56 // Set the bInheritHandle flag so pipe handles are inherited.
57 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); 57 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
58 sa_attr.bInheritHandle = TRUE; 58 sa_attr.bInheritHandle = TRUE;
59 sa_attr.lpSecurityDescriptor = NULL; 59 sa_attr.lpSecurityDescriptor = nullptr;
60 60
61 // Create the pipe for the child process's STDOUT. 61 // Create the pipe for the child process's STDOUT.
62 if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) { 62 if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
63 NOTREACHED() << "Failed to create pipe"; 63 NOTREACHED() << "Failed to create pipe";
64 return false; 64 return false;
65 } 65 }
66 66
67 // Ensure we don't leak the handles. 67 // Ensure we don't leak the handles.
68 win::ScopedHandle scoped_out_read(out_read); 68 win::ScopedHandle scoped_out_read(out_read);
69 win::ScopedHandle scoped_out_write(out_write); 69 win::ScopedHandle scoped_out_write(out_write);
(...skipping 15 matching lines...) Expand all
85 start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 85 start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
86 if (include_stderr) { 86 if (include_stderr) {
87 start_info.hStdError = out_write; 87 start_info.hStdError = out_write;
88 } else { 88 } else {
89 start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); 89 start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
90 } 90 }
91 start_info.dwFlags |= STARTF_USESTDHANDLES; 91 start_info.dwFlags |= STARTF_USESTDHANDLES;
92 92
93 // Create the child process. 93 // Create the child process.
94 PROCESS_INFORMATION temp_process_info = {}; 94 PROCESS_INFORMATION temp_process_info = {};
95 if (!CreateProcess(NULL, 95 if (!CreateProcess(nullptr, &writable_command_line_string[0], nullptr,
96 &writable_command_line_string[0], 96 nullptr,
97 NULL, NULL,
98 TRUE, // Handles are inherited. 97 TRUE, // Handles are inherited.
99 0, NULL, NULL, &start_info, &temp_process_info)) { 98 0, nullptr, nullptr, &start_info, &temp_process_info)) {
100 NOTREACHED() << "Failed to start process"; 99 NOTREACHED() << "Failed to start process";
101 return false; 100 return false;
102 } 101 }
103 base::win::ScopedProcessInformation proc_info(temp_process_info); 102 base::win::ScopedProcessInformation proc_info(temp_process_info);
104 103
105 // Close our writing end of pipe now. Otherwise later read would not be able 104 // Close our writing end of pipe now. Otherwise later read would not be able
106 // to detect end of child's output. 105 // to detect end of child's output.
107 scoped_out_write.Close(); 106 scoped_out_write.Close();
108 107
109 // Read output from the child process's pipe for STDOUT 108 // Read output from the child process's pipe for STDOUT
110 const int kBufferSize = 1024; 109 const int kBufferSize = 1024;
111 char buffer[kBufferSize]; 110 char buffer[kBufferSize];
112 111
113 for (;;) { 112 for (;;) {
114 DWORD bytes_read = 0; 113 DWORD bytes_read = 0;
115 BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL); 114 BOOL success =
115 ReadFile(out_read, buffer, kBufferSize, &bytes_read, nullptr);
116 if (!success || bytes_read == 0) 116 if (!success || bytes_read == 0)
117 break; 117 break;
118 output->append(buffer, bytes_read); 118 output->append(buffer, bytes_read);
119 } 119 }
120 120
121 // Let's wait for the process to finish. 121 // Let's wait for the process to finish.
122 WaitForSingleObject(proc_info.process_handle(), INFINITE); 122 WaitForSingleObject(proc_info.process_handle(), INFINITE);
123 123
124 int exit_code; 124 int exit_code;
125 base::TerminationStatus status = GetTerminationStatus( 125 base::TerminationStatus status = GetTerminationStatus(
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 return; 181 return;
182 } 182 }
183 } 183 }
184 184
185 // Arbitrary byte count to use when buffering output lines. More 185 // Arbitrary byte count to use when buffering output lines. More
186 // means potential waste, less means more risk of interleaved 186 // means potential waste, less means more risk of interleaved
187 // log-lines in output. 187 // log-lines in output.
188 enum { kOutputBufferSize = 64 * 1024 }; 188 enum { kOutputBufferSize = 64 * 1024 };
189 189
190 if (freopen("CONOUT$", "w", stdout)) { 190 if (freopen("CONOUT$", "w", stdout)) {
191 setvbuf(stdout, NULL, _IOLBF, kOutputBufferSize); 191 setvbuf(stdout, nullptr, _IOLBF, kOutputBufferSize);
192 // Overwrite FD 1 for the benefit of any code that uses this FD 192 // Overwrite FD 1 for the benefit of any code that uses this FD
193 // directly. This is safe because the CRT allocates FDs 0, 1 and 193 // directly. This is safe because the CRT allocates FDs 0, 1 and
194 // 2 at startup even if they don't have valid underlying Windows 194 // 2 at startup even if they don't have valid underlying Windows
195 // handles. This means we won't be overwriting an FD created by 195 // handles. This means we won't be overwriting an FD created by
196 // _open() after startup. 196 // _open() after startup.
197 _dup2(_fileno(stdout), 1); 197 _dup2(_fileno(stdout), 1);
198 } 198 }
199 if (freopen("CONOUT$", "w", stderr)) { 199 if (freopen("CONOUT$", "w", stderr)) {
200 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); 200 setvbuf(stderr, nullptr, _IOLBF, kOutputBufferSize);
201 _dup2(_fileno(stderr), 2); 201 _dup2(_fileno(stderr), 2);
202 } 202 }
203 203
204 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. 204 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog.
205 std::ios::sync_with_stdio(); 205 std::ios::sync_with_stdio();
206 } 206 }
207 207
208 Process LaunchProcess(const CommandLine& cmdline, 208 Process LaunchProcess(const CommandLine& cmdline,
209 const LaunchOptions& options) { 209 const LaunchOptions& options) {
210 return LaunchProcess(cmdline.GetCommandLineString(), options); 210 return LaunchProcess(cmdline.GetCommandLineString(), options);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 // releases that do not support nested jobs. 283 // releases that do not support nested jobs.
284 if (win::GetVersion() < win::VERSION_WIN8) 284 if (win::GetVersion() < win::VERSION_WIN8)
285 flags |= CREATE_BREAKAWAY_FROM_JOB; 285 flags |= CREATE_BREAKAWAY_FROM_JOB;
286 } 286 }
287 287
288 if (options.force_breakaway_from_job_) 288 if (options.force_breakaway_from_job_)
289 flags |= CREATE_BREAKAWAY_FROM_JOB; 289 flags |= CREATE_BREAKAWAY_FROM_JOB;
290 290
291 PROCESS_INFORMATION temp_process_info = {}; 291 PROCESS_INFORMATION temp_process_info = {};
292 292
293 LPCTSTR current_directory = options.current_directory.empty()
294 ? nullptr
295 : options.current_directory.value().c_str();
296
293 string16 writable_cmdline(cmdline); 297 string16 writable_cmdline(cmdline);
294 if (options.as_user) { 298 if (options.as_user) {
295 flags |= CREATE_UNICODE_ENVIRONMENT; 299 flags |= CREATE_UNICODE_ENVIRONMENT;
296 void* enviroment_block = NULL; 300 void* enviroment_block = nullptr;
297 301
298 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { 302 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) {
299 DPLOG(ERROR); 303 DPLOG(ERROR);
300 return Process(); 304 return Process();
301 } 305 }
302 306
303 BOOL launched = 307 BOOL launched = CreateProcessAsUser(
304 CreateProcessAsUser(options.as_user, NULL, 308 options.as_user, nullptr, &writable_cmdline[0], nullptr, nullptr,
305 &writable_cmdline[0], 309 inherit_handles, flags, enviroment_block, current_directory,
306 NULL, NULL, inherit_handles, flags, 310 startup_info, &temp_process_info);
307 enviroment_block, NULL, startup_info,
308 &temp_process_info);
309 DestroyEnvironmentBlock(enviroment_block); 311 DestroyEnvironmentBlock(enviroment_block);
310 if (!launched) { 312 if (!launched) {
311 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline) 313 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline)
312 << std::endl; 314 << std::endl;
313 return Process(); 315 return Process();
314 } 316 }
315 } else { 317 } else {
316 if (!CreateProcess(NULL, 318 if (!CreateProcess(nullptr, &writable_cmdline[0], nullptr, nullptr,
317 &writable_cmdline[0], NULL, NULL, 319 inherit_handles, flags, nullptr, current_directory,
318 inherit_handles, flags, NULL, NULL,
319 startup_info, &temp_process_info)) { 320 startup_info, &temp_process_info)) {
320 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline) 321 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline)
321 << std::endl; 322 << std::endl;
322 return Process(); 323 return Process();
323 } 324 }
324 } 325 }
325 base::win::ScopedProcessInformation process_info(temp_process_info); 326 base::win::ScopedProcessInformation process_info(temp_process_info);
326 327
327 if (options.job_handle) { 328 if (options.job_handle) {
328 if (0 == AssignProcessToJobObject(options.job_handle, 329 if (0 == AssignProcessToJobObject(options.job_handle,
(...skipping 18 matching lines...) Expand all
347 const string16 file = cmdline.GetProgram().value(); 348 const string16 file = cmdline.GetProgram().value();
348 const string16 arguments = cmdline.GetArgumentsString(); 349 const string16 arguments = cmdline.GetArgumentsString();
349 350
350 SHELLEXECUTEINFO shex_info = {}; 351 SHELLEXECUTEINFO shex_info = {};
351 shex_info.cbSize = sizeof(shex_info); 352 shex_info.cbSize = sizeof(shex_info);
352 shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; 353 shex_info.fMask = SEE_MASK_NOCLOSEPROCESS;
353 shex_info.hwnd = GetActiveWindow(); 354 shex_info.hwnd = GetActiveWindow();
354 shex_info.lpVerb = L"runas"; 355 shex_info.lpVerb = L"runas";
355 shex_info.lpFile = file.c_str(); 356 shex_info.lpFile = file.c_str();
356 shex_info.lpParameters = arguments.c_str(); 357 shex_info.lpParameters = arguments.c_str();
357 shex_info.lpDirectory = NULL; 358 shex_info.lpDirectory = nullptr;
358 shex_info.nShow = options.start_hidden ? SW_HIDE : SW_SHOW; 359 shex_info.nShow = options.start_hidden ? SW_HIDE : SW_SHOW;
359 shex_info.hInstApp = NULL; 360 shex_info.hInstApp = nullptr;
360 361
361 if (!ShellExecuteEx(&shex_info)) { 362 if (!ShellExecuteEx(&shex_info)) {
362 DPLOG(ERROR); 363 DPLOG(ERROR);
363 return Process(); 364 return Process();
364 } 365 }
365 366
366 if (options.wait) 367 if (options.wait)
367 WaitForSingleObject(shex_info.hProcess, INFINITE); 368 WaitForSingleObject(shex_info.hProcess, INFINITE);
368 369
369 return Process(shex_info.hProcess); 370 return Process(shex_info.hProcess);
(...skipping 19 matching lines...) Expand all
389 390
390 bool GetAppOutput(const StringPiece16& cl, std::string* output) { 391 bool GetAppOutput(const StringPiece16& cl, std::string* output) {
391 return GetAppOutputInternal(cl, false, output); 392 return GetAppOutputInternal(cl, false, output);
392 } 393 }
393 394
394 void RaiseProcessToHighPriority() { 395 void RaiseProcessToHighPriority() {
395 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 396 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
396 } 397 }
397 398
398 } // namespace base 399 } // namespace base
OLDNEW
« no previous file with comments | « base/process/launch.h ('k') | base/process/process_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698