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 |