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> |
| 11 #include <psapi.h> | 11 #include <psapi.h> |
| 12 #include <Shellapi.h> | |
| 12 | 13 |
| 13 #include <ios> | 14 #include <ios> |
| 14 | 15 |
| 15 #include "base/bind.h" | 16 #include "base/bind.h" |
| 16 #include "base/bind_helpers.h" | 17 #include "base/bind_helpers.h" |
| 17 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 18 #include "base/debug/stack_trace.h" | 19 #include "base/debug/stack_trace.h" |
| 19 #include "base/logging.h" | 20 #include "base/logging.h" |
| 20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
| 21 #include "base/message_loop/message_loop.h" | 22 #include "base/message_loop/message_loop.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 if (freopen("CONOUT$", "w", stderr)) { | 96 if (freopen("CONOUT$", "w", stderr)) { |
| 96 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); | 97 setvbuf(stderr, NULL, _IOLBF, kOutputBufferSize); |
| 97 _dup2(_fileno(stderr), 2); | 98 _dup2(_fileno(stderr), 2); |
| 98 } | 99 } |
| 99 | 100 |
| 100 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. | 101 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. |
| 101 std::ios::sync_with_stdio(); | 102 std::ios::sync_with_stdio(); |
| 102 } | 103 } |
| 103 | 104 |
| 104 bool LaunchProcess(const string16& cmdline, | 105 bool LaunchProcess(const string16& cmdline, |
| 106 const string16& file, | |
| 107 const string16& arguments, | |
| 105 const LaunchOptions& options, | 108 const LaunchOptions& options, |
| 106 ProcessHandle* process_handle) { | 109 ProcessHandle* process_handle) { |
| 107 STARTUPINFO startup_info = {}; | 110 STARTUPINFO startup_info = {}; |
| 108 startup_info.cb = sizeof(startup_info); | 111 startup_info.cb = sizeof(startup_info); |
| 109 if (options.empty_desktop_name) | 112 if (options.empty_desktop_name) |
| 110 startup_info.lpDesktop = L""; | 113 startup_info.lpDesktop = L""; |
| 111 startup_info.dwFlags = STARTF_USESHOWWINDOW; | 114 startup_info.dwFlags = STARTF_USESHOWWINDOW; |
| 112 startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW; | 115 startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW; |
| 113 | 116 |
| 114 if (options.stdin_handle || options.stdout_handle || options.stderr_handle) { | 117 if (options.stdin_handle || options.stdout_handle || options.stderr_handle) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 131 // automatically associated with a job object created by the debugger. | 134 // automatically associated with a job object created by the debugger. |
| 132 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. | 135 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. |
| 133 flags |= CREATE_BREAKAWAY_FROM_JOB; | 136 flags |= CREATE_BREAKAWAY_FROM_JOB; |
| 134 } | 137 } |
| 135 | 138 |
| 136 if (options.force_breakaway_from_job_) | 139 if (options.force_breakaway_from_job_) |
| 137 flags |= CREATE_BREAKAWAY_FROM_JOB; | 140 flags |= CREATE_BREAKAWAY_FROM_JOB; |
| 138 | 141 |
| 139 base::win::ScopedProcessInformation process_info; | 142 base::win::ScopedProcessInformation process_info; |
| 140 | 143 |
| 141 if (options.as_user) { | 144 if (options.run_elevated) { |
| 142 flags |= CREATE_UNICODE_ENVIRONMENT; | 145 SHELLEXECUTEINFO shex_info = {0}; |
| 143 void* enviroment_block = NULL; | 146 shex_info.cbSize = sizeof(shex_info); |
| 147 shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; | |
| 148 shex_info.hwnd = NULL; | |
|
mef
2013/12/10 15:25:18
We may have to set hwnd to something meaningful, o
| |
| 149 shex_info.lpVerb = L"runas"; | |
| 150 shex_info.lpFile = file.c_str(); | |
| 151 shex_info.lpParameters = arguments.c_str(); | |
| 152 shex_info.lpDirectory = NULL; | |
| 153 shex_info.nShow = SW_HIDE; | |
| 154 shex_info.hInstApp = NULL; | |
| 144 | 155 |
| 145 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { | 156 if (!ShellExecuteEx(&shex_info)) { |
| 146 DPLOG(ERROR); | 157 DPLOG(ERROR); |
| 147 return false; | 158 return false; |
| 148 } | 159 } |
| 149 | 160 |
| 150 BOOL launched = | 161 HANDLE p_handle = shex_info.hProcess; |
| 151 CreateProcessAsUser(options.as_user, NULL, | 162 |
| 152 const_cast<wchar_t*>(cmdline.c_str()), | 163 if (options.wait) |
| 153 NULL, NULL, options.inherit_handles, flags, | 164 WaitForSingleObject(shex_info.hProcess, INFINITE); |
| 154 enviroment_block, NULL, &startup_info, | 165 |
| 155 process_info.Receive()); | 166 // If the caller wants the process handle, we won't close it. |
| 156 DestroyEnvironmentBlock(enviroment_block); | 167 if (process_handle) |
| 157 if (!launched) { | 168 *process_handle = p_handle; |
| 158 DPLOG(ERROR); | 169 |
| 159 return false; | |
| 160 } | |
| 161 } else { | 170 } else { |
| 162 if (!CreateProcess(NULL, | 171 if (options.as_user) { |
| 163 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL, | 172 flags |= CREATE_UNICODE_ENVIRONMENT; |
| 164 options.inherit_handles, flags, NULL, NULL, | 173 void* enviroment_block = NULL; |
| 165 &startup_info, process_info.Receive())) { | |
| 166 DPLOG(ERROR); | |
| 167 return false; | |
| 168 } | |
| 169 } | |
| 170 | 174 |
| 171 if (options.job_handle) { | 175 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) { |
| 172 if (0 == AssignProcessToJobObject(options.job_handle, | 176 DPLOG(ERROR); |
| 173 process_info.process_handle())) { | 177 return false; |
| 174 DLOG(ERROR) << "Could not AssignProcessToObject."; | 178 } |
| 175 KillProcess(process_info.process_handle(), kProcessKilledExitCode, true); | 179 |
| 176 return false; | 180 BOOL launched = |
| 181 CreateProcessAsUser(options.as_user, NULL, | |
| 182 const_cast<wchar_t*>(cmdline.c_str()), | |
| 183 NULL, NULL, options.inherit_handles, flags, | |
| 184 enviroment_block, NULL, &startup_info, | |
| 185 process_info.Receive()); | |
| 186 DestroyEnvironmentBlock(enviroment_block); | |
| 187 if (!launched) { | |
| 188 DPLOG(ERROR); | |
| 189 return false; | |
| 190 } | |
| 191 } else { | |
| 192 if (!CreateProcess(NULL, | |
| 193 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL, | |
| 194 options.inherit_handles, flags, NULL, NULL, | |
| 195 &startup_info, process_info.Receive())) { | |
| 196 DPLOG(ERROR); | |
| 197 return false; | |
| 198 } | |
| 177 } | 199 } |
| 178 | 200 |
| 179 ResumeThread(process_info.thread_handle()); | 201 if (options.job_handle) { |
| 202 if (0 == AssignProcessToJobObject(options.job_handle, | |
| 203 process_info.process_handle())) { | |
| 204 DLOG(ERROR) << "Could not AssignProcessToObject."; | |
| 205 KillProcess(process_info.process_handle(), | |
| 206 kProcessKilledExitCode, | |
| 207 true); | |
| 208 return false; | |
| 209 } | |
| 210 | |
| 211 ResumeThread(process_info.thread_handle()); | |
| 212 } | |
| 213 | |
| 214 if (options.wait) | |
| 215 WaitForSingleObject(process_info.process_handle(), INFINITE); | |
| 216 | |
| 217 // If the caller wants the process handle, we won't close it. | |
| 218 if (process_handle) | |
| 219 *process_handle = process_info.TakeProcessHandle(); | |
| 180 } | 220 } |
| 181 | 221 |
| 182 if (options.wait) | |
| 183 WaitForSingleObject(process_info.process_handle(), INFINITE); | |
| 184 | |
| 185 // If the caller wants the process handle, we won't close it. | |
| 186 if (process_handle) | |
| 187 *process_handle = process_info.TakeProcessHandle(); | |
| 188 | |
| 189 return true; | 222 return true; |
| 190 } | 223 } |
| 191 | 224 |
| 192 bool LaunchProcess(const CommandLine& cmdline, | 225 bool LaunchProcess(const CommandLine& cmdline, |
| 193 const LaunchOptions& options, | 226 const LaunchOptions& options, |
| 194 ProcessHandle* process_handle) { | 227 ProcessHandle* process_handle) { |
| 195 return LaunchProcess(cmdline.GetCommandLineString(), options, process_handle); | 228 return LaunchProcess(cmdline.GetCommandLineString(), |
| 229 cmdline.GetProgram().value(), | |
| 230 cmdline.GetArgumentsString(), | |
| 231 options, process_handle); | |
| 196 } | 232 } |
| 197 | 233 |
| 198 bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) { | 234 bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) { |
| 199 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; | 235 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; |
| 200 limit_info.BasicLimitInformation.LimitFlags = limit_flags; | 236 limit_info.BasicLimitInformation.LimitFlags = limit_flags; |
| 201 return 0 != SetInformationJobObject( | 237 return 0 != SetInformationJobObject( |
| 202 job_object, | 238 job_object, |
| 203 JobObjectExtendedLimitInformation, | 239 JobObjectExtendedLimitInformation, |
| 204 &limit_info, | 240 &limit_info, |
| 205 sizeof(limit_info)); | 241 sizeof(limit_info)); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 WaitForSingleObject(proc_info.process_handle(), INFINITE); | 309 WaitForSingleObject(proc_info.process_handle(), INFINITE); |
| 274 | 310 |
| 275 return true; | 311 return true; |
| 276 } | 312 } |
| 277 | 313 |
| 278 void RaiseProcessToHighPriority() { | 314 void RaiseProcessToHighPriority() { |
| 279 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | 315 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); |
| 280 } | 316 } |
| 281 | 317 |
| 282 } // namespace base | 318 } // namespace base |
| OLD | NEW |