Chromium Code Reviews| 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 <windows.h> | 9 #include <windows.h> |
| 10 #include <userenv.h> | 10 #include <userenv.h> |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); | 96 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); |
| 97 _dup2(_fileno(stderr), 2); | 97 _dup2(_fileno(stderr), 2); |
| 98 } | 98 } |
| 99 | 99 |
| 100 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. | 100 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. |
| 101 std::ios::sync_with_stdio(); | 101 std::ios::sync_with_stdio(); |
| 102 } | 102 } |
| 103 | 103 |
| 104 bool LaunchProcess(const string16& cmdline, | 104 bool LaunchProcess(const string16& cmdline, |
| 105 const LaunchOptions& options, | 105 const LaunchOptions& options, |
| 106 ProcessHandle* process_handle) { | 106 win::ScopedHandle* process_handle) { |
| 107 STARTUPINFO startup_info = {}; | 107 STARTUPINFO startup_info = {}; |
| 108 startup_info.cb = sizeof(startup_info); | 108 startup_info.cb = sizeof(startup_info); |
| 109 if (options.empty_desktop_name) | 109 if (options.empty_desktop_name) |
| 110 startup_info.lpDesktop = L""; | 110 startup_info.lpDesktop = L""; |
| 111 startup_info.dwFlags = STARTF_USESHOWWINDOW; | 111 startup_info.dwFlags = STARTF_USESHOWWINDOW; |
| 112 startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW; | 112 startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW; |
| 113 | 113 |
| 114 if (options.stdin_handle || options.stdout_handle || options.stderr_handle) { | 114 if (options.stdin_handle || options.stdout_handle || options.stderr_handle) { |
| 115 DCHECK(options.inherit_handles); | 115 DCHECK(options.inherit_handles); |
| 116 DCHECK(options.stdin_handle); | 116 DCHECK(options.stdin_handle); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 129 | 129 |
| 130 // If this code is run under a debugger, the launched process is | 130 // If this code is run under a debugger, the launched process is |
| 131 // automatically associated with a job object created by the debugger. | 131 // automatically associated with a job object created by the debugger. |
| 132 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. | 132 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. |
| 133 flags |= CREATE_BREAKAWAY_FROM_JOB; | 133 flags |= CREATE_BREAKAWAY_FROM_JOB; |
| 134 } | 134 } |
| 135 | 135 |
| 136 if (options.force_breakaway_from_job_) | 136 if (options.force_breakaway_from_job_) |
| 137 flags |= CREATE_BREAKAWAY_FROM_JOB; | 137 flags |= CREATE_BREAKAWAY_FROM_JOB; |
| 138 | 138 |
| 139 base::win::ScopedProcessInformation process_info; | 139 PROCESS_INFORMATION temp_process_info = {}; |
| 140 | 140 |
| 141 if (options.as_user) { | 141 if (options.as_user) { |
| 142 flags |= CREATE_UNICODE_ENVIRONMENT; | 142 flags |= CREATE_UNICODE_ENVIRONMENT; |
| 143 void* enviroment_block = NULL; | 143 void* enviroment_block = NULL; |
| 144 | 144 |
| 145 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { | 145 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { |
| 146 DPLOG(ERROR); | 146 DPLOG(ERROR); |
| 147 return false; | 147 return false; |
| 148 } | 148 } |
| 149 | 149 |
| 150 BOOL launched = | 150 BOOL launched = |
| 151 CreateProcessAsUser(options.as_user, NULL, | 151 CreateProcessAsUser(options.as_user, NULL, |
| 152 const_cast<wchar_t*>(cmdline.c_str()), | 152 const_cast<wchar_t*>(cmdline.c_str()), |
| 153 NULL, NULL, options.inherit_handles, flags, | 153 NULL, NULL, options.inherit_handles, flags, |
| 154 enviroment_block, NULL, &startup_info, | 154 enviroment_block, NULL, &startup_info, |
| 155 process_info.Receive()); | 155 &temp_process_info); |
| 156 DestroyEnvironmentBlock(enviroment_block); | 156 DestroyEnvironmentBlock(enviroment_block); |
| 157 if (!launched) { | 157 if (!launched) { |
| 158 DPLOG(ERROR); | 158 DPLOG(ERROR); |
| 159 return false; | 159 return false; |
| 160 } | 160 } |
| 161 } else { | 161 } else { |
| 162 if (!CreateProcess(NULL, | 162 if (!CreateProcess(NULL, |
| 163 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL, | 163 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL, |
| 164 options.inherit_handles, flags, NULL, NULL, | 164 options.inherit_handles, flags, NULL, NULL, |
| 165 &startup_info, process_info.Receive())) { | 165 &startup_info, &temp_process_info)) { |
| 166 DPLOG(ERROR); | 166 DPLOG(ERROR); |
| 167 return false; | 167 return false; |
| 168 } | 168 } |
| 169 } | 169 } |
| 170 base::win::ScopedProcessInformation process_info; | |
| 171 process_info.Set(temp_process_info); | |
|
cpu_(ooo_6.6-7.5)
2013/11/20 02:17:16
can we make it so we can write:
base::win::ScopedP
rvargas (doing something else)
2013/11/20 20:30:47
Done.
| |
| 170 | 172 |
| 171 if (options.job_handle) { | 173 if (options.job_handle) { |
| 172 if (0 == AssignProcessToJobObject(options.job_handle, | 174 if (0 == AssignProcessToJobObject(options.job_handle, |
| 173 process_info.process_handle())) { | 175 process_info.process_handle())) { |
| 174 DLOG(ERROR) << "Could not AssignProcessToObject."; | 176 DLOG(ERROR) << "Could not AssignProcessToObject."; |
| 175 KillProcess(process_info.process_handle(), kProcessKilledExitCode, true); | 177 KillProcess(process_info.process_handle(), kProcessKilledExitCode, true); |
| 176 return false; | 178 return false; |
| 177 } | 179 } |
| 178 | 180 |
| 179 ResumeThread(process_info.thread_handle()); | 181 ResumeThread(process_info.thread_handle()); |
| 180 } | 182 } |
| 181 | 183 |
| 182 if (options.wait) | 184 if (options.wait) |
| 183 WaitForSingleObject(process_info.process_handle(), INFINITE); | 185 WaitForSingleObject(process_info.process_handle(), INFINITE); |
| 184 | 186 |
| 185 // If the caller wants the process handle, we won't close it. | 187 // If the caller wants the process handle, we won't close it. |
| 186 if (process_handle) | 188 if (process_handle) |
| 187 *process_handle = process_info.TakeProcessHandle(); | 189 process_handle->Set(process_info.TakeProcessHandle()); |
| 188 | 190 |
| 189 return true; | 191 return true; |
| 190 } | 192 } |
| 191 | 193 |
| 192 bool LaunchProcess(const CommandLine& cmdline, | 194 bool LaunchProcess(const CommandLine& cmdline, |
| 193 const LaunchOptions& options, | 195 const LaunchOptions& options, |
| 194 ProcessHandle* process_handle) { | 196 ProcessHandle* process_handle) { |
| 195 return LaunchProcess(cmdline.GetCommandLineString(), options, process_handle); | 197 if (!process_handle) |
| 198 return LaunchProcess(cmdline.GetCommandLineString(), options, NULL); | |
| 199 | |
| 200 win::ScopedHandle process; | |
| 201 bool rv = LaunchProcess(cmdline.GetCommandLineString(), options, &process); | |
| 202 *process_handle = process.Take(); | |
| 203 return rv; | |
| 196 } | 204 } |
| 197 | 205 |
| 198 bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) { | 206 bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) { |
| 199 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; | 207 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; |
| 200 limit_info.BasicLimitInformation.LimitFlags = limit_flags; | 208 limit_info.BasicLimitInformation.LimitFlags = limit_flags; |
| 201 return 0 != SetInformationJobObject( | 209 return 0 != SetInformationJobObject( |
| 202 job_object, | 210 job_object, |
| 203 JobObjectExtendedLimitInformation, | 211 JobObjectExtendedLimitInformation, |
| 204 &limit_info, | 212 &limit_info, |
| 205 sizeof(limit_info)); | 213 sizeof(limit_info)); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 226 win::ScopedHandle scoped_out_write(out_write); | 234 win::ScopedHandle scoped_out_write(out_write); |
| 227 | 235 |
| 228 // Ensure the read handle to the pipe for STDOUT is not inherited. | 236 // Ensure the read handle to the pipe for STDOUT is not inherited. |
| 229 if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) { | 237 if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) { |
| 230 NOTREACHED() << "Failed to disabled pipe inheritance"; | 238 NOTREACHED() << "Failed to disabled pipe inheritance"; |
| 231 return false; | 239 return false; |
| 232 } | 240 } |
| 233 | 241 |
| 234 FilePath::StringType writable_command_line_string(cl.GetCommandLineString()); | 242 FilePath::StringType writable_command_line_string(cl.GetCommandLineString()); |
| 235 | 243 |
| 236 base::win::ScopedProcessInformation proc_info; | 244 STARTUPINFO start_info = {}; |
| 237 STARTUPINFO start_info = { 0 }; | |
| 238 | 245 |
| 239 start_info.cb = sizeof(STARTUPINFO); | 246 start_info.cb = sizeof(STARTUPINFO); |
| 240 start_info.hStdOutput = out_write; | 247 start_info.hStdOutput = out_write; |
| 241 // Keep the normal stdin and stderr. | 248 // Keep the normal stdin and stderr. |
| 242 start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); | 249 start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); |
| 243 start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); | 250 start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
| 244 start_info.dwFlags |= STARTF_USESTDHANDLES; | 251 start_info.dwFlags |= STARTF_USESTDHANDLES; |
| 245 | 252 |
| 246 // Create the child process. | 253 // Create the child process. |
| 254 PROCESS_INFORMATION temp_process_info = {}; | |
| 247 if (!CreateProcess(NULL, | 255 if (!CreateProcess(NULL, |
| 248 &writable_command_line_string[0], | 256 &writable_command_line_string[0], |
| 249 NULL, NULL, | 257 NULL, NULL, |
| 250 TRUE, // Handles are inherited. | 258 TRUE, // Handles are inherited. |
| 251 0, NULL, NULL, &start_info, proc_info.Receive())) { | 259 0, NULL, NULL, &start_info, &temp_process_info)) { |
| 252 NOTREACHED() << "Failed to start process"; | 260 NOTREACHED() << "Failed to start process"; |
| 253 return false; | 261 return false; |
| 254 } | 262 } |
| 263 base::win::ScopedProcessInformation proc_info; | |
| 264 proc_info.Set(temp_process_info); | |
| 255 | 265 |
| 256 // Close our writing end of pipe now. Otherwise later read would not be able | 266 // Close our writing end of pipe now. Otherwise later read would not be able |
| 257 // to detect end of child's output. | 267 // to detect end of child's output. |
| 258 scoped_out_write.Close(); | 268 scoped_out_write.Close(); |
| 259 | 269 |
| 260 // Read output from the child process's pipe for STDOUT | 270 // Read output from the child process's pipe for STDOUT |
| 261 const int kBufferSize = 1024; | 271 const int kBufferSize = 1024; |
| 262 char buffer[kBufferSize]; | 272 char buffer[kBufferSize]; |
| 263 | 273 |
| 264 for (;;) { | 274 for (;;) { |
| 265 DWORD bytes_read = 0; | 275 DWORD bytes_read = 0; |
| 266 BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL); | 276 BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL); |
| 267 if (!success || bytes_read == 0) | 277 if (!success || bytes_read == 0) |
| 268 break; | 278 break; |
| 269 output->append(buffer, bytes_read); | 279 output->append(buffer, bytes_read); |
| 270 } | 280 } |
| 271 | 281 |
| 272 // Let's wait for the process to finish. | 282 // Let's wait for the process to finish. |
| 273 WaitForSingleObject(proc_info.process_handle(), INFINITE); | 283 WaitForSingleObject(proc_info.process_handle(), INFINITE); |
| 274 | 284 |
| 275 return true; | 285 return true; |
| 276 } | 286 } |
| 277 | 287 |
| 278 void RaiseProcessToHighPriority() { | 288 void RaiseProcessToHighPriority() { |
| 279 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | 289 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); |
| 280 } | 290 } |
| 281 | 291 |
| 282 } // namespace base | 292 } // namespace base |
| OLD | NEW |