| OLD | NEW |
| 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 } | 98 } |
| 99 if (freopen("CONOUT$", "w", stderr)) { | 99 if (freopen("CONOUT$", "w", stderr)) { |
| 100 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); | 100 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); |
| 101 _dup2(_fileno(stderr), 2); | 101 _dup2(_fileno(stderr), 2); |
| 102 } | 102 } |
| 103 | 103 |
| 104 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. | 104 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. |
| 105 std::ios::sync_with_stdio(); | 105 std::ios::sync_with_stdio(); |
| 106 } | 106 } |
| 107 | 107 |
| 108 bool LaunchProcess(const string16& cmdline, | 108 Process LaunchProcess(const CommandLine& cmdline, |
| 109 const LaunchOptions& options, | 109 const LaunchOptions& options) { |
| 110 win::ScopedHandle* process_handle) { | 110 return LaunchProcess(cmdline.GetCommandLineString(), options); |
| 111 } |
| 112 |
| 113 Process LaunchProcess(const string16& cmdline, |
| 114 const LaunchOptions& options) { |
| 111 win::StartupInformation startup_info_wrapper; | 115 win::StartupInformation startup_info_wrapper; |
| 112 STARTUPINFO* startup_info = startup_info_wrapper.startup_info(); | 116 STARTUPINFO* startup_info = startup_info_wrapper.startup_info(); |
| 113 | 117 |
| 114 bool inherit_handles = options.inherit_handles; | 118 bool inherit_handles = options.inherit_handles; |
| 115 DWORD flags = 0; | 119 DWORD flags = 0; |
| 116 if (options.handles_to_inherit) { | 120 if (options.handles_to_inherit) { |
| 117 if (options.handles_to_inherit->empty()) { | 121 if (options.handles_to_inherit->empty()) { |
| 118 inherit_handles = false; | 122 inherit_handles = false; |
| 119 } else { | 123 } else { |
| 120 if (base::win::GetVersion() < base::win::VERSION_VISTA) { | 124 if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
| 121 DLOG(ERROR) << "Specifying handles to inherit requires Vista or later."; | 125 DLOG(ERROR) << "Specifying handles to inherit requires Vista or later."; |
| 122 return false; | 126 return Process(); |
| 123 } | 127 } |
| 124 | 128 |
| 125 if (options.handles_to_inherit->size() > | 129 if (options.handles_to_inherit->size() > |
| 126 std::numeric_limits<DWORD>::max() / sizeof(HANDLE)) { | 130 std::numeric_limits<DWORD>::max() / sizeof(HANDLE)) { |
| 127 DLOG(ERROR) << "Too many handles to inherit."; | 131 DLOG(ERROR) << "Too many handles to inherit."; |
| 128 return false; | 132 return Process(); |
| 129 } | 133 } |
| 130 | 134 |
| 131 if (!startup_info_wrapper.InitializeProcThreadAttributeList(1)) { | 135 if (!startup_info_wrapper.InitializeProcThreadAttributeList(1)) { |
| 132 DPLOG(ERROR); | 136 DPLOG(ERROR); |
| 133 return false; | 137 return Process(); |
| 134 } | 138 } |
| 135 | 139 |
| 136 if (!startup_info_wrapper.UpdateProcThreadAttribute( | 140 if (!startup_info_wrapper.UpdateProcThreadAttribute( |
| 137 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, | 141 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, |
| 138 const_cast<HANDLE*>(&options.handles_to_inherit->at(0)), | 142 const_cast<HANDLE*>(&options.handles_to_inherit->at(0)), |
| 139 static_cast<DWORD>(options.handles_to_inherit->size() * | 143 static_cast<DWORD>(options.handles_to_inherit->size() * |
| 140 sizeof(HANDLE)))) { | 144 sizeof(HANDLE)))) { |
| 141 DPLOG(ERROR); | 145 DPLOG(ERROR); |
| 142 return false; | 146 return Process(); |
| 143 } | 147 } |
| 144 | 148 |
| 145 inherit_handles = true; | 149 inherit_handles = true; |
| 146 flags |= EXTENDED_STARTUPINFO_PRESENT; | 150 flags |= EXTENDED_STARTUPINFO_PRESENT; |
| 147 } | 151 } |
| 148 } | 152 } |
| 149 | 153 |
| 150 if (options.empty_desktop_name) | 154 if (options.empty_desktop_name) |
| 151 startup_info->lpDesktop = const_cast<wchar_t*>(L""); | 155 startup_info->lpDesktop = const_cast<wchar_t*>(L""); |
| 152 startup_info->dwFlags = STARTF_USESHOWWINDOW; | 156 startup_info->dwFlags = STARTF_USESHOWWINDOW; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 177 | 181 |
| 178 PROCESS_INFORMATION temp_process_info = {}; | 182 PROCESS_INFORMATION temp_process_info = {}; |
| 179 | 183 |
| 180 string16 writable_cmdline(cmdline); | 184 string16 writable_cmdline(cmdline); |
| 181 if (options.as_user) { | 185 if (options.as_user) { |
| 182 flags |= CREATE_UNICODE_ENVIRONMENT; | 186 flags |= CREATE_UNICODE_ENVIRONMENT; |
| 183 void* enviroment_block = NULL; | 187 void* enviroment_block = NULL; |
| 184 | 188 |
| 185 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { | 189 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { |
| 186 DPLOG(ERROR); | 190 DPLOG(ERROR); |
| 187 return false; | 191 return Process(); |
| 188 } | 192 } |
| 189 | 193 |
| 190 BOOL launched = | 194 BOOL launched = |
| 191 CreateProcessAsUser(options.as_user, NULL, | 195 CreateProcessAsUser(options.as_user, NULL, |
| 192 &writable_cmdline[0], | 196 &writable_cmdline[0], |
| 193 NULL, NULL, inherit_handles, flags, | 197 NULL, NULL, inherit_handles, flags, |
| 194 enviroment_block, NULL, startup_info, | 198 enviroment_block, NULL, startup_info, |
| 195 &temp_process_info); | 199 &temp_process_info); |
| 196 DestroyEnvironmentBlock(enviroment_block); | 200 DestroyEnvironmentBlock(enviroment_block); |
| 197 if (!launched) { | 201 if (!launched) { |
| 198 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline) | 202 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline) |
| 199 << std::endl;; | 203 << std::endl;; |
| 200 return false; | 204 return Process(); |
| 201 } | 205 } |
| 202 } else { | 206 } else { |
| 203 if (!CreateProcess(NULL, | 207 if (!CreateProcess(NULL, |
| 204 &writable_cmdline[0], NULL, NULL, | 208 &writable_cmdline[0], NULL, NULL, |
| 205 inherit_handles, flags, NULL, NULL, | 209 inherit_handles, flags, NULL, NULL, |
| 206 startup_info, &temp_process_info)) { | 210 startup_info, &temp_process_info)) { |
| 207 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline) | 211 DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline) |
| 208 << std::endl;; | 212 << std::endl;; |
| 209 return false; | 213 return Process(); |
| 210 } | 214 } |
| 211 } | 215 } |
| 212 base::win::ScopedProcessInformation process_info(temp_process_info); | 216 base::win::ScopedProcessInformation process_info(temp_process_info); |
| 213 | 217 |
| 214 if (options.job_handle) { | 218 if (options.job_handle) { |
| 215 if (0 == AssignProcessToJobObject(options.job_handle, | 219 if (0 == AssignProcessToJobObject(options.job_handle, |
| 216 process_info.process_handle())) { | 220 process_info.process_handle())) { |
| 217 DLOG(ERROR) << "Could not AssignProcessToObject."; | 221 DLOG(ERROR) << "Could not AssignProcessToObject."; |
| 218 KillProcess(process_info.process_handle(), kProcessKilledExitCode, true); | 222 KillProcess(process_info.process_handle(), kProcessKilledExitCode, true); |
| 219 return false; | 223 return Process(); |
| 220 } | 224 } |
| 221 | 225 |
| 222 ResumeThread(process_info.thread_handle()); | 226 ResumeThread(process_info.thread_handle()); |
| 223 } | 227 } |
| 224 | 228 |
| 225 if (options.wait) | 229 if (options.wait) |
| 226 WaitForSingleObject(process_info.process_handle(), INFINITE); | 230 WaitForSingleObject(process_info.process_handle(), INFINITE); |
| 227 | 231 |
| 228 // If the caller wants the process handle, we won't close it. | 232 return Process(process_info.TakeProcessHandle()); |
| 229 if (process_handle) | |
| 230 process_handle->Set(process_info.TakeProcessHandle()); | |
| 231 | |
| 232 return true; | |
| 233 } | |
| 234 | |
| 235 // TODO(rvargas) crbug.com/416721: Remove this stub after LaunchProcess is | |
| 236 // fully migrated to use Process. | |
| 237 Process LaunchProcess(const string16& cmdline, | |
| 238 const LaunchOptions& options) { | |
| 239 win::ScopedHandle process_handle; | |
| 240 if (LaunchProcess(cmdline, options, &process_handle)) | |
| 241 return Process(process_handle.Take()); | |
| 242 | |
| 243 return Process(); | |
| 244 } | |
| 245 | |
| 246 bool LaunchProcess(const CommandLine& cmdline, | |
| 247 const LaunchOptions& options, | |
| 248 ProcessHandle* process_handle) { | |
| 249 if (!process_handle) | |
| 250 return LaunchProcess(cmdline.GetCommandLineString(), options, NULL); | |
| 251 | |
| 252 win::ScopedHandle process; | |
| 253 bool rv = LaunchProcess(cmdline.GetCommandLineString(), options, &process); | |
| 254 *process_handle = process.Take(); | |
| 255 return rv; | |
| 256 } | |
| 257 | |
| 258 Process LaunchProcess(const CommandLine& cmdline, | |
| 259 const LaunchOptions& options) { | |
| 260 ProcessHandle process_handle; | |
| 261 if (LaunchProcess(cmdline, options, &process_handle)) | |
| 262 return Process(process_handle); | |
| 263 | |
| 264 return Process(); | |
| 265 } | 233 } |
| 266 | 234 |
| 267 Process LaunchElevatedProcess(const CommandLine& cmdline, | 235 Process LaunchElevatedProcess(const CommandLine& cmdline, |
| 268 const LaunchOptions& options) { | 236 const LaunchOptions& options) { |
| 269 const string16 file = cmdline.GetProgram().value(); | 237 const string16 file = cmdline.GetProgram().value(); |
| 270 const string16 arguments = cmdline.GetArgumentsString(); | 238 const string16 arguments = cmdline.GetArgumentsString(); |
| 271 | 239 |
| 272 SHELLEXECUTEINFO shex_info = {0}; | 240 SHELLEXECUTEINFO shex_info = {0}; |
| 273 shex_info.cbSize = sizeof(shex_info); | 241 shex_info.cbSize = sizeof(shex_info); |
| 274 shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; | 242 shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 WaitForSingleObject(proc_info.process_handle(), INFINITE); | 343 WaitForSingleObject(proc_info.process_handle(), INFINITE); |
| 376 | 344 |
| 377 return true; | 345 return true; |
| 378 } | 346 } |
| 379 | 347 |
| 380 void RaiseProcessToHighPriority() { | 348 void RaiseProcessToHighPriority() { |
| 381 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | 349 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); |
| 382 } | 350 } |
| 383 | 351 |
| 384 } // namespace base | 352 } // namespace base |
| OLD | NEW |