Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/installer-ca/dutil/procutil.cpp

Issue 11521026: initial custom action library, "hello, world" quality (Closed)
Patch Set: Created Sept. 3, 2013, 12:48 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //------------------------------------------------------------------------------ -------------------
2 // <copyright file="procutil.cpp" company="Outercurve Foundation">
3 // Copyright (c) 2004, Outercurve Foundation.
4 // This software is released under Microsoft Reciprocal License (MS-RL).
5 // The license and further copyright text can be found in the file
6 // LICENSE.TXT at the root directory of the distribution.
7 // </copyright>
8 //
9 // <summary>
10 // Process helper functions.
11 // </summary>
12 //------------------------------------------------------------------------------ -------------------
13
14 #include "../precomp.h"
15
16
17 // private functions
18 static HRESULT CreatePipes(
19 __out HANDLE *phOutRead,
20 __out HANDLE *phOutWrite,
21 __out HANDLE *phErrWrite,
22 __out HANDLE *phInRead,
23 __out HANDLE *phInWrite
24 );
25
26 static BOOL CALLBACK CloseWindowEnumCallback(
27 __in HWND hWnd,
28 __in LPARAM lParam
29 );
30
31
32 extern "C" HRESULT DAPI ProcElevated(
33 __in HANDLE hProcess,
34 __out BOOL* pfElevated
35 )
36 {
37 HRESULT hr = S_OK;
38 HANDLE hToken = NULL;
39 TOKEN_ELEVATION tokenElevated = { };
40 DWORD cbToken = 0;
41
42 if (!::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
43 {
44 ExitWithLastError(hr, "Failed to open process token.");
45 }
46
47 if (::GetTokenInformation(hToken, TokenElevation, &tokenElevated, sizeof(TOK EN_ELEVATION), &cbToken))
48 {
49 *pfElevated = (0 != tokenElevated.TokenIsElevated);
50 }
51 else
52 {
53 DWORD er = ::GetLastError();
54 hr = HRESULT_FROM_WIN32(er);
55
56 // If it's invalid argument, this means the OS doesn't support TokenElev ation, so we're not elevated.
57 if (E_INVALIDARG == hr)
58 {
59 *pfElevated = FALSE;
60 hr = S_OK;
61 }
62 else
63 {
64 ExitOnRootFailure(hr, "Failed to get elevation token from process.") ;
65 }
66 }
67
68 LExit:
69 ReleaseHandle(hToken);
70
71 return hr;
72 }
73
74 extern "C" HRESULT DAPI ProcWow64(
75 __in HANDLE hProcess,
76 __out BOOL* pfWow64
77 )
78 {
79 HRESULT hr = S_OK;
80 BOOL fIsWow64 = FALSE;
81
82 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
83 LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)::GetProcAddres s(::GetModuleHandleW(L"kernel32"), "IsWow64Process");
84
85 if (pfnIsWow64Process)
86 {
87 if (!pfnIsWow64Process(hProcess, &fIsWow64))
88 {
89 ExitWithLastError(hr, "Failed to check WOW64 process.");
90 }
91 }
92
93 *pfWow64 = fIsWow64;
94
95 LExit:
96 return hr;
97 }
98
99 extern "C" HRESULT DAPI ProcDisableWowFileSystemRedirection(
100 __in PROC_FILESYSTEMREDIRECTION* pfsr
101 )
102 {
103 AssertSz(!pfsr->fDisabled, "File system redirection was already disabled.");
104 HRESULT hr = S_OK;
105
106 typedef BOOL (WINAPI *LPFN_Wow64DisableWow64FsRedirection)(PVOID *);
107 LPFN_Wow64DisableWow64FsRedirection pfnWow64DisableWow64FsRedirection = (LPF N_Wow64DisableWow64FsRedirection)::GetProcAddress(::GetModuleHandleW(L"kernel32" ), "Wow64DisableWow64FsRedirection");
108
109 if (!pfnWow64DisableWow64FsRedirection)
110 {
111 ExitFunction1(hr = E_NOTIMPL);
112 }
113
114 if (!pfnWow64DisableWow64FsRedirection(&pfsr->pvRevertState))
115 {
116 ExitWithLastError(hr, "Failed to disable file system redirection.");
117 }
118
119 pfsr->fDisabled = TRUE;
120
121 LExit:
122 return hr;
123 }
124
125 extern "C" HRESULT DAPI ProcRevertWowFileSystemRedirection(
126 __in PROC_FILESYSTEMREDIRECTION* pfsr
127 )
128 {
129 HRESULT hr = S_OK;
130
131 if (pfsr->fDisabled)
132 {
133 typedef BOOL (WINAPI *LPFN_Wow64RevertWow64FsRedirection)(PVOID);
134 LPFN_Wow64RevertWow64FsRedirection pfnWow64RevertWow64FsRedirection = (L PFN_Wow64RevertWow64FsRedirection)::GetProcAddress(::GetModuleHandleW(L"kernel32 "), "Wow64RevertWow64FsRedirection");
135
136 if (!pfnWow64RevertWow64FsRedirection(pfsr->pvRevertState))
137 {
138 ExitWithLastError(hr, "Failed to revert file system redirection.");
139 }
140
141 pfsr->fDisabled = FALSE;
142 pfsr->pvRevertState = NULL;
143 }
144
145 LExit:
146 return hr;
147 }
148
149
150 extern "C" HRESULT DAPI ProcExec(
151 __in_z LPCWSTR wzExecutablePath,
152 __in_z_opt LPCWSTR wzCommandLine,
153 __in int nCmdShow,
154 __out HANDLE *phProcess
155 )
156 {
157 HRESULT hr = S_OK;
158 LPWSTR sczFullCommandLine = NULL;
159 STARTUPINFOW si = { };
160 PROCESS_INFORMATION pi = { };
161
162 hr = StrAllocFormatted(&sczFullCommandLine, L"\"%ls\" %ls", wzExecutablePath , wzCommandLine ? wzCommandLine : L"");
163 ExitOnFailure(hr, "Failed to allocate full command-line.");
164
165 si.cb = sizeof(si);
166 si.wShowWindow = static_cast<WORD>(nCmdShow);
167 if (!::CreateProcessW(wzExecutablePath, sczFullCommandLine, NULL, NULL, FALS E, 0, 0, NULL, &si, &pi))
168 {
169 ExitWithLastError1(hr, "Failed to create process: %ls", sczFullCommandLi ne);
170 }
171
172 *phProcess = pi.hProcess;
173 pi.hProcess = NULL;
174
175 LExit:
176 ReleaseHandle(pi.hThread);
177 ReleaseHandle(pi.hProcess);
178 ReleaseStr(sczFullCommandLine);
179
180 return hr;
181 }
182
183
184 /********************************************************************
185 ProcExecute() - executes a command-line.
186
187 *******************************************************************/
188 extern "C" HRESULT DAPI ProcExecute(
189 __in_z LPWSTR wzCommand,
190 __out HANDLE *phProcess,
191 __out_opt HANDLE *phChildStdIn,
192 __out_opt HANDLE *phChildStdOutErr
193 )
194 {
195 HRESULT hr = S_OK;
196
197 PROCESS_INFORMATION pi = { };
198 STARTUPINFOW si = { };
199
200 HANDLE hOutRead = INVALID_HANDLE_VALUE;
201 HANDLE hOutWrite = INVALID_HANDLE_VALUE;
202 HANDLE hErrWrite = INVALID_HANDLE_VALUE;
203 HANDLE hInRead = INVALID_HANDLE_VALUE;
204 HANDLE hInWrite = INVALID_HANDLE_VALUE;
205
206 // Create redirect pipes.
207 hr = CreatePipes(&hOutRead, &hOutWrite, &hErrWrite, &hInRead, &hInWrite);
208 ExitOnFailure(hr, "failed to create output pipes");
209
210 // Set up startup structure.
211 si.cb = sizeof(STARTUPINFOW);
212 si.dwFlags = STARTF_USESTDHANDLES;
213 si.hStdInput = hInRead;
214 si.hStdOutput = hOutWrite;
215 si.hStdError = hErrWrite;
216
217 #pragma prefast(push)
218 #pragma prefast(disable:25028)
219 if (::CreateProcessW(NULL,
220 wzCommand, // command line
221 NULL, // security info
222 NULL, // thread info
223 TRUE, // inherit handles
224 ::GetPriorityClass(::GetCurrentProcess()) | CREATE_NO_WINDOW, // creatio n flags
225 NULL, // environment
226 NULL, // cur dir
227 &si,
228 &pi))
229 #pragma prefast(pop)
230 {
231 // Close child process output/input handles so child doesn't hang
232 // while waiting for input from parent process.
233 ::CloseHandle(hOutWrite);
234 hOutWrite = INVALID_HANDLE_VALUE;
235
236 ::CloseHandle(hErrWrite);
237 hErrWrite = INVALID_HANDLE_VALUE;
238
239 ::CloseHandle(hInRead);
240 hInRead = INVALID_HANDLE_VALUE;
241 }
242 else
243 {
244 ExitWithLastError(hr, "Process failed to execute.");
245 }
246
247 *phProcess = pi.hProcess;
248 pi.hProcess = 0;
249
250 if (phChildStdIn)
251 {
252 *phChildStdIn = hInWrite;
253 hInWrite = INVALID_HANDLE_VALUE;
254 }
255
256 if (phChildStdOutErr)
257 {
258 *phChildStdOutErr = hOutRead;
259 hOutRead = INVALID_HANDLE_VALUE;
260 }
261
262 LExit:
263 if (pi.hThread)
264 {
265 ::CloseHandle(pi.hThread);
266 }
267
268 if (pi.hProcess)
269 {
270 ::CloseHandle(pi.hProcess);
271 }
272
273 ReleaseFileHandle(hOutRead);
274 ReleaseFileHandle(hOutWrite);
275 ReleaseFileHandle(hErrWrite);
276 ReleaseFileHandle(hInRead);
277 ReleaseFileHandle(hInWrite);
278
279 return hr;
280 }
281
282
283 /********************************************************************
284 ProcWaitForCompletion() - waits for process to complete and gets return code.
285
286 *******************************************************************/
287 extern "C" HRESULT DAPI ProcWaitForCompletion(
288 __in HANDLE hProcess,
289 __in DWORD dwTimeout,
290 __out DWORD *pReturnCode
291 )
292 {
293 HRESULT hr = S_OK;
294 DWORD er = ERROR_SUCCESS;
295
296 // Wait for everything to finish
297 er = ::WaitForSingleObject(hProcess, dwTimeout);
298 if (WAIT_FAILED == er)
299 {
300 ExitWithLastError(hr, "Failed to wait for process to complete.");
301 }
302 else if (WAIT_TIMEOUT == er)
303 {
304 ExitFunction1(hr = HRESULT_FROM_WIN32(er));
305 }
306
307 if (!::GetExitCodeProcess(hProcess, &er))
308 {
309 ExitWithLastError(hr, "Failed to get process return code.");
310 }
311
312 *pReturnCode = er;
313
314 LExit:
315 return hr;
316 }
317
318 /********************************************************************
319 ProcWaitForIds() - waits for multiple processes to complete.
320
321 *******************************************************************/
322 extern "C" HRESULT DAPI ProcWaitForIds(
323 __in_ecount(cProcessIds) const DWORD rgdwProcessIds[],
324 __in DWORD cProcessIds,
325 __in DWORD dwMilliseconds
326 )
327 {
328 HRESULT hr = S_OK;
329 DWORD er = ERROR_SUCCESS;
330 HANDLE hProcess = NULL;
331 HANDLE * rghProcesses = NULL;
332 DWORD cProcesses = 0;
333
334 rghProcesses = static_cast<HANDLE*>(MemAlloc(sizeof(DWORD) * cProcessIds, T RUE));
335 ExitOnNull(rgdwProcessIds, hr, E_OUTOFMEMORY, "Failed to allocate array for process ID Handles.");
336
337 for (DWORD i = 0; i < cProcessIds; ++i)
338 {
339 hProcess = ::OpenProcess(SYNCHRONIZE, FALSE, rgdwProcessIds[i]);
340 if (hProcess != NULL)
341 {
342 rghProcesses[cProcesses++] = hProcess;
343 }
344 }
345
346 er = ::WaitForMultipleObjects(cProcesses, rghProcesses, TRUE, dwMilliseconds );
347 if (WAIT_FAILED == er)
348 {
349 ExitWithLastError(hr, "Failed to wait for process to complete.");
350 }
351 else if (WAIT_TIMEOUT == er)
352 {
353 ExitOnWin32Error(er, hr, "Timed out while waiting for process to complet e.");
354 }
355
356 LExit:
357 if (rghProcesses)
358 {
359 for (DWORD i = 0; i < cProcesses; ++i)
360 {
361 if (NULL != rghProcesses[i])
362 {
363 ::CloseHandle(rghProcesses[i]);
364 }
365 }
366
367 MemFree(rghProcesses);
368 }
369
370 return hr;
371 }
372
373 /********************************************************************
374 ProcCloseIds() - sends WM_CLOSE messages to all process ids.
375
376 *******************************************************************/
377 extern "C" HRESULT DAPI ProcCloseIds(
378 __in_ecount(cProcessIds) const DWORD* pdwProcessIds,
379 __in DWORD cProcessIds
380 )
381 {
382 HRESULT hr = S_OK;
383
384 for (DWORD i = 0; i < cProcessIds; ++i)
385 {
386 if (!::EnumWindows(&CloseWindowEnumCallback, pdwProcessIds[i]))
387 {
388 ExitWithLastError(hr, "Failed to enumerate windows.");
389 }
390 }
391
392 LExit:
393 return hr;
394 }
395
396
397 static HRESULT CreatePipes(
398 __out HANDLE *phOutRead,
399 __out HANDLE *phOutWrite,
400 __out HANDLE *phErrWrite,
401 __out HANDLE *phInRead,
402 __out HANDLE *phInWrite
403 )
404 {
405 HRESULT hr = S_OK;
406 SECURITY_ATTRIBUTES sa;
407 HANDLE hOutTemp = INVALID_HANDLE_VALUE;
408 HANDLE hInTemp = INVALID_HANDLE_VALUE;
409
410 HANDLE hOutRead = INVALID_HANDLE_VALUE;
411 HANDLE hOutWrite = INVALID_HANDLE_VALUE;
412 HANDLE hErrWrite = INVALID_HANDLE_VALUE;
413 HANDLE hInRead = INVALID_HANDLE_VALUE;
414 HANDLE hInWrite = INVALID_HANDLE_VALUE;
415
416 // Fill out security structure so we can inherit handles
417 ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
418 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
419 sa.bInheritHandle = TRUE;
420 sa.lpSecurityDescriptor = NULL;
421
422 // Create pipes
423 if (!::CreatePipe(&hOutTemp, &hOutWrite, &sa, 0))
424 {
425 ExitWithLastError(hr, "failed to create output pipe");
426 }
427
428 if (!::CreatePipe(&hInRead, &hInTemp, &sa, 0))
429 {
430 ExitWithLastError(hr, "failed to create input pipe");
431 }
432
433 // Duplicate output pipe so standard error and standard output write to the same pipe.
434 if (!::DuplicateHandle(::GetCurrentProcess(), hOutWrite, ::GetCurrentProcess (), &hErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS))
435 {
436 ExitWithLastError(hr, "failed to duplicate write handle");
437 }
438
439 // We need to create new "output read" and "input write" handles that are no n inheritable. Otherwise CreateProcess will creates handles in
440 // the child process that can't be closed.
441 if (!::DuplicateHandle(::GetCurrentProcess(), hOutTemp, ::GetCurrentProcess( ), &hOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS))
442 {
443 ExitWithLastError(hr, "failed to duplicate output pipe");
444 }
445
446 if (!::DuplicateHandle(::GetCurrentProcess(), hInTemp, ::GetCurrentProcess() , &hInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS))
447 {
448 ExitWithLastError(hr, "failed to duplicate input pipe");
449 }
450
451 // now that everything has succeeded, assign to the outputs
452 *phOutRead = hOutRead;
453 hOutRead = INVALID_HANDLE_VALUE;
454
455 *phOutWrite = hOutWrite;
456 hOutWrite = INVALID_HANDLE_VALUE;
457
458 *phErrWrite = hErrWrite;
459 hErrWrite = INVALID_HANDLE_VALUE;
460
461 *phInRead = hInRead;
462 hInRead = INVALID_HANDLE_VALUE;
463
464 *phInWrite = hInWrite;
465 hInWrite = INVALID_HANDLE_VALUE;
466
467 LExit:
468 ReleaseFileHandle(hOutRead);
469 ReleaseFileHandle(hOutWrite);
470 ReleaseFileHandle(hErrWrite);
471 ReleaseFileHandle(hInRead);
472 ReleaseFileHandle(hInWrite);
473 ReleaseFileHandle(hOutTemp);
474 ReleaseFileHandle(hInTemp);
475
476 return hr;
477 }
478
479
480 /********************************************************************
481 CloseWindowEnumCallback() - outputs trace and log info
482
483 *******************************************************************/
484 static BOOL CALLBACK CloseWindowEnumCallback(
485 __in HWND hWnd,
486 __in LPARAM lParam
487 )
488 {
489 DWORD dwPid = static_cast<DWORD>(lParam);
490 DWORD dwProcessId = 0;
491
492 ::GetWindowThreadProcessId(hWnd, &dwProcessId);
493 if (dwPid == dwProcessId)
494 {
495 ::SendMessageW(hWnd, WM_CLOSE, 0, 0);
496 }
497
498 return TRUE;
499 }
OLDNEW

Powered by Google App Engine
This is Rietveld