diff options
Diffstat (limited to 'src/engine/elevation.cpp')
-rw-r--r-- | src/engine/elevation.cpp | 2814 |
1 files changed, 2814 insertions, 0 deletions
diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp new file mode 100644 index 00000000..1b9336e0 --- /dev/null +++ b/src/engine/elevation.cpp | |||
@@ -0,0 +1,2814 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | |||
6 | const DWORD BURN_TIMEOUT = 5 * 60 * 1000; // TODO: is 5 minutes good? | ||
7 | |||
8 | typedef enum _BURN_ELEVATION_MESSAGE_TYPE | ||
9 | { | ||
10 | BURN_ELEVATION_MESSAGE_TYPE_UNKNOWN, | ||
11 | BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE, | ||
12 | BURN_ELEVATION_MESSAGE_TYPE_APPLY_UNINITIALIZE, | ||
13 | BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN, | ||
14 | BURN_ELEVATION_MESSAGE_TYPE_SESSION_RESUME, | ||
15 | BURN_ELEVATION_MESSAGE_TYPE_SESSION_END, | ||
16 | BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE, | ||
17 | BURN_ELEVATION_MESSAGE_TYPE_LAYOUT_BUNDLE, | ||
18 | BURN_ELEVATION_MESSAGE_TYPE_CACHE_OR_LAYOUT_CONTAINER_OR_PAYLOAD, | ||
19 | BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, | ||
20 | BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, | ||
21 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, | ||
22 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, | ||
23 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, | ||
24 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE, | ||
25 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER, | ||
26 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY, | ||
27 | BURN_ELEVATION_MESSAGE_TYPE_LOAD_COMPATIBLE_PACKAGE, | ||
28 | BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_EMBEDDED_CHILD, | ||
29 | BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE, | ||
30 | BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE, | ||
31 | |||
32 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, | ||
33 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, | ||
34 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, | ||
35 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE, | ||
36 | BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, | ||
37 | |||
38 | BURN_ELEVATION_TRANSACTION_BEGIN, | ||
39 | BURN_ELEVATION_TRANSACTION_COMMIT, | ||
40 | BURN_ELEVATION_TRANSACTION_ROLLBACK | ||
41 | |||
42 | } BURN_ELEVATION_MESSAGE_TYPE; | ||
43 | |||
44 | |||
45 | // struct | ||
46 | |||
47 | typedef struct _BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT | ||
48 | { | ||
49 | PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler; | ||
50 | LPVOID pvContext; | ||
51 | } BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT; | ||
52 | |||
53 | typedef struct _BURN_ELEVATION_MSI_MESSAGE_CONTEXT | ||
54 | { | ||
55 | PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler; | ||
56 | LPVOID pvContext; | ||
57 | } BURN_ELEVATION_MSI_MESSAGE_CONTEXT; | ||
58 | |||
59 | typedef struct _BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT | ||
60 | { | ||
61 | DWORD dwProcessId; | ||
62 | } BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT; | ||
63 | |||
64 | typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT | ||
65 | { | ||
66 | DWORD dwLoggingTlsId; | ||
67 | HANDLE hPipe; | ||
68 | HANDLE* phLock; | ||
69 | BOOL* pfDisabledAutomaticUpdates; | ||
70 | BURN_APPROVED_EXES* pApprovedExes; | ||
71 | BURN_CONTAINERS* pContainers; | ||
72 | BURN_PACKAGES* pPackages; | ||
73 | BURN_PAYLOADS* pPayloads; | ||
74 | BURN_VARIABLES* pVariables; | ||
75 | BURN_REGISTRATION* pRegistration; | ||
76 | BURN_USER_EXPERIENCE* pUserExperience; | ||
77 | |||
78 | MSIHANDLE hMsiTrns; | ||
79 | HANDLE hMsiTrnsEvent; | ||
80 | } BURN_ELEVATION_CHILD_MESSAGE_CONTEXT; | ||
81 | |||
82 | |||
83 | // internal function declarations | ||
84 | |||
85 | static HRESULT OnMsiBeginTransaction( | ||
86 | __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext | ||
87 | ); | ||
88 | static HRESULT OnMsiCommitTransaction( | ||
89 | __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext | ||
90 | ); | ||
91 | static HRESULT OnMsiRollbackTransaction( | ||
92 | __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext | ||
93 | ); | ||
94 | |||
95 | static DWORD WINAPI ElevatedChildCacheThreadProc( | ||
96 | __in LPVOID lpThreadParameter | ||
97 | ); | ||
98 | static HRESULT WaitForElevatedChildCacheThread( | ||
99 | __in HANDLE hCacheThread, | ||
100 | __in DWORD dwExpectedExitCode | ||
101 | ); | ||
102 | static HRESULT OnLoadCompatiblePackage( | ||
103 | __in BURN_PACKAGES* pPackages, | ||
104 | __in BYTE* pbData, | ||
105 | __in DWORD cbData | ||
106 | ); | ||
107 | static HRESULT ProcessGenericExecuteMessages( | ||
108 | __in BURN_PIPE_MESSAGE* pMsg, | ||
109 | __in_opt LPVOID pvContext, | ||
110 | __out DWORD* pdwResult | ||
111 | ); | ||
112 | static HRESULT ProcessMsiPackageMessages( | ||
113 | __in BURN_PIPE_MESSAGE* pMsg, | ||
114 | __in_opt LPVOID pvContext, | ||
115 | __out DWORD* pdwResult | ||
116 | ); | ||
117 | static HRESULT ProcessLaunchApprovedExeMessages( | ||
118 | __in BURN_PIPE_MESSAGE* pMsg, | ||
119 | __in_opt LPVOID pvContext, | ||
120 | __out DWORD* pdwResult | ||
121 | ); | ||
122 | static HRESULT ProcessElevatedChildMessage( | ||
123 | __in BURN_PIPE_MESSAGE* pMsg, | ||
124 | __in_opt LPVOID pvContext, | ||
125 | __out DWORD* pdwResult | ||
126 | ); | ||
127 | static HRESULT ProcessElevatedChildCacheMessage( | ||
128 | __in BURN_PIPE_MESSAGE* pMsg, | ||
129 | __in_opt LPVOID pvContext, | ||
130 | __out DWORD* pdwResult | ||
131 | ); | ||
132 | static HRESULT ProcessResult( | ||
133 | __in DWORD dwResult, | ||
134 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
135 | ); | ||
136 | static HRESULT OnApplyInitialize( | ||
137 | __in BURN_VARIABLES* pVariables, | ||
138 | __in BURN_REGISTRATION* pRegistration, | ||
139 | __in HANDLE* phLock, | ||
140 | __in BOOL* pfDisabledWindowsUpdate, | ||
141 | __in BYTE* pbData, | ||
142 | __in DWORD cbData | ||
143 | ); | ||
144 | static HRESULT OnApplyUninitialize( | ||
145 | __in HANDLE* phLock | ||
146 | ); | ||
147 | static HRESULT OnSessionBegin( | ||
148 | __in BURN_REGISTRATION* pRegistration, | ||
149 | __in BURN_VARIABLES* pVariables, | ||
150 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
151 | __in BYTE* pbData, | ||
152 | __in DWORD cbData | ||
153 | ); | ||
154 | static HRESULT OnSessionResume( | ||
155 | __in BURN_REGISTRATION* pRegistration, | ||
156 | __in BURN_VARIABLES* pVariables, | ||
157 | __in BYTE* pbData, | ||
158 | __in DWORD cbData | ||
159 | ); | ||
160 | static HRESULT OnSessionEnd( | ||
161 | __in BURN_REGISTRATION* pRegistration, | ||
162 | __in BYTE* pbData, | ||
163 | __in DWORD cbData | ||
164 | ); | ||
165 | static HRESULT OnSaveState( | ||
166 | __in BURN_REGISTRATION* pRegistration, | ||
167 | __in BYTE* pbData, | ||
168 | __in DWORD cbData | ||
169 | ); | ||
170 | static HRESULT OnLayoutBundle( | ||
171 | __in_z LPCWSTR wzExecutableName, | ||
172 | __in BYTE* pbData, | ||
173 | __in DWORD cbData | ||
174 | ); | ||
175 | static HRESULT OnCacheOrLayoutContainerOrPayload( | ||
176 | __in BURN_CONTAINERS* pContainers, | ||
177 | __in BURN_PACKAGES* pPackages, | ||
178 | __in BURN_PAYLOADS* pPayloads, | ||
179 | __in BYTE* pbData, | ||
180 | __in DWORD cbData | ||
181 | ); | ||
182 | static void OnCacheCleanup( | ||
183 | __in_z LPCWSTR wzBundleId | ||
184 | ); | ||
185 | static HRESULT OnProcessDependentRegistration( | ||
186 | __in const BURN_REGISTRATION* pRegistration, | ||
187 | __in BYTE* pbData, | ||
188 | __in DWORD cbData | ||
189 | ); | ||
190 | static HRESULT OnExecuteExePackage( | ||
191 | __in HANDLE hPipe, | ||
192 | __in BURN_PACKAGES* pPackages, | ||
193 | __in BURN_RELATED_BUNDLES* pRelatedBundles, | ||
194 | __in BURN_VARIABLES* pVariables, | ||
195 | __in BYTE* pbData, | ||
196 | __in DWORD cbData | ||
197 | ); | ||
198 | static HRESULT OnExecuteMsiPackage( | ||
199 | __in HANDLE hPipe, | ||
200 | __in BURN_PACKAGES* pPackages, | ||
201 | __in BURN_VARIABLES* pVariables, | ||
202 | __in BYTE* pbData, | ||
203 | __in DWORD cbData | ||
204 | ); | ||
205 | static HRESULT OnExecuteMspPackage( | ||
206 | __in HANDLE hPipe, | ||
207 | __in BURN_PACKAGES* pPackages, | ||
208 | __in BURN_VARIABLES* pVariables, | ||
209 | __in BYTE* pbData, | ||
210 | __in DWORD cbData | ||
211 | ); | ||
212 | static HRESULT OnExecuteMsuPackage( | ||
213 | __in HANDLE hPipe, | ||
214 | __in BURN_PACKAGES* pPackages, | ||
215 | __in BURN_VARIABLES* pVariables, | ||
216 | __in BYTE* pbData, | ||
217 | __in DWORD cbData | ||
218 | ); | ||
219 | static HRESULT OnExecutePackageProviderAction( | ||
220 | __in BURN_PACKAGES* pPackages, | ||
221 | __in BURN_RELATED_BUNDLES* pRelatedBundles, | ||
222 | __in BYTE* pbData, | ||
223 | __in DWORD cbData | ||
224 | ); | ||
225 | static HRESULT OnExecutePackageDependencyAction( | ||
226 | __in BURN_PACKAGES* pPackages, | ||
227 | __in BURN_RELATED_BUNDLES* pRelatedBundles, | ||
228 | __in BYTE* pbData, | ||
229 | __in DWORD cbData | ||
230 | ); | ||
231 | static int GenericExecuteMessageHandler( | ||
232 | __in GENERIC_EXECUTE_MESSAGE* pMessage, | ||
233 | __in LPVOID pvContext | ||
234 | ); | ||
235 | static int MsiExecuteMessageHandler( | ||
236 | __in WIU_MSI_EXECUTE_MESSAGE* pMessage, | ||
237 | __in_opt LPVOID pvContext | ||
238 | ); | ||
239 | static HRESULT OnCleanPackage( | ||
240 | __in BURN_PACKAGES* pPackages, | ||
241 | __in BYTE* pbData, | ||
242 | __in DWORD cbData | ||
243 | ); | ||
244 | static HRESULT OnLaunchApprovedExe( | ||
245 | __in HANDLE hPipe, | ||
246 | __in BURN_APPROVED_EXES* pApprovedExes, | ||
247 | __in BURN_VARIABLES* pVariables, | ||
248 | __in BYTE* pbData, | ||
249 | __in DWORD cbData | ||
250 | ); | ||
251 | |||
252 | |||
253 | // function definitions | ||
254 | |||
255 | extern "C" HRESULT ElevationElevate( | ||
256 | __in BURN_ENGINE_STATE* pEngineState, | ||
257 | __in_opt HWND hwndParent | ||
258 | ) | ||
259 | { | ||
260 | Assert(BURN_MODE_ELEVATED != pEngineState->mode); | ||
261 | Assert(!pEngineState->companionConnection.sczName); | ||
262 | Assert(!pEngineState->companionConnection.sczSecret); | ||
263 | Assert(!pEngineState->companionConnection.hProcess); | ||
264 | Assert(!pEngineState->companionConnection.dwProcessId); | ||
265 | Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe); | ||
266 | Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hCachePipe); | ||
267 | |||
268 | HRESULT hr = S_OK; | ||
269 | int nResult = IDOK; | ||
270 | HANDLE hPipesCreatedEvent = INVALID_HANDLE_VALUE; | ||
271 | |||
272 | hr = UserExperienceOnElevateBegin(&pEngineState->userExperience); | ||
273 | ExitOnRootFailure(hr, "BA aborted elevation requirement."); | ||
274 | |||
275 | hr = PipeCreateNameAndSecret(&pEngineState->companionConnection.sczName, &pEngineState->companionConnection.sczSecret); | ||
276 | ExitOnFailure(hr, "Failed to create pipe name and client token."); | ||
277 | |||
278 | hr = PipeCreatePipes(&pEngineState->companionConnection, TRUE, &hPipesCreatedEvent); | ||
279 | ExitOnFailure(hr, "Failed to create pipe and cache pipe."); | ||
280 | |||
281 | LogId(REPORT_STANDARD, MSG_LAUNCH_ELEVATED_ENGINE_STARTING); | ||
282 | |||
283 | do | ||
284 | { | ||
285 | nResult = IDOK; | ||
286 | |||
287 | // Create the elevated process and if successful, wait for it to connect. | ||
288 | hr = PipeLaunchChildProcess(pEngineState->sczBundleEngineWorkingPath, &pEngineState->companionConnection, TRUE, hwndParent); | ||
289 | if (SUCCEEDED(hr)) | ||
290 | { | ||
291 | LogId(REPORT_STANDARD, MSG_LAUNCH_ELEVATED_ENGINE_SUCCESS); | ||
292 | |||
293 | hr = PipeWaitForChildConnect(&pEngineState->companionConnection); | ||
294 | ExitOnFailure(hr, "Failed to connect to elevated child process."); | ||
295 | |||
296 | LogId(REPORT_STANDARD, MSG_CONNECT_TO_ELEVATED_ENGINE_SUCCESS); | ||
297 | } | ||
298 | else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) | ||
299 | { | ||
300 | // The user clicked "Cancel" on the elevation prompt or the elevation prompt timed out, provide the notification with the option to retry. | ||
301 | hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); | ||
302 | nResult = UserExperienceSendError(&pEngineState->userExperience, BOOTSTRAPPER_ERROR_TYPE_ELEVATE, NULL, hr, NULL, MB_ICONERROR | MB_RETRYCANCEL, IDNOACTION); | ||
303 | } | ||
304 | } while (IDRETRY == nResult); | ||
305 | ExitOnFailure(hr, "Failed to elevate."); | ||
306 | |||
307 | LExit: | ||
308 | ReleaseHandle(hPipesCreatedEvent); | ||
309 | |||
310 | if (FAILED(hr)) | ||
311 | { | ||
312 | PipeConnectionUninitialize(&pEngineState->companionConnection); | ||
313 | } | ||
314 | |||
315 | UserExperienceOnElevateComplete(&pEngineState->userExperience, hr); | ||
316 | |||
317 | return hr; | ||
318 | } | ||
319 | |||
320 | extern "C" HRESULT ElevationApplyInitialize( | ||
321 | __in HANDLE hPipe, | ||
322 | __in BURN_VARIABLES* pVariables, | ||
323 | __in BOOTSTRAPPER_ACTION action, | ||
324 | __in BURN_AU_PAUSE_ACTION auAction, | ||
325 | __in BOOL fTakeSystemRestorePoint | ||
326 | ) | ||
327 | { | ||
328 | HRESULT hr = S_OK; | ||
329 | BYTE* pbData = NULL; | ||
330 | SIZE_T cbData = 0; | ||
331 | DWORD dwResult = 0; | ||
332 | |||
333 | // serialize message data | ||
334 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)action); | ||
335 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
336 | |||
337 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)auAction); | ||
338 | ExitOnFailure(hr, "Failed to write update action to message buffer."); | ||
339 | |||
340 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fTakeSystemRestorePoint); | ||
341 | ExitOnFailure(hr, "Failed to write system restore point action to message buffer."); | ||
342 | |||
343 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | ||
344 | ExitOnFailure(hr, "Failed to write variables."); | ||
345 | |||
346 | // send message | ||
347 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE, pbData, cbData, NULL, NULL, &dwResult); | ||
348 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
349 | |||
350 | hr = (HRESULT)dwResult; | ||
351 | |||
352 | LExit: | ||
353 | ReleaseBuffer(pbData); | ||
354 | |||
355 | return hr; | ||
356 | } | ||
357 | |||
358 | extern "C" HRESULT ElevationApplyUninitialize( | ||
359 | __in HANDLE hPipe | ||
360 | ) | ||
361 | { | ||
362 | HRESULT hr = S_OK; | ||
363 | BYTE* pbData = NULL; | ||
364 | SIZE_T cbData = 0; | ||
365 | DWORD dwResult = 0; | ||
366 | |||
367 | // send message | ||
368 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_UNINITIALIZE, pbData, cbData, NULL, NULL, &dwResult); | ||
369 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
370 | |||
371 | hr = (HRESULT)dwResult; | ||
372 | |||
373 | LExit: | ||
374 | ReleaseBuffer(pbData); | ||
375 | |||
376 | return hr; | ||
377 | } | ||
378 | |||
379 | /******************************************************************* | ||
380 | ElevationSessionBegin - | ||
381 | |||
382 | *******************************************************************/ | ||
383 | extern "C" HRESULT ElevationSessionBegin( | ||
384 | __in HANDLE hPipe, | ||
385 | __in_z LPCWSTR wzEngineWorkingPath, | ||
386 | __in_z LPCWSTR wzResumeCommandLine, | ||
387 | __in BOOL fDisableResume, | ||
388 | __in BURN_VARIABLES* pVariables, | ||
389 | __in DWORD dwRegistrationOperations, | ||
390 | __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction, | ||
391 | __in DWORD64 qwEstimatedSize | ||
392 | ) | ||
393 | { | ||
394 | HRESULT hr = S_OK; | ||
395 | BYTE* pbData = NULL; | ||
396 | SIZE_T cbData = 0; | ||
397 | DWORD dwResult = 0; | ||
398 | |||
399 | // serialize message data | ||
400 | hr = BuffWriteString(&pbData, &cbData, wzEngineWorkingPath); | ||
401 | ExitOnFailure(hr, "Failed to write engine working path to message buffer."); | ||
402 | |||
403 | hr = BuffWriteString(&pbData, &cbData, wzResumeCommandLine); | ||
404 | ExitOnFailure(hr, "Failed to write resume command line to message buffer."); | ||
405 | |||
406 | hr = BuffWriteNumber(&pbData, &cbData, fDisableResume); | ||
407 | ExitOnFailure(hr, "Failed to write resume flag."); | ||
408 | |||
409 | hr = BuffWriteNumber(&pbData, &cbData, dwRegistrationOperations); | ||
410 | ExitOnFailure(hr, "Failed to write registration operations to message buffer."); | ||
411 | |||
412 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)dependencyRegistrationAction); | ||
413 | ExitOnFailure(hr, "Failed to write dependency registration action to message buffer."); | ||
414 | |||
415 | hr = BuffWriteNumber64(&pbData, &cbData, qwEstimatedSize); | ||
416 | ExitOnFailure(hr, "Failed to write estimated size to message buffer."); | ||
417 | |||
418 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | ||
419 | ExitOnFailure(hr, "Failed to write variables."); | ||
420 | |||
421 | // send message | ||
422 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN, pbData, cbData, NULL, NULL, &dwResult); | ||
423 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
424 | |||
425 | hr = (HRESULT)dwResult; | ||
426 | |||
427 | LExit: | ||
428 | ReleaseBuffer(pbData); | ||
429 | |||
430 | return hr; | ||
431 | } | ||
432 | |||
433 | /******************************************************************* | ||
434 | ElevationSessionResume - | ||
435 | |||
436 | *******************************************************************/ | ||
437 | extern "C" HRESULT ElevationSessionResume( | ||
438 | __in HANDLE hPipe, | ||
439 | __in_z LPCWSTR wzResumeCommandLine, | ||
440 | __in BOOL fDisableResume, | ||
441 | __in BURN_VARIABLES* pVariables | ||
442 | ) | ||
443 | { | ||
444 | HRESULT hr = S_OK; | ||
445 | BYTE* pbData = NULL; | ||
446 | SIZE_T cbData = 0; | ||
447 | DWORD dwResult = 0; | ||
448 | |||
449 | // serialize message data | ||
450 | hr = BuffWriteString(&pbData, &cbData, wzResumeCommandLine); | ||
451 | ExitOnFailure(hr, "Failed to write resume command line to message buffer."); | ||
452 | |||
453 | hr = BuffWriteNumber(&pbData, &cbData, fDisableResume); | ||
454 | ExitOnFailure(hr, "Failed to write resume flag."); | ||
455 | |||
456 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | ||
457 | ExitOnFailure(hr, "Failed to write variables."); | ||
458 | |||
459 | // send message | ||
460 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_RESUME, pbData, cbData, NULL, NULL, &dwResult); | ||
461 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
462 | |||
463 | hr = (HRESULT)dwResult; | ||
464 | |||
465 | LExit: | ||
466 | ReleaseBuffer(pbData); | ||
467 | |||
468 | return hr; | ||
469 | } | ||
470 | |||
471 | /******************************************************************* | ||
472 | ElevationSessionEnd - | ||
473 | |||
474 | *******************************************************************/ | ||
475 | extern "C" HRESULT ElevationSessionEnd( | ||
476 | __in HANDLE hPipe, | ||
477 | __in BURN_RESUME_MODE resumeMode, | ||
478 | __in BOOTSTRAPPER_APPLY_RESTART restart, | ||
479 | __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction | ||
480 | ) | ||
481 | { | ||
482 | HRESULT hr = S_OK; | ||
483 | BYTE* pbData = NULL; | ||
484 | SIZE_T cbData = 0; | ||
485 | DWORD dwResult = 0; | ||
486 | |||
487 | // serialize message data | ||
488 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)resumeMode); | ||
489 | ExitOnFailure(hr, "Failed to write resume mode to message buffer."); | ||
490 | |||
491 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)restart); | ||
492 | ExitOnFailure(hr, "Failed to write restart enum to message buffer."); | ||
493 | |||
494 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)dependencyRegistrationAction); | ||
495 | ExitOnFailure(hr, "Failed to write dependency registration action to message buffer."); | ||
496 | |||
497 | // send message | ||
498 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_END, pbData, cbData, NULL, NULL, &dwResult); | ||
499 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
500 | |||
501 | hr = (HRESULT)dwResult; | ||
502 | |||
503 | LExit: | ||
504 | ReleaseBuffer(pbData); | ||
505 | |||
506 | return hr; | ||
507 | } | ||
508 | |||
509 | /******************************************************************* | ||
510 | ElevationSaveState - | ||
511 | |||
512 | *******************************************************************/ | ||
513 | HRESULT ElevationSaveState( | ||
514 | __in HANDLE hPipe, | ||
515 | __in_bcount(cbBuffer) BYTE* pbBuffer, | ||
516 | __in SIZE_T cbBuffer | ||
517 | ) | ||
518 | { | ||
519 | HRESULT hr = S_OK; | ||
520 | DWORD dwResult = 0; | ||
521 | |||
522 | // send message | ||
523 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE, pbBuffer, (DWORD)cbBuffer, NULL, NULL, &dwResult); | ||
524 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
525 | |||
526 | hr = (HRESULT)dwResult; | ||
527 | |||
528 | LExit: | ||
529 | return hr; | ||
530 | } | ||
531 | |||
532 | /******************************************************************* | ||
533 | ElevationLayoutBundle - | ||
534 | |||
535 | *******************************************************************/ | ||
536 | extern "C" HRESULT ElevationLayoutBundle( | ||
537 | __in HANDLE hPipe, | ||
538 | __in_z LPCWSTR wzLayoutDirectory, | ||
539 | __in_z LPCWSTR wzUnverifiedPath | ||
540 | ) | ||
541 | { | ||
542 | HRESULT hr = S_OK; | ||
543 | BYTE* pbData = NULL; | ||
544 | SIZE_T cbData = 0; | ||
545 | DWORD dwResult = 0; | ||
546 | |||
547 | // serialize message data | ||
548 | hr = BuffWriteString(&pbData, &cbData, wzLayoutDirectory); | ||
549 | ExitOnFailure(hr, "Failed to write layout directory to message buffer."); | ||
550 | |||
551 | hr = BuffWriteString(&pbData, &cbData, wzUnverifiedPath); | ||
552 | ExitOnFailure(hr, "Failed to write payload unverified path to message buffer."); | ||
553 | |||
554 | // send message | ||
555 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_LAYOUT_BUNDLE, pbData, cbData, NULL, NULL, &dwResult); | ||
556 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_LAYOUT_BUNDLE message to per-machine process."); | ||
557 | |||
558 | hr = (HRESULT)dwResult; | ||
559 | |||
560 | LExit: | ||
561 | ReleaseBuffer(pbData); | ||
562 | |||
563 | return hr; | ||
564 | } | ||
565 | |||
566 | /******************************************************************* | ||
567 | ElevationCacheOrLayoutPayload - | ||
568 | |||
569 | *******************************************************************/ | ||
570 | extern "C" HRESULT ElevationCacheOrLayoutContainerOrPayload( | ||
571 | __in HANDLE hPipe, | ||
572 | __in_opt BURN_CONTAINER* pContainer, | ||
573 | __in_opt BURN_PACKAGE* pPackage, | ||
574 | __in_opt BURN_PAYLOAD* pPayload, | ||
575 | __in_z_opt LPCWSTR wzLayoutDirectory, | ||
576 | __in_z LPCWSTR wzUnverifiedPath, | ||
577 | __in BOOL fMove | ||
578 | ) | ||
579 | { | ||
580 | HRESULT hr = S_OK; | ||
581 | BYTE* pbData = NULL; | ||
582 | SIZE_T cbData = 0; | ||
583 | DWORD dwResult = 0; | ||
584 | |||
585 | // serialize message data | ||
586 | hr = BuffWriteString(&pbData, &cbData, pContainer ? pContainer->sczId : NULL); | ||
587 | ExitOnFailure(hr, "Failed to write container id to message buffer."); | ||
588 | |||
589 | hr = BuffWriteString(&pbData, &cbData, pPackage ? pPackage->sczId : NULL); | ||
590 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
591 | |||
592 | hr = BuffWriteString(&pbData, &cbData, pPayload ? pPayload->sczKey : NULL); | ||
593 | ExitOnFailure(hr, "Failed to write payload id to message buffer."); | ||
594 | |||
595 | hr = BuffWriteString(&pbData, &cbData, wzLayoutDirectory); | ||
596 | ExitOnFailure(hr, "Failed to write layout directory to message buffer."); | ||
597 | |||
598 | hr = BuffWriteString(&pbData, &cbData, wzUnverifiedPath); | ||
599 | ExitOnFailure(hr, "Failed to write unverified path to message buffer."); | ||
600 | |||
601 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fMove); | ||
602 | ExitOnFailure(hr, "Failed to write move flag to message buffer."); | ||
603 | |||
604 | // send message | ||
605 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_OR_LAYOUT_CONTAINER_OR_PAYLOAD, pbData, cbData, NULL, NULL, &dwResult); | ||
606 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_OR_LAYOUT_CONTAINER_OR_PAYLOAD message to per-machine process."); | ||
607 | |||
608 | hr = (HRESULT)dwResult; | ||
609 | |||
610 | LExit: | ||
611 | ReleaseBuffer(pbData); | ||
612 | |||
613 | return hr; | ||
614 | } | ||
615 | |||
616 | /******************************************************************* | ||
617 | ElevationCacheCleanup - | ||
618 | |||
619 | *******************************************************************/ | ||
620 | extern "C" HRESULT ElevationCacheCleanup( | ||
621 | __in HANDLE hPipe | ||
622 | ) | ||
623 | { | ||
624 | HRESULT hr = S_OK; | ||
625 | DWORD dwResult = 0; | ||
626 | |||
627 | // send message | ||
628 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, NULL, 0, NULL, NULL, &dwResult); | ||
629 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP message to per-machine process."); | ||
630 | |||
631 | hr = (HRESULT)dwResult; | ||
632 | |||
633 | LExit: | ||
634 | return hr; | ||
635 | } | ||
636 | |||
637 | extern "C" HRESULT ElevationProcessDependentRegistration( | ||
638 | __in HANDLE hPipe, | ||
639 | __in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction | ||
640 | ) | ||
641 | { | ||
642 | HRESULT hr = S_OK; | ||
643 | BYTE* pbData = NULL; | ||
644 | SIZE_T cbData = 0; | ||
645 | DWORD dwResult = 0; | ||
646 | |||
647 | // serialize message data | ||
648 | hr = BuffWriteNumber(&pbData, &cbData, pAction->type); | ||
649 | ExitOnFailure(hr, "Failed to write action type to message buffer."); | ||
650 | |||
651 | hr = BuffWriteString(&pbData, &cbData, pAction->sczBundleId); | ||
652 | ExitOnFailure(hr, "Failed to write bundle id to message buffer."); | ||
653 | |||
654 | hr = BuffWriteString(&pbData, &cbData, pAction->sczDependentProviderKey); | ||
655 | ExitOnFailure(hr, "Failed to write dependent provider key to message buffer."); | ||
656 | |||
657 | // send message | ||
658 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, pbData, cbData, NULL, NULL, &dwResult); | ||
659 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION message to per-machine process."); | ||
660 | |||
661 | hr = (HRESULT)dwResult; | ||
662 | |||
663 | LExit: | ||
664 | ReleaseBuffer(pbData); | ||
665 | |||
666 | return hr; | ||
667 | } | ||
668 | |||
669 | /******************************************************************* | ||
670 | ElevationExecuteExePackage - | ||
671 | |||
672 | *******************************************************************/ | ||
673 | extern "C" HRESULT ElevationExecuteExePackage( | ||
674 | __in HANDLE hPipe, | ||
675 | __in BURN_EXECUTE_ACTION* pExecuteAction, | ||
676 | __in BURN_VARIABLES* pVariables, | ||
677 | __in BOOL fRollback, | ||
678 | __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, | ||
679 | __in LPVOID pvContext, | ||
680 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
681 | ) | ||
682 | { | ||
683 | HRESULT hr = S_OK; | ||
684 | BYTE* pbData = NULL; | ||
685 | SIZE_T cbData = 0; | ||
686 | BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT context = { }; | ||
687 | DWORD dwResult = 0; | ||
688 | |||
689 | // serialize message data | ||
690 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId); | ||
691 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
692 | |||
693 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action); | ||
694 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
695 | |||
696 | hr = BuffWriteNumber(&pbData, &cbData, fRollback); | ||
697 | ExitOnFailure(hr, "Failed to write rollback."); | ||
698 | |||
699 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies); | ||
700 | ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer."); | ||
701 | |||
702 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); | ||
703 | ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); | ||
704 | |||
705 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | ||
706 | ExitOnFailure(hr, "Failed to write variables."); | ||
707 | |||
708 | // send message | ||
709 | context.pfnGenericMessageHandler = pfnGenericMessageHandler; | ||
710 | context.pvContext = pvContext; | ||
711 | |||
712 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); | ||
713 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process."); | ||
714 | |||
715 | hr = ProcessResult(dwResult, pRestart); | ||
716 | |||
717 | LExit: | ||
718 | ReleaseBuffer(pbData); | ||
719 | |||
720 | return hr; | ||
721 | } | ||
722 | |||
723 | extern "C" HRESULT ElevationMsiBeginTransaction( | ||
724 | __in HANDLE hPipe, | ||
725 | __in_opt HWND hwndParent, | ||
726 | __in LPVOID pvContext | ||
727 | ) | ||
728 | { | ||
729 | UNREFERENCED_PARAMETER(hwndParent); | ||
730 | HRESULT hr = S_OK; | ||
731 | BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; | ||
732 | DWORD dwResult = ERROR_SUCCESS; | ||
733 | |||
734 | context.pvContext = pvContext; | ||
735 | |||
736 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_BEGIN, NULL, 0, NULL, &context, &dwResult); | ||
737 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); | ||
738 | ExitOnWin32Error(dwResult, hr, "Failed beginning an elevated MSI transaction"); | ||
739 | |||
740 | LExit: | ||
741 | return hr; | ||
742 | } | ||
743 | |||
744 | extern "C" HRESULT ElevationMsiCommitTransaction( | ||
745 | __in HANDLE hPipe, | ||
746 | __in_opt HWND hwndParent, | ||
747 | __in LPVOID pvContext | ||
748 | ) | ||
749 | { | ||
750 | UNREFERENCED_PARAMETER(hwndParent); | ||
751 | HRESULT hr = S_OK; | ||
752 | BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; | ||
753 | DWORD dwResult = ERROR_SUCCESS; | ||
754 | |||
755 | context.pvContext = pvContext; | ||
756 | |||
757 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_COMMIT, NULL, 0, NULL, &context, &dwResult); | ||
758 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); | ||
759 | ExitOnWin32Error(dwResult, hr, "Failed committing an elevated MSI transaction"); | ||
760 | |||
761 | LExit: | ||
762 | return hr; | ||
763 | } | ||
764 | |||
765 | extern "C" HRESULT ElevationMsiRollbackTransaction( | ||
766 | __in HANDLE hPipe, | ||
767 | __in_opt HWND hwndParent, | ||
768 | __in LPVOID pvContext | ||
769 | ) | ||
770 | { | ||
771 | UNREFERENCED_PARAMETER(hwndParent); | ||
772 | HRESULT hr = S_OK; | ||
773 | BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; | ||
774 | DWORD dwResult = ERROR_SUCCESS; | ||
775 | |||
776 | context.pvContext = pvContext; | ||
777 | |||
778 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_ROLLBACK, NULL, 0, NULL, &context, &dwResult); | ||
779 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); | ||
780 | ExitOnWin32Error(dwResult, hr, "Failed rolling back an elevated MSI transaction"); | ||
781 | |||
782 | LExit: | ||
783 | return hr; | ||
784 | } | ||
785 | |||
786 | |||
787 | |||
788 | /******************************************************************* | ||
789 | ElevationExecuteMsiPackage - | ||
790 | |||
791 | *******************************************************************/ | ||
792 | extern "C" HRESULT ElevationExecuteMsiPackage( | ||
793 | __in HANDLE hPipe, | ||
794 | __in_opt HWND hwndParent, | ||
795 | __in BURN_EXECUTE_ACTION* pExecuteAction, | ||
796 | __in BURN_VARIABLES* pVariables, | ||
797 | __in BOOL fRollback, | ||
798 | __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, | ||
799 | __in LPVOID pvContext, | ||
800 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
801 | ) | ||
802 | { | ||
803 | HRESULT hr = S_OK; | ||
804 | BYTE* pbData = NULL; | ||
805 | SIZE_T cbData = 0; | ||
806 | BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; | ||
807 | DWORD dwResult = 0; | ||
808 | |||
809 | // serialize message data | ||
810 | // TODO: for patching we might not have a package | ||
811 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msiPackage.pPackage->sczId); | ||
812 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
813 | |||
814 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)hwndParent); | ||
815 | ExitOnFailure(hr, "Failed to write parent hwnd to message buffer."); | ||
816 | |||
817 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msiPackage.sczLogPath); | ||
818 | ExitOnFailure(hr, "Failed to write package log to message buffer."); | ||
819 | |||
820 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.uiLevel); | ||
821 | ExitOnFailure(hr, "Failed to write UI level to message buffer."); | ||
822 | |||
823 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.action); | ||
824 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
825 | |||
826 | // Feature actions. | ||
827 | for (DWORD i = 0; i < pExecuteAction->msiPackage.pPackage->Msi.cFeatures; ++i) | ||
828 | { | ||
829 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.rgFeatures[i]); | ||
830 | ExitOnFailure(hr, "Failed to write feature action to message buffer."); | ||
831 | } | ||
832 | |||
833 | // Slipstream patches actions. | ||
834 | for (DWORD i = 0; i < pExecuteAction->msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++i) | ||
835 | { | ||
836 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.rgSlipstreamPatches[i]); | ||
837 | ExitOnFailure(hr, "Failed to write slipstream patch action to message buffer."); | ||
838 | } | ||
839 | |||
840 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | ||
841 | ExitOnFailure(hr, "Failed to write variables."); | ||
842 | |||
843 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); | ||
844 | ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); | ||
845 | |||
846 | |||
847 | // send message | ||
848 | context.pfnMessageHandler = pfnMessageHandler; | ||
849 | context.pvContext = pvContext; | ||
850 | |||
851 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); | ||
852 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); | ||
853 | |||
854 | hr = ProcessResult(dwResult, pRestart); | ||
855 | |||
856 | LExit: | ||
857 | ReleaseBuffer(pbData); | ||
858 | |||
859 | return hr; | ||
860 | } | ||
861 | |||
862 | /******************************************************************* | ||
863 | ElevationExecuteMspPackage - | ||
864 | |||
865 | *******************************************************************/ | ||
866 | extern "C" HRESULT ElevationExecuteMspPackage( | ||
867 | __in HANDLE hPipe, | ||
868 | __in_opt HWND hwndParent, | ||
869 | __in BURN_EXECUTE_ACTION* pExecuteAction, | ||
870 | __in BURN_VARIABLES* pVariables, | ||
871 | __in BOOL fRollback, | ||
872 | __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, | ||
873 | __in LPVOID pvContext, | ||
874 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
875 | ) | ||
876 | { | ||
877 | HRESULT hr = S_OK; | ||
878 | BYTE* pbData = NULL; | ||
879 | SIZE_T cbData = 0; | ||
880 | BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; | ||
881 | DWORD dwResult = 0; | ||
882 | |||
883 | // serialize message data | ||
884 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.pPackage->sczId); | ||
885 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
886 | |||
887 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)hwndParent); | ||
888 | ExitOnFailure(hr, "Failed to write parent hwnd to message buffer."); | ||
889 | |||
890 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.sczTargetProductCode); | ||
891 | ExitOnFailure(hr, "Failed to write target product code to message buffer."); | ||
892 | |||
893 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.sczLogPath); | ||
894 | ExitOnFailure(hr, "Failed to write package log to message buffer."); | ||
895 | |||
896 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.uiLevel); | ||
897 | ExitOnFailure(hr, "Failed to write UI level to message buffer."); | ||
898 | |||
899 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.action); | ||
900 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
901 | |||
902 | hr = BuffWriteNumber(&pbData, &cbData, pExecuteAction->mspTarget.cOrderedPatches); | ||
903 | ExitOnFailure(hr, "Failed to write count of ordered patches to message buffer."); | ||
904 | |||
905 | for (DWORD i = 0; i < pExecuteAction->mspTarget.cOrderedPatches; ++i) | ||
906 | { | ||
907 | hr = BuffWriteNumber(&pbData, &cbData, pExecuteAction->mspTarget.rgOrderedPatches[i].dwOrder); | ||
908 | ExitOnFailure(hr, "Failed to write ordered patch order to message buffer."); | ||
909 | |||
910 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage->sczId); | ||
911 | ExitOnFailure(hr, "Failed to write ordered patch id to message buffer."); | ||
912 | } | ||
913 | |||
914 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | ||
915 | ExitOnFailure(hr, "Failed to write variables."); | ||
916 | |||
917 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); | ||
918 | ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); | ||
919 | |||
920 | // send message | ||
921 | context.pfnMessageHandler = pfnMessageHandler; | ||
922 | context.pvContext = pvContext; | ||
923 | |||
924 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); | ||
925 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE message to per-machine process."); | ||
926 | |||
927 | hr = ProcessResult(dwResult, pRestart); | ||
928 | |||
929 | LExit: | ||
930 | ReleaseBuffer(pbData); | ||
931 | |||
932 | return hr; | ||
933 | } | ||
934 | |||
935 | /******************************************************************* | ||
936 | ElevationExecuteMsuPackage - | ||
937 | |||
938 | *******************************************************************/ | ||
939 | extern "C" HRESULT ElevationExecuteMsuPackage( | ||
940 | __in HANDLE hPipe, | ||
941 | __in BURN_EXECUTE_ACTION* pExecuteAction, | ||
942 | __in BOOL fRollback, | ||
943 | __in BOOL fStopWusaService, | ||
944 | __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, | ||
945 | __in LPVOID pvContext, | ||
946 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
947 | ) | ||
948 | { | ||
949 | HRESULT hr = S_OK; | ||
950 | BYTE* pbData = NULL; | ||
951 | SIZE_T cbData = 0; | ||
952 | BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT context = { }; | ||
953 | DWORD dwResult = 0; | ||
954 | |||
955 | // serialize message data | ||
956 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msuPackage.pPackage->sczId); | ||
957 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
958 | |||
959 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msuPackage.sczLogPath); | ||
960 | ExitOnFailure(hr, "Failed to write package log to message buffer."); | ||
961 | |||
962 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msuPackage.action); | ||
963 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
964 | |||
965 | hr = BuffWriteNumber(&pbData, &cbData, fRollback); | ||
966 | ExitOnFailure(hr, "Failed to write rollback."); | ||
967 | |||
968 | hr = BuffWriteNumber(&pbData, &cbData, fStopWusaService); | ||
969 | ExitOnFailure(hr, "Failed to write StopWusaService."); | ||
970 | |||
971 | // send message | ||
972 | context.pfnGenericMessageHandler = pfnGenericMessageHandler; | ||
973 | context.pvContext = pvContext; | ||
974 | |||
975 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); | ||
976 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE message to per-machine process."); | ||
977 | |||
978 | hr = ProcessResult(dwResult, pRestart); | ||
979 | |||
980 | LExit: | ||
981 | ReleaseBuffer(pbData); | ||
982 | |||
983 | return hr; | ||
984 | } | ||
985 | |||
986 | extern "C" HRESULT ElevationExecutePackageProviderAction( | ||
987 | __in HANDLE hPipe, | ||
988 | __in BURN_EXECUTE_ACTION* pExecuteAction | ||
989 | ) | ||
990 | { | ||
991 | HRESULT hr = S_OK; | ||
992 | BYTE* pbData = NULL; | ||
993 | SIZE_T cbData = 0; | ||
994 | DWORD dwResult = 0; | ||
995 | BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
996 | |||
997 | // Serialize the message data. | ||
998 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageProvider.pPackage->sczId); | ||
999 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
1000 | |||
1001 | hr = BuffWriteNumber(&pbData, &cbData, pExecuteAction->packageProvider.action); | ||
1002 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
1003 | |||
1004 | // Send the message. | ||
1005 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER, pbData, cbData, NULL, NULL, &dwResult); | ||
1006 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER message to per-machine process."); | ||
1007 | |||
1008 | // Ignore the restart since this action only results in registry writes. | ||
1009 | hr = ProcessResult(dwResult, &restart); | ||
1010 | |||
1011 | LExit: | ||
1012 | ReleaseBuffer(pbData); | ||
1013 | |||
1014 | return hr; | ||
1015 | } | ||
1016 | |||
1017 | extern "C" HRESULT ElevationExecutePackageDependencyAction( | ||
1018 | __in HANDLE hPipe, | ||
1019 | __in BURN_EXECUTE_ACTION* pExecuteAction | ||
1020 | ) | ||
1021 | { | ||
1022 | HRESULT hr = S_OK; | ||
1023 | BYTE* pbData = NULL; | ||
1024 | SIZE_T cbData = 0; | ||
1025 | DWORD dwResult = 0; | ||
1026 | BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
1027 | |||
1028 | // Serialize the message data. | ||
1029 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageDependency.pPackage->sczId); | ||
1030 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
1031 | |||
1032 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageDependency.sczBundleProviderKey); | ||
1033 | ExitOnFailure(hr, "Failed to write bundle dependency key to message buffer."); | ||
1034 | |||
1035 | hr = BuffWriteNumber(&pbData, &cbData, pExecuteAction->packageDependency.action); | ||
1036 | ExitOnFailure(hr, "Failed to write action to message buffer."); | ||
1037 | |||
1038 | // Send the message. | ||
1039 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY, pbData, cbData, NULL, NULL, &dwResult); | ||
1040 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY message to per-machine process."); | ||
1041 | |||
1042 | // Ignore the restart since this action only results in registry writes. | ||
1043 | hr = ProcessResult(dwResult, &restart); | ||
1044 | |||
1045 | LExit: | ||
1046 | ReleaseBuffer(pbData); | ||
1047 | |||
1048 | return hr; | ||
1049 | } | ||
1050 | |||
1051 | /******************************************************************* | ||
1052 | ElevationLoadCompatiblePackageAction - Load compatible package | ||
1053 | information from the referenced package. | ||
1054 | |||
1055 | *******************************************************************/ | ||
1056 | extern "C" HRESULT ElevationLoadCompatiblePackageAction( | ||
1057 | __in HANDLE hPipe, | ||
1058 | __in BURN_EXECUTE_ACTION* pExecuteAction | ||
1059 | ) | ||
1060 | { | ||
1061 | HRESULT hr = S_OK; | ||
1062 | BYTE* pbData = NULL; | ||
1063 | SIZE_T cbData = 0; | ||
1064 | DWORD dwResult = 0; | ||
1065 | BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
1066 | |||
1067 | // Serialize message data. | ||
1068 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->compatiblePackage.pReferencePackage->sczId); | ||
1069 | ExitOnFailure(hr, "Failed to write package id to message buffer."); | ||
1070 | |||
1071 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->compatiblePackage.sczInstalledProductCode); | ||
1072 | ExitOnFailure(hr, "Failed to write installed ProductCode to message buffer."); | ||
1073 | |||
1074 | hr = BuffWriteNumber64(&pbData, &cbData, pExecuteAction->compatiblePackage.qwInstalledVersion); | ||
1075 | ExitOnFailure(hr, "Failed to write installed version to message buffer."); | ||
1076 | |||
1077 | // Send the message. | ||
1078 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_LOAD_COMPATIBLE_PACKAGE, pbData, cbData, NULL, NULL, &dwResult); | ||
1079 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_LOAD_COMPATIBLE_PACKAGE message to per-machine process."); | ||
1080 | |||
1081 | // Ignore the restart since this action only loads data into memory. | ||
1082 | hr = ProcessResult(dwResult, &restart); | ||
1083 | |||
1084 | LExit: | ||
1085 | ReleaseBuffer(pbData); | ||
1086 | |||
1087 | return hr; | ||
1088 | } | ||
1089 | |||
1090 | /******************************************************************* | ||
1091 | ElevationCleanPackage - | ||
1092 | |||
1093 | *******************************************************************/ | ||
1094 | extern "C" HRESULT ElevationCleanPackage( | ||
1095 | __in HANDLE hPipe, | ||
1096 | __in BURN_PACKAGE* pPackage | ||
1097 | ) | ||
1098 | { | ||
1099 | HRESULT hr = S_OK; | ||
1100 | BYTE* pbData = NULL; | ||
1101 | SIZE_T cbData = 0; | ||
1102 | DWORD dwResult = 0; | ||
1103 | |||
1104 | // serialize message data | ||
1105 | hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); | ||
1106 | ExitOnFailure(hr, "Failed to write clean package id to message buffer."); | ||
1107 | |||
1108 | // send message | ||
1109 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE, pbData, cbData, NULL, NULL, &dwResult); | ||
1110 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE message to per-machine process."); | ||
1111 | |||
1112 | hr = (HRESULT)dwResult; | ||
1113 | |||
1114 | LExit: | ||
1115 | ReleaseBuffer(pbData); | ||
1116 | |||
1117 | return hr; | ||
1118 | } | ||
1119 | |||
1120 | extern "C" HRESULT ElevationLaunchApprovedExe( | ||
1121 | __in HANDLE hPipe, | ||
1122 | __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe, | ||
1123 | __out DWORD* pdwProcessId | ||
1124 | ) | ||
1125 | { | ||
1126 | HRESULT hr = S_OK; | ||
1127 | BYTE* pbData = NULL; | ||
1128 | SIZE_T cbData = 0; | ||
1129 | DWORD dwResult = 0; | ||
1130 | BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT context = { }; | ||
1131 | |||
1132 | // Serialize message data. | ||
1133 | hr = BuffWriteString(&pbData, &cbData, pLaunchApprovedExe->sczId); | ||
1134 | ExitOnFailure(hr, "Failed to write approved exe id to message buffer."); | ||
1135 | |||
1136 | hr = BuffWriteString(&pbData, &cbData, pLaunchApprovedExe->sczArguments); | ||
1137 | ExitOnFailure(hr, "Failed to write approved exe arguments to message buffer."); | ||
1138 | |||
1139 | hr = BuffWriteNumber(&pbData, &cbData, pLaunchApprovedExe->dwWaitForInputIdleTimeout); | ||
1140 | ExitOnFailure(hr, "Failed to write approved exe WaitForInputIdle timeout to message buffer."); | ||
1141 | |||
1142 | // Send the message. | ||
1143 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE, pbData, cbData, ProcessLaunchApprovedExeMessages, &context, &dwResult); | ||
1144 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE message to per-machine process."); | ||
1145 | |||
1146 | hr = (HRESULT)dwResult; | ||
1147 | *pdwProcessId = context.dwProcessId; | ||
1148 | |||
1149 | LExit: | ||
1150 | ReleaseBuffer(pbData); | ||
1151 | |||
1152 | return hr; | ||
1153 | } | ||
1154 | |||
1155 | /******************************************************************* | ||
1156 | ElevationChildPumpMessages - | ||
1157 | |||
1158 | *******************************************************************/ | ||
1159 | extern "C" HRESULT ElevationChildPumpMessages( | ||
1160 | __in DWORD dwLoggingTlsId, | ||
1161 | __in HANDLE hPipe, | ||
1162 | __in HANDLE hCachePipe, | ||
1163 | __in BURN_APPROVED_EXES* pApprovedExes, | ||
1164 | __in BURN_CONTAINERS* pContainers, | ||
1165 | __in BURN_PACKAGES* pPackages, | ||
1166 | __in BURN_PAYLOADS* pPayloads, | ||
1167 | __in BURN_VARIABLES* pVariables, | ||
1168 | __in BURN_REGISTRATION* pRegistration, | ||
1169 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
1170 | __out HANDLE* phLock, | ||
1171 | __out BOOL* pfDisabledAutomaticUpdates, | ||
1172 | __out DWORD* pdwChildExitCode, | ||
1173 | __out BOOL* pfRestart | ||
1174 | ) | ||
1175 | { | ||
1176 | HRESULT hr = S_OK; | ||
1177 | BURN_ELEVATION_CHILD_MESSAGE_CONTEXT cacheContext = { }; | ||
1178 | BURN_ELEVATION_CHILD_MESSAGE_CONTEXT context = { }; | ||
1179 | HANDLE hCacheThread = NULL; | ||
1180 | BURN_PIPE_RESULT result = { }; | ||
1181 | |||
1182 | cacheContext.dwLoggingTlsId = dwLoggingTlsId; | ||
1183 | cacheContext.hPipe = hCachePipe; | ||
1184 | cacheContext.pContainers = pContainers; | ||
1185 | cacheContext.pPackages = pPackages; | ||
1186 | cacheContext.pPayloads = pPayloads; | ||
1187 | cacheContext.pVariables = pVariables; | ||
1188 | cacheContext.pRegistration = pRegistration; | ||
1189 | cacheContext.pUserExperience = pUserExperience; | ||
1190 | |||
1191 | context.dwLoggingTlsId = dwLoggingTlsId; | ||
1192 | context.hPipe = hPipe; | ||
1193 | context.phLock = phLock; | ||
1194 | context.pfDisabledAutomaticUpdates = pfDisabledAutomaticUpdates; | ||
1195 | context.pApprovedExes = pApprovedExes; | ||
1196 | context.pContainers = pContainers; | ||
1197 | context.pPackages = pPackages; | ||
1198 | context.pPayloads = pPayloads; | ||
1199 | context.pVariables = pVariables; | ||
1200 | context.pRegistration = pRegistration; | ||
1201 | context.pUserExperience = pUserExperience; | ||
1202 | |||
1203 | hCacheThread = ::CreateThread(NULL, 0, ElevatedChildCacheThreadProc, &cacheContext, 0, NULL); | ||
1204 | ExitOnNullWithLastError(hCacheThread, hr, "Failed to create elevated cache thread."); | ||
1205 | |||
1206 | hr = PipePumpMessages(hPipe, ProcessElevatedChildMessage, &context, &result); | ||
1207 | ExitOnFailure(hr, "Failed to pump messages in child process."); | ||
1208 | |||
1209 | // Wait for the cache thread and verify it gets the right result but don't fail if things | ||
1210 | // don't work out. | ||
1211 | WaitForElevatedChildCacheThread(hCacheThread, result.dwResult); | ||
1212 | |||
1213 | *pdwChildExitCode = result.dwResult; | ||
1214 | *pfRestart = result.fRestart; | ||
1215 | |||
1216 | LExit: | ||
1217 | ReleaseHandle(hCacheThread); | ||
1218 | |||
1219 | return hr; | ||
1220 | } | ||
1221 | |||
1222 | extern "C" HRESULT ElevationChildResumeAutomaticUpdates() | ||
1223 | { | ||
1224 | HRESULT hr = S_OK; | ||
1225 | |||
1226 | LogId(REPORT_STANDARD, MSG_RESUME_AU_STARTING); | ||
1227 | |||
1228 | hr = WuaResumeAutomaticUpdates(); | ||
1229 | ExitOnFailure(hr, "Failed to resume automatic updates after pausing them, continuing..."); | ||
1230 | |||
1231 | LogId(REPORT_STANDARD, MSG_RESUME_AU_SUCCEEDED); | ||
1232 | |||
1233 | LExit: | ||
1234 | return hr; | ||
1235 | } | ||
1236 | |||
1237 | // internal function definitions | ||
1238 | |||
1239 | static DWORD WINAPI ElevatedChildCacheThreadProc( | ||
1240 | __in LPVOID lpThreadParameter | ||
1241 | ) | ||
1242 | { | ||
1243 | HRESULT hr = S_OK; | ||
1244 | BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = reinterpret_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(lpThreadParameter); | ||
1245 | BOOL fComInitialized = FALSE; | ||
1246 | BURN_PIPE_RESULT result = { }; | ||
1247 | |||
1248 | if (!::TlsSetValue(pContext->dwLoggingTlsId, pContext->hPipe)) | ||
1249 | { | ||
1250 | ExitWithLastError(hr, "Failed to set elevated cache pipe into thread local storage for logging."); | ||
1251 | } | ||
1252 | |||
1253 | // initialize COM | ||
1254 | hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); | ||
1255 | ExitOnFailure(hr, "Failed to initialize COM."); | ||
1256 | fComInitialized = TRUE; | ||
1257 | |||
1258 | hr = PipePumpMessages(pContext->hPipe, ProcessElevatedChildCacheMessage, pContext, &result); | ||
1259 | ExitOnFailure(hr, "Failed to pump messages in child process."); | ||
1260 | |||
1261 | hr = (HRESULT)result.dwResult; | ||
1262 | |||
1263 | LExit: | ||
1264 | if (fComInitialized) | ||
1265 | { | ||
1266 | ::CoUninitialize(); | ||
1267 | } | ||
1268 | |||
1269 | return (DWORD)hr; | ||
1270 | } | ||
1271 | |||
1272 | static HRESULT WaitForElevatedChildCacheThread( | ||
1273 | __in HANDLE hCacheThread, | ||
1274 | __in DWORD dwExpectedExitCode | ||
1275 | ) | ||
1276 | { | ||
1277 | UNREFERENCED_PARAMETER(dwExpectedExitCode); | ||
1278 | |||
1279 | HRESULT hr = S_OK; | ||
1280 | DWORD dwExitCode = ERROR_SUCCESS; | ||
1281 | |||
1282 | if (WAIT_OBJECT_0 != ::WaitForSingleObject(hCacheThread, BURN_TIMEOUT)) | ||
1283 | { | ||
1284 | ExitWithLastError(hr, "Failed to wait for cache thread to terminate."); | ||
1285 | } | ||
1286 | |||
1287 | if (!::GetExitCodeThread(hCacheThread, &dwExitCode)) | ||
1288 | { | ||
1289 | ExitWithLastError(hr, "Failed to get cache thread exit code."); | ||
1290 | } | ||
1291 | |||
1292 | AssertSz(dwExitCode == dwExpectedExitCode, "Cache thread should have exited with the expected exit code."); | ||
1293 | |||
1294 | LExit: | ||
1295 | return hr; | ||
1296 | } | ||
1297 | |||
1298 | static HRESULT ProcessGenericExecuteMessages( | ||
1299 | __in BURN_PIPE_MESSAGE* pMsg, | ||
1300 | __in_opt LPVOID pvContext, | ||
1301 | __out DWORD* pdwResult | ||
1302 | ) | ||
1303 | { | ||
1304 | HRESULT hr = S_OK; | ||
1305 | SIZE_T iData = 0; | ||
1306 | BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT*>(pvContext); | ||
1307 | LPWSTR sczMessage = NULL; | ||
1308 | DWORD cFiles = 0; | ||
1309 | LPWSTR* rgwzFiles = NULL; | ||
1310 | GENERIC_EXECUTE_MESSAGE message = { }; | ||
1311 | |||
1312 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwAllowedResults); | ||
1313 | ExitOnFailure(hr, "Failed to allowed results."); | ||
1314 | |||
1315 | // Process the message. | ||
1316 | switch (pMsg->dwMessage) | ||
1317 | { | ||
1318 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS: | ||
1319 | message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; | ||
1320 | |||
1321 | // read message parameters | ||
1322 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.progress.dwPercentage); | ||
1323 | ExitOnFailure(hr, "Failed to progress."); | ||
1324 | break; | ||
1325 | |||
1326 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: | ||
1327 | message.type = GENERIC_EXECUTE_MESSAGE_ERROR; | ||
1328 | |||
1329 | // read message parameters | ||
1330 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.error.dwErrorCode); | ||
1331 | ExitOnFailure(hr, "Failed to read error code."); | ||
1332 | |||
1333 | hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage); | ||
1334 | ExitOnFailure(hr, "Failed to read message."); | ||
1335 | |||
1336 | message.error.wzMessage = sczMessage; | ||
1337 | break; | ||
1338 | |||
1339 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE: | ||
1340 | message.type = GENERIC_EXECUTE_MESSAGE_FILES_IN_USE; | ||
1341 | |||
1342 | // read message parameters | ||
1343 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cFiles); | ||
1344 | ExitOnFailure(hr, "Failed to read file count."); | ||
1345 | |||
1346 | rgwzFiles = (LPWSTR*)MemAlloc(sizeof(LPWSTR*) * cFiles, TRUE); | ||
1347 | ExitOnNull(rgwzFiles, hr, E_OUTOFMEMORY, "Failed to allocate buffer for files in use."); | ||
1348 | |||
1349 | for (DWORD i = 0; i < cFiles; ++i) | ||
1350 | { | ||
1351 | hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &rgwzFiles[i]); | ||
1352 | ExitOnFailure(hr, "Failed to read file name: %u", i); | ||
1353 | } | ||
1354 | |||
1355 | message.filesInUse.cFiles = cFiles; | ||
1356 | message.filesInUse.rgwzFiles = (LPCWSTR*)rgwzFiles; | ||
1357 | break; | ||
1358 | |||
1359 | default: | ||
1360 | hr = E_INVALIDARG; | ||
1361 | ExitOnRootFailure(hr, "Invalid package message."); | ||
1362 | break; | ||
1363 | } | ||
1364 | |||
1365 | // send message | ||
1366 | *pdwResult = (DWORD)pContext->pfnGenericMessageHandler(&message, pContext->pvContext);; | ||
1367 | |||
1368 | LExit: | ||
1369 | ReleaseStr(sczMessage); | ||
1370 | |||
1371 | if (rgwzFiles) | ||
1372 | { | ||
1373 | for (DWORD i = 0; i < cFiles; ++i) | ||
1374 | { | ||
1375 | ReleaseStr(rgwzFiles[i]); | ||
1376 | } | ||
1377 | MemFree(rgwzFiles); | ||
1378 | } | ||
1379 | return hr; | ||
1380 | } | ||
1381 | |||
1382 | static HRESULT ProcessMsiPackageMessages( | ||
1383 | __in BURN_PIPE_MESSAGE* pMsg, | ||
1384 | __in_opt LPVOID pvContext, | ||
1385 | __out DWORD* pdwResult | ||
1386 | ) | ||
1387 | { | ||
1388 | HRESULT hr = S_OK; | ||
1389 | SIZE_T iData = 0; | ||
1390 | WIU_MSI_EXECUTE_MESSAGE message = { }; | ||
1391 | DWORD cMsiData = 0; | ||
1392 | LPWSTR* rgwzMsiData = NULL; | ||
1393 | BURN_ELEVATION_MSI_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_MSI_MESSAGE_CONTEXT*>(pvContext); | ||
1394 | LPWSTR sczMessage = NULL; | ||
1395 | |||
1396 | // Read MSI extended message data. | ||
1397 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cMsiData); | ||
1398 | ExitOnFailure(hr, "Failed to read MSI data count."); | ||
1399 | |||
1400 | if (cMsiData) | ||
1401 | { | ||
1402 | rgwzMsiData = (LPWSTR*)MemAlloc(sizeof(LPWSTR*) * cMsiData, TRUE); | ||
1403 | ExitOnNull(rgwzMsiData, hr, E_OUTOFMEMORY, "Failed to allocate buffer to read MSI data."); | ||
1404 | |||
1405 | for (DWORD i = 0; i < cMsiData; ++i) | ||
1406 | { | ||
1407 | hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &rgwzMsiData[i]); | ||
1408 | ExitOnFailure(hr, "Failed to read MSI data: %u", i); | ||
1409 | } | ||
1410 | |||
1411 | message.cData = cMsiData; | ||
1412 | message.rgwzData = (LPCWSTR*)rgwzMsiData; | ||
1413 | } | ||
1414 | |||
1415 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, (DWORD*)&message.dwAllowedResults); | ||
1416 | ExitOnFailure(hr, "Failed to read UI flags."); | ||
1417 | |||
1418 | // Process the rest of the message. | ||
1419 | switch (pMsg->dwMessage) | ||
1420 | { | ||
1421 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS: | ||
1422 | // read message parameters | ||
1423 | message.type = WIU_MSI_EXECUTE_MESSAGE_PROGRESS; | ||
1424 | |||
1425 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.progress.dwPercentage); | ||
1426 | ExitOnFailure(hr, "Failed to read progress."); | ||
1427 | break; | ||
1428 | |||
1429 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: | ||
1430 | // read message parameters | ||
1431 | message.type = WIU_MSI_EXECUTE_MESSAGE_ERROR; | ||
1432 | |||
1433 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.error.dwErrorCode); | ||
1434 | ExitOnFailure(hr, "Failed to read error code."); | ||
1435 | |||
1436 | hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage); | ||
1437 | ExitOnFailure(hr, "Failed to read message."); | ||
1438 | message.error.wzMessage = sczMessage; | ||
1439 | break; | ||
1440 | |||
1441 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE: | ||
1442 | // read message parameters | ||
1443 | message.type = WIU_MSI_EXECUTE_MESSAGE_MSI_MESSAGE; | ||
1444 | |||
1445 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, (DWORD*)&message.msiMessage.mt); | ||
1446 | ExitOnFailure(hr, "Failed to read message type."); | ||
1447 | |||
1448 | hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage); | ||
1449 | ExitOnFailure(hr, "Failed to read message."); | ||
1450 | message.msiMessage.wzMessage = sczMessage; | ||
1451 | break; | ||
1452 | |||
1453 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE: | ||
1454 | message.type = WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE; | ||
1455 | message.msiFilesInUse.cFiles = cMsiData; | ||
1456 | message.msiFilesInUse.rgwzFiles = (LPCWSTR*)rgwzMsiData; | ||
1457 | break; | ||
1458 | |||
1459 | default: | ||
1460 | hr = E_INVALIDARG; | ||
1461 | ExitOnRootFailure(hr, "Invalid package message."); | ||
1462 | break; | ||
1463 | } | ||
1464 | |||
1465 | // send message | ||
1466 | *pdwResult = (DWORD)pContext->pfnMessageHandler(&message, pContext->pvContext); | ||
1467 | |||
1468 | LExit: | ||
1469 | ReleaseStr(sczMessage); | ||
1470 | |||
1471 | if (rgwzMsiData) | ||
1472 | { | ||
1473 | for (DWORD i = 0; i < cMsiData; ++i) | ||
1474 | { | ||
1475 | ReleaseStr(rgwzMsiData[i]); | ||
1476 | } | ||
1477 | |||
1478 | MemFree(rgwzMsiData); | ||
1479 | } | ||
1480 | |||
1481 | return hr; | ||
1482 | } | ||
1483 | |||
1484 | static HRESULT ProcessLaunchApprovedExeMessages( | ||
1485 | __in BURN_PIPE_MESSAGE* pMsg, | ||
1486 | __in_opt LPVOID pvContext, | ||
1487 | __out DWORD* pdwResult | ||
1488 | ) | ||
1489 | { | ||
1490 | HRESULT hr = S_OK; | ||
1491 | SIZE_T iData = 0; | ||
1492 | BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT*>(pvContext); | ||
1493 | DWORD dwProcessId = 0; | ||
1494 | |||
1495 | // Process the message. | ||
1496 | switch (pMsg->dwMessage) | ||
1497 | { | ||
1498 | case BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID: | ||
1499 | // read message parameters | ||
1500 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &dwProcessId); | ||
1501 | ExitOnFailure(hr, "Failed to read approved exe process id."); | ||
1502 | pContext->dwProcessId = dwProcessId; | ||
1503 | break; | ||
1504 | |||
1505 | default: | ||
1506 | hr = E_INVALIDARG; | ||
1507 | ExitOnRootFailure(hr, "Invalid launch approved exe message."); | ||
1508 | break; | ||
1509 | } | ||
1510 | |||
1511 | *pdwResult = static_cast<DWORD>(hr); | ||
1512 | |||
1513 | LExit: | ||
1514 | return hr; | ||
1515 | } | ||
1516 | |||
1517 | static HRESULT ProcessElevatedChildMessage( | ||
1518 | __in BURN_PIPE_MESSAGE* pMsg, | ||
1519 | __in_opt LPVOID pvContext, | ||
1520 | __out DWORD* pdwResult | ||
1521 | ) | ||
1522 | { | ||
1523 | HRESULT hr = S_OK; | ||
1524 | BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext); | ||
1525 | HRESULT hrResult = S_OK; | ||
1526 | DWORD dwPid = 0; | ||
1527 | |||
1528 | switch (pMsg->dwMessage) | ||
1529 | { | ||
1530 | case BURN_ELEVATION_TRANSACTION_BEGIN: | ||
1531 | hrResult = OnMsiBeginTransaction(pContext); | ||
1532 | break; | ||
1533 | |||
1534 | case BURN_ELEVATION_TRANSACTION_COMMIT: | ||
1535 | hrResult = OnMsiCommitTransaction(pContext); | ||
1536 | break; | ||
1537 | |||
1538 | case BURN_ELEVATION_TRANSACTION_ROLLBACK: | ||
1539 | hrResult = OnMsiRollbackTransaction(pContext); | ||
1540 | break; | ||
1541 | |||
1542 | case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE: | ||
1543 | hrResult = OnApplyInitialize(pContext->pVariables, pContext->pRegistration, pContext->phLock, pContext->pfDisabledAutomaticUpdates, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1544 | break; | ||
1545 | |||
1546 | case BURN_ELEVATION_MESSAGE_TYPE_APPLY_UNINITIALIZE: | ||
1547 | hrResult = OnApplyUninitialize(pContext->phLock); | ||
1548 | break; | ||
1549 | |||
1550 | case BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN: | ||
1551 | hrResult = OnSessionBegin(pContext->pRegistration, pContext->pVariables, pContext->pUserExperience, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1552 | break; | ||
1553 | |||
1554 | case BURN_ELEVATION_MESSAGE_TYPE_SESSION_RESUME: | ||
1555 | hrResult = OnSessionResume(pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1556 | break; | ||
1557 | |||
1558 | case BURN_ELEVATION_MESSAGE_TYPE_SESSION_END: | ||
1559 | hrResult = OnSessionEnd(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1560 | break; | ||
1561 | |||
1562 | case BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE: | ||
1563 | hrResult = OnSaveState(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1564 | break; | ||
1565 | |||
1566 | case BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION: | ||
1567 | hrResult = OnProcessDependentRegistration(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1568 | break; | ||
1569 | |||
1570 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE: | ||
1571 | hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pPackages, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1572 | break; | ||
1573 | |||
1574 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE: | ||
1575 | hrResult = OnExecuteMsiPackage(pContext->hPipe, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1576 | break; | ||
1577 | |||
1578 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE: | ||
1579 | hrResult = OnExecuteMspPackage(pContext->hPipe, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1580 | break; | ||
1581 | |||
1582 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE: | ||
1583 | hrResult = OnExecuteMsuPackage(pContext->hPipe, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1584 | break; | ||
1585 | |||
1586 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER: | ||
1587 | hrResult = OnExecutePackageProviderAction(pContext->pPackages, &pContext->pRegistration->relatedBundles, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1588 | break; | ||
1589 | |||
1590 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY: | ||
1591 | hrResult = OnExecutePackageDependencyAction(pContext->pPackages, &pContext->pRegistration->relatedBundles, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1592 | break; | ||
1593 | |||
1594 | case BURN_ELEVATION_MESSAGE_TYPE_LOAD_COMPATIBLE_PACKAGE: | ||
1595 | hrResult = OnLoadCompatiblePackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1596 | break; | ||
1597 | |||
1598 | case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE: | ||
1599 | hrResult = OnCleanPackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1600 | break; | ||
1601 | |||
1602 | case BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE: | ||
1603 | hrResult = OnLaunchApprovedExe(pContext->hPipe, pContext->pApprovedExes, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1604 | break; | ||
1605 | |||
1606 | default: | ||
1607 | hr = E_INVALIDARG; | ||
1608 | ExitOnRootFailure(hr, "Unexpected elevated message sent to child process, msg: %u", pMsg->dwMessage); | ||
1609 | } | ||
1610 | |||
1611 | *pdwResult = dwPid ? dwPid : (DWORD)hrResult; | ||
1612 | |||
1613 | LExit: | ||
1614 | return hr; | ||
1615 | } | ||
1616 | |||
1617 | static HRESULT ProcessElevatedChildCacheMessage( | ||
1618 | __in BURN_PIPE_MESSAGE* pMsg, | ||
1619 | __in_opt LPVOID pvContext, | ||
1620 | __out DWORD* pdwResult | ||
1621 | ) | ||
1622 | { | ||
1623 | HRESULT hr = S_OK; | ||
1624 | BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext); | ||
1625 | HRESULT hrResult = S_OK; | ||
1626 | |||
1627 | switch (pMsg->dwMessage) | ||
1628 | { | ||
1629 | case BURN_ELEVATION_MESSAGE_TYPE_LAYOUT_BUNDLE: | ||
1630 | hrResult = OnLayoutBundle(pContext->pRegistration->sczExecutableName, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1631 | break; | ||
1632 | |||
1633 | case BURN_ELEVATION_MESSAGE_TYPE_CACHE_OR_LAYOUT_CONTAINER_OR_PAYLOAD: | ||
1634 | hrResult = OnCacheOrLayoutContainerOrPayload(pContext->pContainers, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1635 | break; | ||
1636 | |||
1637 | case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP: | ||
1638 | OnCacheCleanup(pContext->pRegistration->sczId); | ||
1639 | hrResult = S_OK; | ||
1640 | break; | ||
1641 | |||
1642 | case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE: | ||
1643 | hrResult = OnCleanPackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); | ||
1644 | break; | ||
1645 | |||
1646 | default: | ||
1647 | hr = E_INVALIDARG; | ||
1648 | ExitOnRootFailure(hr, "Unexpected elevated cache message sent to child process, msg: %u", pMsg->dwMessage); | ||
1649 | } | ||
1650 | |||
1651 | *pdwResult = (DWORD)hrResult; | ||
1652 | |||
1653 | LExit: | ||
1654 | return hr; | ||
1655 | } | ||
1656 | |||
1657 | static HRESULT ProcessResult( | ||
1658 | __in DWORD dwResult, | ||
1659 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
1660 | ) | ||
1661 | { | ||
1662 | HRESULT hr = static_cast<HRESULT>(dwResult); | ||
1663 | if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) == hr) | ||
1664 | { | ||
1665 | *pRestart = BOOTSTRAPPER_APPLY_RESTART_REQUIRED; | ||
1666 | hr = S_OK; | ||
1667 | } | ||
1668 | else if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED) == hr) | ||
1669 | { | ||
1670 | *pRestart = BOOTSTRAPPER_APPLY_RESTART_INITIATED; | ||
1671 | hr = S_OK; | ||
1672 | } | ||
1673 | |||
1674 | return hr; | ||
1675 | } | ||
1676 | |||
1677 | static HRESULT OnMsiBeginTransaction( | ||
1678 | __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext | ||
1679 | ) | ||
1680 | { | ||
1681 | UINT uResult = ERROR_SUCCESS; | ||
1682 | HRESULT hr = S_OK; | ||
1683 | |||
1684 | pContext->hMsiTrns = NULL; | ||
1685 | pContext->hMsiTrnsEvent = NULL; | ||
1686 | uResult = MsiBeginTransaction(L"WiX", 0, &pContext->hMsiTrns, &pContext->hMsiTrnsEvent); | ||
1687 | ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction"); | ||
1688 | |||
1689 | LExit: | ||
1690 | return hr; | ||
1691 | } | ||
1692 | |||
1693 | static HRESULT OnMsiCommitTransaction( | ||
1694 | __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext | ||
1695 | ) | ||
1696 | { | ||
1697 | UINT uResult = ERROR_SUCCESS; | ||
1698 | HRESULT hr = S_OK; | ||
1699 | |||
1700 | uResult = MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT); | ||
1701 | ExitOnWin32Error(uResult, hr, "Failed committing an MSI transaction"); | ||
1702 | |||
1703 | LExit: | ||
1704 | pContext->hMsiTrns = NULL; | ||
1705 | pContext->hMsiTrnsEvent = NULL; | ||
1706 | return hr; | ||
1707 | } | ||
1708 | |||
1709 | static HRESULT OnMsiRollbackTransaction( | ||
1710 | __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext | ||
1711 | ) { | ||
1712 | UINT uResult = ERROR_SUCCESS; | ||
1713 | HRESULT hr = S_OK; | ||
1714 | |||
1715 | uResult = MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK); | ||
1716 | ExitOnWin32Error(uResult, hr, "Failed rolling back an MSI transaction"); | ||
1717 | |||
1718 | LExit: | ||
1719 | pContext->hMsiTrns = NULL; | ||
1720 | pContext->hMsiTrnsEvent = NULL; | ||
1721 | return hr; | ||
1722 | } | ||
1723 | |||
1724 | static HRESULT OnApplyInitialize( | ||
1725 | __in BURN_VARIABLES* pVariables, | ||
1726 | __in BURN_REGISTRATION* pRegistration, | ||
1727 | __in HANDLE* phLock, | ||
1728 | __in BOOL* pfDisabledWindowsUpdate, | ||
1729 | __in BYTE* pbData, | ||
1730 | __in DWORD cbData | ||
1731 | ) | ||
1732 | { | ||
1733 | HRESULT hr = S_OK; | ||
1734 | SIZE_T iData = 0; | ||
1735 | DWORD dwAction = 0; | ||
1736 | DWORD dwAUAction = 0; | ||
1737 | DWORD dwTakeSystemRestorePoint = 0; | ||
1738 | LPWSTR sczBundleName = NULL; | ||
1739 | |||
1740 | // Deserialize message data. | ||
1741 | hr = BuffReadNumber(pbData, cbData, &iData, &dwAction); | ||
1742 | ExitOnFailure(hr, "Failed to read action."); | ||
1743 | |||
1744 | hr = BuffReadNumber(pbData, cbData, &iData, &dwAUAction); | ||
1745 | ExitOnFailure(hr, "Failed to read update action."); | ||
1746 | |||
1747 | hr = BuffReadNumber(pbData, cbData, &iData, &dwTakeSystemRestorePoint); | ||
1748 | ExitOnFailure(hr, "Failed to read system restore point action."); | ||
1749 | |||
1750 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | ||
1751 | ExitOnFailure(hr, "Failed to read variables."); | ||
1752 | |||
1753 | // Initialize. | ||
1754 | hr = ApplyLock(TRUE, phLock); | ||
1755 | ExitOnFailure(hr, "Failed to acquire lock due to setup in other session."); | ||
1756 | |||
1757 | // Reset and reload the related bundles. | ||
1758 | RelatedBundlesUninitialize(&pRegistration->relatedBundles); | ||
1759 | |||
1760 | hr = RelatedBundlesInitializeForScope(TRUE, pRegistration, &pRegistration->relatedBundles); | ||
1761 | ExitOnFailure(hr, "Failed to initialize per-machine related bundles."); | ||
1762 | |||
1763 | // Attempt to pause AU with best effort. | ||
1764 | if (BURN_AU_PAUSE_ACTION_IFELEVATED == dwAUAction || BURN_AU_PAUSE_ACTION_IFELEVATED_NORESUME == dwAUAction) | ||
1765 | { | ||
1766 | LogId(REPORT_STANDARD, MSG_PAUSE_AU_STARTING); | ||
1767 | |||
1768 | hr = WuaPauseAutomaticUpdates(); | ||
1769 | if (FAILED(hr)) | ||
1770 | { | ||
1771 | LogId(REPORT_STANDARD, MSG_FAILED_PAUSE_AU, hr); | ||
1772 | hr = S_OK; | ||
1773 | } | ||
1774 | else | ||
1775 | { | ||
1776 | LogId(REPORT_STANDARD, MSG_PAUSE_AU_SUCCEEDED); | ||
1777 | if (BURN_AU_PAUSE_ACTION_IFELEVATED == dwAUAction) | ||
1778 | { | ||
1779 | *pfDisabledWindowsUpdate = TRUE; | ||
1780 | } | ||
1781 | } | ||
1782 | } | ||
1783 | |||
1784 | if (dwTakeSystemRestorePoint) | ||
1785 | { | ||
1786 | hr = VariableGetString(pVariables, BURN_BUNDLE_NAME, &sczBundleName); | ||
1787 | if (FAILED(hr)) | ||
1788 | { | ||
1789 | hr = S_OK; | ||
1790 | ExitFunction(); | ||
1791 | } | ||
1792 | |||
1793 | LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_STARTING); | ||
1794 | |||
1795 | BOOTSTRAPPER_ACTION action = static_cast<BOOTSTRAPPER_ACTION>(dwAction); | ||
1796 | SRP_ACTION restoreAction = (BOOTSTRAPPER_ACTION_INSTALL == action) ? SRP_ACTION_INSTALL : (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? SRP_ACTION_UNINSTALL : SRP_ACTION_MODIFY; | ||
1797 | hr = SrpCreateRestorePoint(sczBundleName, restoreAction); | ||
1798 | if (SUCCEEDED(hr)) | ||
1799 | { | ||
1800 | LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_SUCCEEDED); | ||
1801 | } | ||
1802 | else if (E_NOTIMPL == hr) | ||
1803 | { | ||
1804 | LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_DISABLED); | ||
1805 | hr = S_OK; | ||
1806 | } | ||
1807 | else if (FAILED(hr)) | ||
1808 | { | ||
1809 | LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_FAILED, hr); | ||
1810 | hr = S_OK; | ||
1811 | } | ||
1812 | } | ||
1813 | |||
1814 | LExit: | ||
1815 | ReleaseStr(sczBundleName); | ||
1816 | return hr; | ||
1817 | } | ||
1818 | |||
1819 | static HRESULT OnApplyUninitialize( | ||
1820 | __in HANDLE* phLock | ||
1821 | ) | ||
1822 | { | ||
1823 | Assert(phLock); | ||
1824 | |||
1825 | // TODO: end system restore point. | ||
1826 | |||
1827 | if (*phLock) | ||
1828 | { | ||
1829 | ::ReleaseMutex(*phLock); | ||
1830 | ::CloseHandle(*phLock); | ||
1831 | *phLock = NULL; | ||
1832 | } | ||
1833 | |||
1834 | return S_OK; | ||
1835 | } | ||
1836 | |||
1837 | static HRESULT OnSessionBegin( | ||
1838 | __in BURN_REGISTRATION* pRegistration, | ||
1839 | __in BURN_VARIABLES* pVariables, | ||
1840 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
1841 | __in BYTE* pbData, | ||
1842 | __in DWORD cbData | ||
1843 | ) | ||
1844 | { | ||
1845 | HRESULT hr = S_OK; | ||
1846 | SIZE_T iData = 0; | ||
1847 | LPWSTR sczEngineWorkingPath = NULL; | ||
1848 | DWORD dwRegistrationOperations = 0; | ||
1849 | DWORD dwDependencyRegistrationAction = 0; | ||
1850 | DWORD64 qwEstimatedSize = 0; | ||
1851 | |||
1852 | // Deserialize message data. | ||
1853 | hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingPath); | ||
1854 | ExitOnFailure(hr, "Failed to read engine working path."); | ||
1855 | |||
1856 | hr = BuffReadString(pbData, cbData, &iData, &pRegistration->sczResumeCommandLine); | ||
1857 | ExitOnFailure(hr, "Failed to read resume command line."); | ||
1858 | |||
1859 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDisableResume); | ||
1860 | ExitOnFailure(hr, "Failed to read resume flag."); | ||
1861 | |||
1862 | hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationOperations); | ||
1863 | ExitOnFailure(hr, "Failed to read registration operations."); | ||
1864 | |||
1865 | hr = BuffReadNumber(pbData, cbData, &iData, &dwDependencyRegistrationAction); | ||
1866 | ExitOnFailure(hr, "Failed to read dependency registration action."); | ||
1867 | |||
1868 | hr = BuffReadNumber64(pbData, cbData, &iData, &qwEstimatedSize); | ||
1869 | ExitOnFailure(hr, "Failed to read estimated size."); | ||
1870 | |||
1871 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | ||
1872 | ExitOnFailure(hr, "Failed to read variables."); | ||
1873 | |||
1874 | // Begin session in per-machine process. | ||
1875 | hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pVariables, pUserExperience, dwRegistrationOperations, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, qwEstimatedSize); | ||
1876 | ExitOnFailure(hr, "Failed to begin registration session."); | ||
1877 | |||
1878 | LExit: | ||
1879 | ReleaseStr(sczEngineWorkingPath); | ||
1880 | |||
1881 | return hr; | ||
1882 | } | ||
1883 | |||
1884 | static HRESULT OnSessionResume( | ||
1885 | __in BURN_REGISTRATION* pRegistration, | ||
1886 | __in BURN_VARIABLES* pVariables, | ||
1887 | __in BYTE* pbData, | ||
1888 | __in DWORD cbData | ||
1889 | ) | ||
1890 | { | ||
1891 | HRESULT hr = S_OK; | ||
1892 | SIZE_T iData = 0; | ||
1893 | |||
1894 | // Deserialize message data. | ||
1895 | hr = BuffReadString(pbData, cbData, &iData, &pRegistration->sczResumeCommandLine); | ||
1896 | ExitOnFailure(hr, "Failed to read resume command line."); | ||
1897 | |||
1898 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDisableResume); | ||
1899 | ExitOnFailure(hr, "Failed to read resume flag."); | ||
1900 | |||
1901 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | ||
1902 | ExitOnFailure(hr, "Failed to read variables."); | ||
1903 | |||
1904 | // resume session in per-machine process | ||
1905 | hr = RegistrationSessionResume(pRegistration, pVariables); | ||
1906 | ExitOnFailure(hr, "Failed to resume registration session."); | ||
1907 | |||
1908 | LExit: | ||
1909 | return hr; | ||
1910 | } | ||
1911 | |||
1912 | static HRESULT OnSessionEnd( | ||
1913 | __in BURN_REGISTRATION* pRegistration, | ||
1914 | __in BYTE* pbData, | ||
1915 | __in DWORD cbData | ||
1916 | ) | ||
1917 | { | ||
1918 | HRESULT hr = S_OK; | ||
1919 | SIZE_T iData = 0; | ||
1920 | DWORD dwResumeMode = 0; | ||
1921 | DWORD dwRestart = 0; | ||
1922 | DWORD dwDependencyRegistrationAction = 0; | ||
1923 | |||
1924 | // Deserialize message data. | ||
1925 | hr = BuffReadNumber(pbData, cbData, &iData, &dwResumeMode); | ||
1926 | ExitOnFailure(hr, "Failed to read resume mode enum."); | ||
1927 | |||
1928 | hr = BuffReadNumber(pbData, cbData, &iData, &dwRestart); | ||
1929 | ExitOnFailure(hr, "Failed to read restart enum."); | ||
1930 | |||
1931 | hr = BuffReadNumber(pbData, cbData, &iData, &dwDependencyRegistrationAction); | ||
1932 | ExitOnFailure(hr, "Failed to read dependency registration action."); | ||
1933 | |||
1934 | // suspend session in per-machine process | ||
1935 | hr = RegistrationSessionEnd(pRegistration, (BURN_RESUME_MODE)dwResumeMode, (BOOTSTRAPPER_APPLY_RESTART)dwRestart, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction); | ||
1936 | ExitOnFailure(hr, "Failed to suspend registration session."); | ||
1937 | |||
1938 | LExit: | ||
1939 | return hr; | ||
1940 | } | ||
1941 | |||
1942 | static HRESULT OnSaveState( | ||
1943 | __in BURN_REGISTRATION* pRegistration, | ||
1944 | __in BYTE* pbData, | ||
1945 | __in DWORD cbData | ||
1946 | ) | ||
1947 | { | ||
1948 | HRESULT hr = S_OK; | ||
1949 | |||
1950 | // save state in per-machine process | ||
1951 | hr = RegistrationSaveState(pRegistration, pbData, cbData); | ||
1952 | ExitOnFailure(hr, "Failed to save state."); | ||
1953 | |||
1954 | LExit: | ||
1955 | return hr; | ||
1956 | } | ||
1957 | |||
1958 | static HRESULT OnLayoutBundle( | ||
1959 | __in_z LPCWSTR wzExecutableName, | ||
1960 | __in BYTE* pbData, | ||
1961 | __in DWORD cbData | ||
1962 | ) | ||
1963 | { | ||
1964 | HRESULT hr = S_OK; | ||
1965 | SIZE_T iData = 0; | ||
1966 | LPWSTR sczLayoutDirectory = NULL; | ||
1967 | LPWSTR sczUnverifiedPath = NULL; | ||
1968 | |||
1969 | // Deserialize message data. | ||
1970 | hr = BuffReadString(pbData, cbData, &iData, &sczLayoutDirectory); | ||
1971 | ExitOnFailure(hr, "Failed to read layout directory."); | ||
1972 | |||
1973 | hr = BuffReadString(pbData, cbData, &iData, &sczUnverifiedPath); | ||
1974 | ExitOnFailure(hr, "Failed to read unverified bundle path."); | ||
1975 | |||
1976 | // Layout the bundle. | ||
1977 | hr = CacheLayoutBundle(wzExecutableName, sczLayoutDirectory, sczUnverifiedPath); | ||
1978 | ExitOnFailure(hr, "Failed to layout bundle from: %ls", sczUnverifiedPath); | ||
1979 | |||
1980 | LExit: | ||
1981 | ReleaseStr(sczUnverifiedPath); | ||
1982 | ReleaseStr(sczLayoutDirectory); | ||
1983 | |||
1984 | return hr; | ||
1985 | } | ||
1986 | |||
1987 | static HRESULT OnCacheOrLayoutContainerOrPayload( | ||
1988 | __in BURN_CONTAINERS* pContainers, | ||
1989 | __in BURN_PACKAGES* pPackages, | ||
1990 | __in BURN_PAYLOADS* pPayloads, | ||
1991 | __in BYTE* pbData, | ||
1992 | __in DWORD cbData | ||
1993 | ) | ||
1994 | { | ||
1995 | HRESULT hr = S_OK; | ||
1996 | SIZE_T iData = 0; | ||
1997 | LPWSTR scz = NULL; | ||
1998 | BURN_CONTAINER* pContainer = NULL; | ||
1999 | BURN_PACKAGE* pPackage = NULL; | ||
2000 | BURN_PAYLOAD* pPayload = NULL; | ||
2001 | LPWSTR sczLayoutDirectory = NULL; | ||
2002 | LPWSTR sczUnverifiedPath = NULL; | ||
2003 | BOOL fMove = FALSE; | ||
2004 | |||
2005 | // Deserialize message data. | ||
2006 | hr = BuffReadString(pbData, cbData, &iData, &scz); | ||
2007 | ExitOnFailure(hr, "Failed to read package id."); | ||
2008 | |||
2009 | if (scz && *scz) | ||
2010 | { | ||
2011 | hr = ContainerFindById(pContainers, scz, &pContainer); | ||
2012 | ExitOnFailure(hr, "Failed to find container: %ls", scz); | ||
2013 | } | ||
2014 | |||
2015 | hr = BuffReadString(pbData, cbData, &iData, &scz); | ||
2016 | ExitOnFailure(hr, "Failed to read package id."); | ||
2017 | |||
2018 | if (scz && *scz) | ||
2019 | { | ||
2020 | hr = PackageFindById(pPackages, scz, &pPackage); | ||
2021 | ExitOnFailure(hr, "Failed to find package: %ls", scz); | ||
2022 | } | ||
2023 | |||
2024 | hr = BuffReadString(pbData, cbData, &iData, &scz); | ||
2025 | ExitOnFailure(hr, "Failed to read payload id."); | ||
2026 | |||
2027 | if (scz && *scz) | ||
2028 | { | ||
2029 | hr = PayloadFindById(pPayloads, scz, &pPayload); | ||
2030 | ExitOnFailure(hr, "Failed to find payload: %ls", scz); | ||
2031 | } | ||
2032 | |||
2033 | hr = BuffReadString(pbData, cbData, &iData, &sczLayoutDirectory); | ||
2034 | ExitOnFailure(hr, "Failed to read layout directory."); | ||
2035 | |||
2036 | hr = BuffReadString(pbData, cbData, &iData, &sczUnverifiedPath); | ||
2037 | ExitOnFailure(hr, "Failed to read unverified path."); | ||
2038 | |||
2039 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fMove); | ||
2040 | ExitOnFailure(hr, "Failed to read move flag."); | ||
2041 | |||
2042 | // Layout payload. | ||
2043 | if (sczLayoutDirectory && *sczLayoutDirectory) | ||
2044 | { | ||
2045 | if (pContainer) | ||
2046 | { | ||
2047 | Assert(!pPackage); | ||
2048 | Assert(!pPayload); | ||
2049 | |||
2050 | hr = CacheLayoutContainer(pContainer, sczLayoutDirectory, sczUnverifiedPath, fMove); | ||
2051 | ExitOnFailure(hr, "Failed to layout container from: %ls to %ls", sczUnverifiedPath, sczLayoutDirectory); | ||
2052 | } | ||
2053 | else | ||
2054 | { | ||
2055 | hr = CacheLayoutPayload(pPayload, sczLayoutDirectory, sczUnverifiedPath, fMove); | ||
2056 | ExitOnFailure(hr, "Failed to layout payload from: %ls to %ls", sczUnverifiedPath, sczLayoutDirectory); | ||
2057 | } | ||
2058 | } | ||
2059 | else if (pPackage) // complete payload. | ||
2060 | { | ||
2061 | Assert(!pContainer); | ||
2062 | |||
2063 | hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove); | ||
2064 | ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey); | ||
2065 | } | ||
2066 | else | ||
2067 | { | ||
2068 | hr = E_INVALIDARG; | ||
2069 | ExitOnRootFailure(hr, "Invalid data passed to cache or layout payload."); | ||
2070 | } | ||
2071 | |||
2072 | LExit: | ||
2073 | ReleaseStr(sczUnverifiedPath); | ||
2074 | ReleaseStr(sczLayoutDirectory); | ||
2075 | ReleaseStr(scz); | ||
2076 | |||
2077 | return hr; | ||
2078 | } | ||
2079 | |||
2080 | static void OnCacheCleanup( | ||
2081 | __in_z LPCWSTR wzBundleId | ||
2082 | ) | ||
2083 | { | ||
2084 | CacheCleanup(TRUE, wzBundleId); | ||
2085 | } | ||
2086 | |||
2087 | static HRESULT OnProcessDependentRegistration( | ||
2088 | __in const BURN_REGISTRATION* pRegistration, | ||
2089 | __in BYTE* pbData, | ||
2090 | __in DWORD cbData | ||
2091 | ) | ||
2092 | { | ||
2093 | HRESULT hr = S_OK; | ||
2094 | SIZE_T iData = 0; | ||
2095 | BURN_DEPENDENT_REGISTRATION_ACTION action = { }; | ||
2096 | |||
2097 | // Deserialize message data. | ||
2098 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&action.type); | ||
2099 | ExitOnFailure(hr, "Failed to read action type."); | ||
2100 | |||
2101 | hr = BuffReadString(pbData, cbData, &iData, &action.sczBundleId); | ||
2102 | ExitOnFailure(hr, "Failed to read bundle id."); | ||
2103 | |||
2104 | hr = BuffReadString(pbData, cbData, &iData, &action.sczDependentProviderKey); | ||
2105 | ExitOnFailure(hr, "Failed to read dependent provider key."); | ||
2106 | |||
2107 | // Execute the registration action. | ||
2108 | hr = DependencyProcessDependentRegistration(pRegistration, &action); | ||
2109 | ExitOnFailure(hr, "Failed to execute dependent registration action for provider key: %ls", action.sczDependentProviderKey); | ||
2110 | |||
2111 | LExit: | ||
2112 | // TODO: do the right thing here. | ||
2113 | //DependencyUninitializeRegistrationAction(&action); | ||
2114 | ReleaseStr(action.sczDependentProviderKey); | ||
2115 | ReleaseStr(action.sczBundleId) | ||
2116 | |||
2117 | return hr; | ||
2118 | } | ||
2119 | |||
2120 | static HRESULT OnExecuteExePackage( | ||
2121 | __in HANDLE hPipe, | ||
2122 | __in BURN_PACKAGES* pPackages, | ||
2123 | __in BURN_RELATED_BUNDLES* pRelatedBundles, | ||
2124 | __in BURN_VARIABLES* pVariables, | ||
2125 | __in BYTE* pbData, | ||
2126 | __in DWORD cbData | ||
2127 | ) | ||
2128 | { | ||
2129 | HRESULT hr = S_OK; | ||
2130 | SIZE_T iData = 0; | ||
2131 | LPWSTR sczPackage = NULL; | ||
2132 | DWORD dwRollback = 0; | ||
2133 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2134 | LPWSTR sczIgnoreDependencies = NULL; | ||
2135 | LPWSTR sczAncestors = NULL; | ||
2136 | BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
2137 | |||
2138 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; | ||
2139 | |||
2140 | // Deserialize message data. | ||
2141 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2142 | ExitOnFailure(hr, "Failed to read EXE package id."); | ||
2143 | |||
2144 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action); | ||
2145 | ExitOnFailure(hr, "Failed to read action."); | ||
2146 | |||
2147 | hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); | ||
2148 | ExitOnFailure(hr, "Failed to read rollback."); | ||
2149 | |||
2150 | hr = BuffReadString(pbData, cbData, &iData, &sczIgnoreDependencies); | ||
2151 | ExitOnFailure(hr, "Failed to read the list of dependencies to ignore."); | ||
2152 | |||
2153 | hr = BuffReadString(pbData, cbData, &iData, &sczAncestors); | ||
2154 | ExitOnFailure(hr, "Failed to read the list of ancestors."); | ||
2155 | |||
2156 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | ||
2157 | ExitOnFailure(hr, "Failed to read variables."); | ||
2158 | |||
2159 | hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage); | ||
2160 | if (E_NOTFOUND == hr) | ||
2161 | { | ||
2162 | hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.exePackage.pPackage); | ||
2163 | } | ||
2164 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2165 | |||
2166 | // Pass the list of dependencies to ignore, if any, to the related bundle. | ||
2167 | if (sczIgnoreDependencies && *sczIgnoreDependencies) | ||
2168 | { | ||
2169 | hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0); | ||
2170 | ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); | ||
2171 | } | ||
2172 | |||
2173 | // Pass the list of ancestors, if any, to the related bundle. | ||
2174 | if (sczAncestors && *sczAncestors) | ||
2175 | { | ||
2176 | hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0); | ||
2177 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); | ||
2178 | } | ||
2179 | |||
2180 | // Execute EXE package. | ||
2181 | hr = ExeEngineExecutePackage(&executeAction, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); | ||
2182 | ExitOnFailure(hr, "Failed to execute EXE package."); | ||
2183 | |||
2184 | LExit: | ||
2185 | ReleaseStr(sczAncestors); | ||
2186 | ReleaseStr(sczIgnoreDependencies); | ||
2187 | ReleaseStr(sczPackage); | ||
2188 | PlanUninitializeExecuteAction(&executeAction); | ||
2189 | |||
2190 | if (SUCCEEDED(hr)) | ||
2191 | { | ||
2192 | if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart) | ||
2193 | { | ||
2194 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); | ||
2195 | } | ||
2196 | else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == exeRestart) | ||
2197 | { | ||
2198 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED); | ||
2199 | } | ||
2200 | } | ||
2201 | |||
2202 | return hr; | ||
2203 | } | ||
2204 | |||
2205 | static HRESULT OnExecuteMsiPackage( | ||
2206 | __in HANDLE hPipe, | ||
2207 | __in BURN_PACKAGES* pPackages, | ||
2208 | __in BURN_VARIABLES* pVariables, | ||
2209 | __in BYTE* pbData, | ||
2210 | __in DWORD cbData | ||
2211 | ) | ||
2212 | { | ||
2213 | HRESULT hr = S_OK; | ||
2214 | SIZE_T iData = 0; | ||
2215 | LPWSTR sczPackage = NULL; | ||
2216 | HWND hwndParent = NULL; | ||
2217 | BOOL fRollback = 0; | ||
2218 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2219 | BOOTSTRAPPER_APPLY_RESTART msiRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
2220 | |||
2221 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE; | ||
2222 | |||
2223 | // Deserialize message data. | ||
2224 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2225 | ExitOnFailure(hr, "Failed to read MSI package id."); | ||
2226 | |||
2227 | hr = PackageFindById(pPackages, sczPackage, &executeAction.msiPackage.pPackage); | ||
2228 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2229 | |||
2230 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&hwndParent); | ||
2231 | ExitOnFailure(hr, "Failed to read parent hwnd."); | ||
2232 | |||
2233 | hr = BuffReadString(pbData, cbData, &iData, &executeAction.msiPackage.sczLogPath); | ||
2234 | ExitOnFailure(hr, "Failed to read package log."); | ||
2235 | |||
2236 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.uiLevel); | ||
2237 | ExitOnFailure(hr, "Failed to read UI level."); | ||
2238 | |||
2239 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.action); | ||
2240 | ExitOnFailure(hr, "Failed to read action."); | ||
2241 | |||
2242 | // Read feature actions. | ||
2243 | if (executeAction.msiPackage.pPackage->Msi.cFeatures) | ||
2244 | { | ||
2245 | executeAction.msiPackage.rgFeatures = (BOOTSTRAPPER_FEATURE_ACTION*)MemAlloc(executeAction.msiPackage.pPackage->Msi.cFeatures * sizeof(BOOTSTRAPPER_FEATURE_ACTION), TRUE); | ||
2246 | ExitOnNull(executeAction.msiPackage.rgFeatures, hr, E_OUTOFMEMORY, "Failed to allocate memory for feature actions."); | ||
2247 | |||
2248 | for (DWORD i = 0; i < executeAction.msiPackage.pPackage->Msi.cFeatures; ++i) | ||
2249 | { | ||
2250 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.rgFeatures[i]); | ||
2251 | ExitOnFailure(hr, "Failed to read feature action."); | ||
2252 | } | ||
2253 | } | ||
2254 | |||
2255 | // Read slipstream patches actions. | ||
2256 | if (executeAction.msiPackage.pPackage->Msi.cSlipstreamMspPackages) | ||
2257 | { | ||
2258 | executeAction.msiPackage.rgSlipstreamPatches = (BOOTSTRAPPER_ACTION_STATE*)MemAlloc(executeAction.msiPackage.pPackage->Msi.cSlipstreamMspPackages * sizeof(BOOTSTRAPPER_ACTION_STATE), TRUE); | ||
2259 | ExitOnNull(executeAction.msiPackage.rgSlipstreamPatches, hr, E_OUTOFMEMORY, "Failed to allocate memory for slipstream patch actions."); | ||
2260 | |||
2261 | for (DWORD i = 0; i < executeAction.msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++i) | ||
2262 | { | ||
2263 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.rgSlipstreamPatches[i]); | ||
2264 | ExitOnFailure(hr, "Failed to read slipstream action."); | ||
2265 | } | ||
2266 | } | ||
2267 | |||
2268 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | ||
2269 | ExitOnFailure(hr, "Failed to read variables."); | ||
2270 | |||
2271 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); | ||
2272 | ExitOnFailure(hr, "Failed to read rollback flag."); | ||
2273 | |||
2274 | // Execute MSI package. | ||
2275 | hr = MsiEngineExecutePackage(hwndParent, &executeAction, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &msiRestart); | ||
2276 | ExitOnFailure(hr, "Failed to execute MSI package."); | ||
2277 | |||
2278 | LExit: | ||
2279 | ReleaseStr(sczPackage); | ||
2280 | PlanUninitializeExecuteAction(&executeAction); | ||
2281 | |||
2282 | if (SUCCEEDED(hr)) | ||
2283 | { | ||
2284 | if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == msiRestart) | ||
2285 | { | ||
2286 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); | ||
2287 | } | ||
2288 | else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == msiRestart) | ||
2289 | { | ||
2290 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED); | ||
2291 | } | ||
2292 | } | ||
2293 | |||
2294 | return hr; | ||
2295 | } | ||
2296 | |||
2297 | static HRESULT OnExecuteMspPackage( | ||
2298 | __in HANDLE hPipe, | ||
2299 | __in BURN_PACKAGES* pPackages, | ||
2300 | __in BURN_VARIABLES* pVariables, | ||
2301 | __in BYTE* pbData, | ||
2302 | __in DWORD cbData | ||
2303 | ) | ||
2304 | { | ||
2305 | HRESULT hr = S_OK; | ||
2306 | SIZE_T iData = 0; | ||
2307 | LPWSTR sczPackage = NULL; | ||
2308 | HWND hwndParent = NULL; | ||
2309 | BOOL fRollback = 0; | ||
2310 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2311 | BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
2312 | |||
2313 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSP_TARGET; | ||
2314 | |||
2315 | // Deserialize message data. | ||
2316 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2317 | ExitOnFailure(hr, "Failed to read MSP package id."); | ||
2318 | |||
2319 | hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.pPackage); | ||
2320 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2321 | |||
2322 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&hwndParent); | ||
2323 | ExitOnFailure(hr, "Failed to read parent hwnd."); | ||
2324 | |||
2325 | executeAction.mspTarget.fPerMachineTarget = TRUE; // we're in the elevated process, clearly we're targeting a per-machine product. | ||
2326 | |||
2327 | hr = BuffReadString(pbData, cbData, &iData, &executeAction.mspTarget.sczTargetProductCode); | ||
2328 | ExitOnFailure(hr, "Failed to read target product code."); | ||
2329 | |||
2330 | hr = BuffReadString(pbData, cbData, &iData, &executeAction.mspTarget.sczLogPath); | ||
2331 | ExitOnFailure(hr, "Failed to read package log."); | ||
2332 | |||
2333 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.uiLevel); | ||
2334 | ExitOnFailure(hr, "Failed to read UI level."); | ||
2335 | |||
2336 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.action); | ||
2337 | ExitOnFailure(hr, "Failed to read action."); | ||
2338 | |||
2339 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.cOrderedPatches); | ||
2340 | ExitOnFailure(hr, "Failed to read count of ordered patches."); | ||
2341 | |||
2342 | if (executeAction.mspTarget.cOrderedPatches) | ||
2343 | { | ||
2344 | executeAction.mspTarget.rgOrderedPatches = (BURN_ORDERED_PATCHES*)MemAlloc(executeAction.mspTarget.cOrderedPatches * sizeof(BURN_ORDERED_PATCHES), TRUE); | ||
2345 | ExitOnNull(executeAction.mspTarget.rgOrderedPatches, hr, E_OUTOFMEMORY, "Failed to allocate memory for ordered patches."); | ||
2346 | |||
2347 | for (DWORD i = 0; i < executeAction.mspTarget.cOrderedPatches; ++i) | ||
2348 | { | ||
2349 | hr = BuffReadNumber(pbData, cbData, &iData, &executeAction.mspTarget.rgOrderedPatches[i].dwOrder); | ||
2350 | ExitOnFailure(hr, "Failed to read ordered patch order number."); | ||
2351 | |||
2352 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2353 | ExitOnFailure(hr, "Failed to read ordered patch package id."); | ||
2354 | |||
2355 | hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.rgOrderedPatches[i].pPackage); | ||
2356 | ExitOnFailure(hr, "Failed to find ordered patch package: %ls", sczPackage); | ||
2357 | } | ||
2358 | } | ||
2359 | |||
2360 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | ||
2361 | ExitOnFailure(hr, "Failed to read variables."); | ||
2362 | |||
2363 | hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); | ||
2364 | ExitOnFailure(hr, "Failed to read rollback flag."); | ||
2365 | |||
2366 | // Execute MSP package. | ||
2367 | hr = MspEngineExecutePackage(hwndParent, &executeAction, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &restart); | ||
2368 | ExitOnFailure(hr, "Failed to execute MSP package."); | ||
2369 | |||
2370 | LExit: | ||
2371 | ReleaseStr(sczPackage); | ||
2372 | PlanUninitializeExecuteAction(&executeAction); | ||
2373 | |||
2374 | if (SUCCEEDED(hr)) | ||
2375 | { | ||
2376 | if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == restart) | ||
2377 | { | ||
2378 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); | ||
2379 | } | ||
2380 | else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart) | ||
2381 | { | ||
2382 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED); | ||
2383 | } | ||
2384 | } | ||
2385 | |||
2386 | return hr; | ||
2387 | } | ||
2388 | |||
2389 | static HRESULT OnExecuteMsuPackage( | ||
2390 | __in HANDLE hPipe, | ||
2391 | __in BURN_PACKAGES* pPackages, | ||
2392 | __in BURN_VARIABLES* pVariables, | ||
2393 | __in BYTE* pbData, | ||
2394 | __in DWORD cbData | ||
2395 | ) | ||
2396 | { | ||
2397 | HRESULT hr = S_OK; | ||
2398 | SIZE_T iData = 0; | ||
2399 | LPWSTR sczPackage = NULL; | ||
2400 | DWORD dwRollback = 0; | ||
2401 | DWORD dwStopWusaService = 0; | ||
2402 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2403 | BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
2404 | |||
2405 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; | ||
2406 | |||
2407 | // Deserialize message data. | ||
2408 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2409 | ExitOnFailure(hr, "Failed to read MSU package id."); | ||
2410 | |||
2411 | hr = BuffReadString(pbData, cbData, &iData, &executeAction.msuPackage.sczLogPath); | ||
2412 | ExitOnFailure(hr, "Failed to read package log."); | ||
2413 | |||
2414 | hr = BuffReadNumber(pbData, cbData, &iData, reinterpret_cast<DWORD*>(&executeAction.msuPackage.action)); | ||
2415 | ExitOnFailure(hr, "Failed to read action."); | ||
2416 | |||
2417 | hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); | ||
2418 | ExitOnFailure(hr, "Failed to read rollback."); | ||
2419 | |||
2420 | hr = BuffReadNumber(pbData, cbData, &iData, &dwStopWusaService); | ||
2421 | ExitOnFailure(hr, "Failed to read StopWusaService."); | ||
2422 | |||
2423 | hr = PackageFindById(pPackages, sczPackage, &executeAction.msuPackage.pPackage); | ||
2424 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2425 | |||
2426 | // execute MSU package | ||
2427 | hr = MsuEngineExecutePackage(&executeAction, pVariables, static_cast<BOOL>(dwRollback), static_cast<BOOL>(dwStopWusaService), GenericExecuteMessageHandler, hPipe, &restart); | ||
2428 | ExitOnFailure(hr, "Failed to execute MSU package."); | ||
2429 | |||
2430 | LExit: | ||
2431 | ReleaseStr(sczPackage); | ||
2432 | PlanUninitializeExecuteAction(&executeAction); | ||
2433 | |||
2434 | if (SUCCEEDED(hr)) | ||
2435 | { | ||
2436 | if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == restart) | ||
2437 | { | ||
2438 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); | ||
2439 | } | ||
2440 | else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart) | ||
2441 | { | ||
2442 | hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED); | ||
2443 | } | ||
2444 | } | ||
2445 | |||
2446 | return hr; | ||
2447 | } | ||
2448 | |||
2449 | static HRESULT OnExecutePackageProviderAction( | ||
2450 | __in BURN_PACKAGES* pPackages, | ||
2451 | __in BURN_RELATED_BUNDLES* pRelatedBundles, | ||
2452 | __in BYTE* pbData, | ||
2453 | __in DWORD cbData | ||
2454 | ) | ||
2455 | { | ||
2456 | HRESULT hr = S_OK; | ||
2457 | SIZE_T iData = 0; | ||
2458 | LPWSTR sczPackage = NULL; | ||
2459 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2460 | |||
2461 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER; | ||
2462 | |||
2463 | // Deserialize the message data. | ||
2464 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2465 | ExitOnFailure(hr, "Failed to read package id from message buffer."); | ||
2466 | |||
2467 | hr = BuffReadNumber(pbData, cbData, &iData, reinterpret_cast<DWORD*>(&executeAction.packageProvider.action)); | ||
2468 | ExitOnFailure(hr, "Failed to read action."); | ||
2469 | |||
2470 | // Find the package again. | ||
2471 | hr = PackageFindById(pPackages, sczPackage, &executeAction.packageProvider.pPackage); | ||
2472 | if (E_NOTFOUND == hr) | ||
2473 | { | ||
2474 | hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.packageProvider.pPackage); | ||
2475 | } | ||
2476 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2477 | |||
2478 | // Execute the package provider action. | ||
2479 | hr = DependencyExecutePackageProviderAction(&executeAction); | ||
2480 | ExitOnFailure(hr, "Failed to execute package provider action."); | ||
2481 | |||
2482 | LExit: | ||
2483 | ReleaseStr(sczPackage); | ||
2484 | PlanUninitializeExecuteAction(&executeAction); | ||
2485 | |||
2486 | return hr; | ||
2487 | } | ||
2488 | |||
2489 | static HRESULT OnExecutePackageDependencyAction( | ||
2490 | __in BURN_PACKAGES* pPackages, | ||
2491 | __in BURN_RELATED_BUNDLES* pRelatedBundles, | ||
2492 | __in BYTE* pbData, | ||
2493 | __in DWORD cbData | ||
2494 | ) | ||
2495 | { | ||
2496 | HRESULT hr = S_OK; | ||
2497 | SIZE_T iData = 0; | ||
2498 | LPWSTR sczPackage = NULL; | ||
2499 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2500 | |||
2501 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY; | ||
2502 | |||
2503 | // Deserialize the message data. | ||
2504 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2505 | ExitOnFailure(hr, "Failed to read package id from message buffer."); | ||
2506 | |||
2507 | hr = BuffReadString(pbData, cbData, &iData, &executeAction.packageDependency.sczBundleProviderKey); | ||
2508 | ExitOnFailure(hr, "Failed to read bundle dependency key from message buffer."); | ||
2509 | |||
2510 | hr = BuffReadNumber(pbData, cbData, &iData, reinterpret_cast<DWORD*>(&executeAction.packageDependency.action)); | ||
2511 | ExitOnFailure(hr, "Failed to read action."); | ||
2512 | |||
2513 | // Find the package again. | ||
2514 | hr = PackageFindById(pPackages, sczPackage, &executeAction.packageDependency.pPackage); | ||
2515 | if (E_NOTFOUND == hr) | ||
2516 | { | ||
2517 | hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.packageDependency.pPackage); | ||
2518 | } | ||
2519 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2520 | |||
2521 | // Execute the package dependency action. | ||
2522 | hr = DependencyExecutePackageDependencyAction(TRUE, &executeAction); | ||
2523 | ExitOnFailure(hr, "Failed to execute package dependency action."); | ||
2524 | |||
2525 | LExit: | ||
2526 | ReleaseStr(sczPackage); | ||
2527 | PlanUninitializeExecuteAction(&executeAction); | ||
2528 | |||
2529 | return hr; | ||
2530 | } | ||
2531 | |||
2532 | static HRESULT OnLoadCompatiblePackage( | ||
2533 | __in BURN_PACKAGES* pPackages, | ||
2534 | __in BYTE* pbData, | ||
2535 | __in DWORD cbData | ||
2536 | ) | ||
2537 | { | ||
2538 | HRESULT hr = S_OK; | ||
2539 | SIZE_T iData = 0; | ||
2540 | LPWSTR sczPackage = NULL; | ||
2541 | BURN_EXECUTE_ACTION executeAction = { }; | ||
2542 | |||
2543 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_COMPATIBLE_PACKAGE; | ||
2544 | |||
2545 | // Deserialize the message data. | ||
2546 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2547 | ExitOnFailure(hr, "Failed to read package id from message buffer."); | ||
2548 | |||
2549 | // Find the reference package. | ||
2550 | hr = PackageFindById(pPackages, sczPackage, &executeAction.compatiblePackage.pReferencePackage); | ||
2551 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2552 | |||
2553 | hr = BuffReadString(pbData, cbData, &iData, &executeAction.compatiblePackage.sczInstalledProductCode); | ||
2554 | ExitOnFailure(hr, "Failed to read installed ProductCode from message buffer."); | ||
2555 | |||
2556 | hr = BuffReadNumber64(pbData, cbData, &iData, &executeAction.compatiblePackage.qwInstalledVersion); | ||
2557 | ExitOnFailure(hr, "Failed to read installed version from message buffer."); | ||
2558 | |||
2559 | // Copy the installed data to the reference package. | ||
2560 | hr = StrAllocString(&executeAction.compatiblePackage.pReferencePackage->Msi.sczInstalledProductCode, executeAction.compatiblePackage.sczInstalledProductCode, 0); | ||
2561 | ExitOnFailure(hr, "Failed to copy installed ProductCode."); | ||
2562 | |||
2563 | executeAction.compatiblePackage.pReferencePackage->Msi.qwInstalledVersion = executeAction.compatiblePackage.qwInstalledVersion; | ||
2564 | |||
2565 | // Load the compatible package and add it to the list. | ||
2566 | hr = MsiEngineAddCompatiblePackage(pPackages, executeAction.compatiblePackage.pReferencePackage, NULL); | ||
2567 | ExitOnFailure(hr, "Failed to load compatible package."); | ||
2568 | |||
2569 | LExit: | ||
2570 | ReleaseStr(sczPackage); | ||
2571 | PlanUninitializeExecuteAction(&executeAction); | ||
2572 | |||
2573 | return hr; | ||
2574 | } | ||
2575 | |||
2576 | static int GenericExecuteMessageHandler( | ||
2577 | __in GENERIC_EXECUTE_MESSAGE* pMessage, | ||
2578 | __in LPVOID pvContext | ||
2579 | ) | ||
2580 | { | ||
2581 | HRESULT hr = S_OK; | ||
2582 | int nResult = IDOK; | ||
2583 | HANDLE hPipe = (HANDLE)pvContext; | ||
2584 | BYTE* pbData = NULL; | ||
2585 | SIZE_T cbData = 0; | ||
2586 | DWORD dwMessage = 0; | ||
2587 | |||
2588 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwAllowedResults); | ||
2589 | ExitOnFailure(hr, "Failed to write UI flags."); | ||
2590 | |||
2591 | switch(pMessage->type) | ||
2592 | { | ||
2593 | case GENERIC_EXECUTE_MESSAGE_PROGRESS: | ||
2594 | // serialize message data | ||
2595 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->progress.dwPercentage); | ||
2596 | ExitOnFailure(hr, "Failed to write progress percentage to message buffer."); | ||
2597 | |||
2598 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS; | ||
2599 | break; | ||
2600 | |||
2601 | case GENERIC_EXECUTE_MESSAGE_ERROR: | ||
2602 | // serialize message data | ||
2603 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); | ||
2604 | ExitOnFailure(hr, "Failed to write error code to message buffer."); | ||
2605 | |||
2606 | hr = BuffWriteString(&pbData, &cbData, pMessage->error.wzMessage); | ||
2607 | ExitOnFailure(hr, "Failed to write message to message buffer."); | ||
2608 | |||
2609 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR; | ||
2610 | break; | ||
2611 | |||
2612 | case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE: | ||
2613 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->filesInUse.cFiles); | ||
2614 | ExitOnFailure(hr, "Failed to count of files in use to message buffer."); | ||
2615 | |||
2616 | for (DWORD i = 0; i < pMessage->filesInUse.cFiles; ++i) | ||
2617 | { | ||
2618 | hr = BuffWriteString(&pbData, &cbData, pMessage->filesInUse.rgwzFiles[i]); | ||
2619 | ExitOnFailure(hr, "Failed to write file in use to message buffer."); | ||
2620 | } | ||
2621 | |||
2622 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE; | ||
2623 | break; | ||
2624 | } | ||
2625 | |||
2626 | // send message | ||
2627 | hr = PipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, reinterpret_cast<DWORD*>(&nResult)); | ||
2628 | ExitOnFailure(hr, "Failed to send message to per-user process."); | ||
2629 | |||
2630 | LExit: | ||
2631 | ReleaseBuffer(pbData); | ||
2632 | |||
2633 | return nResult; | ||
2634 | } | ||
2635 | |||
2636 | static int MsiExecuteMessageHandler( | ||
2637 | __in WIU_MSI_EXECUTE_MESSAGE* pMessage, | ||
2638 | __in_opt LPVOID pvContext | ||
2639 | ) | ||
2640 | { | ||
2641 | HRESULT hr = S_OK; | ||
2642 | int nResult = IDOK; | ||
2643 | HANDLE hPipe = (HANDLE)pvContext; | ||
2644 | BYTE* pbData = NULL; | ||
2645 | SIZE_T cbData = 0; | ||
2646 | DWORD dwMessage = 0; | ||
2647 | |||
2648 | // Always send any extra data via the struct first. | ||
2649 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->cData); | ||
2650 | ExitOnFailure(hr, "Failed to write MSI data count to message buffer."); | ||
2651 | |||
2652 | for (DWORD i = 0; i < pMessage->cData; ++i) | ||
2653 | { | ||
2654 | hr = BuffWriteString(&pbData, &cbData, pMessage->rgwzData[i]); | ||
2655 | ExitOnFailure(hr, "Failed to write MSI data to message buffer."); | ||
2656 | } | ||
2657 | |||
2658 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwAllowedResults); | ||
2659 | ExitOnFailure(hr, "Failed to write UI flags."); | ||
2660 | |||
2661 | switch (pMessage->type) | ||
2662 | { | ||
2663 | case WIU_MSI_EXECUTE_MESSAGE_PROGRESS: | ||
2664 | // serialize message data | ||
2665 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->progress.dwPercentage); | ||
2666 | ExitOnFailure(hr, "Failed to write progress percentage to message buffer."); | ||
2667 | |||
2668 | // set message id | ||
2669 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS; | ||
2670 | break; | ||
2671 | |||
2672 | case WIU_MSI_EXECUTE_MESSAGE_ERROR: | ||
2673 | // serialize message data | ||
2674 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); | ||
2675 | ExitOnFailure(hr, "Failed to write error code to message buffer."); | ||
2676 | |||
2677 | hr = BuffWriteString(&pbData, &cbData, pMessage->error.wzMessage); | ||
2678 | ExitOnFailure(hr, "Failed to write message to message buffer."); | ||
2679 | |||
2680 | // set message id | ||
2681 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR; | ||
2682 | break; | ||
2683 | |||
2684 | case WIU_MSI_EXECUTE_MESSAGE_MSI_MESSAGE: | ||
2685 | // serialize message data | ||
2686 | hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pMessage->msiMessage.mt); | ||
2687 | ExitOnFailure(hr, "Failed to write MSI message type to message buffer."); | ||
2688 | |||
2689 | hr = BuffWriteString(&pbData, &cbData, pMessage->msiMessage.wzMessage); | ||
2690 | ExitOnFailure(hr, "Failed to write message to message buffer."); | ||
2691 | |||
2692 | // set message id | ||
2693 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE; | ||
2694 | break; | ||
2695 | |||
2696 | case WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE: | ||
2697 | // NOTE: we do not serialize other message data here because all the "files in use" are in the data above. | ||
2698 | |||
2699 | // set message id | ||
2700 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE; | ||
2701 | break; | ||
2702 | |||
2703 | default: | ||
2704 | hr = E_UNEXPECTED; | ||
2705 | ExitOnFailure(hr, "Invalid message type: %d", pMessage->type); | ||
2706 | } | ||
2707 | |||
2708 | // send message | ||
2709 | hr = PipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, (DWORD*)&nResult); | ||
2710 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
2711 | |||
2712 | LExit: | ||
2713 | ReleaseBuffer(pbData); | ||
2714 | |||
2715 | return nResult; | ||
2716 | } | ||
2717 | |||
2718 | static HRESULT OnCleanPackage( | ||
2719 | __in BURN_PACKAGES* pPackages, | ||
2720 | __in BYTE* pbData, | ||
2721 | __in DWORD cbData | ||
2722 | ) | ||
2723 | { | ||
2724 | HRESULT hr = S_OK; | ||
2725 | SIZE_T iData = 0; | ||
2726 | LPWSTR sczPackage = NULL; | ||
2727 | BURN_PACKAGE* pPackage = NULL; | ||
2728 | |||
2729 | // Deserialize message data. | ||
2730 | hr = BuffReadString(pbData, cbData, &iData, &sczPackage); | ||
2731 | ExitOnFailure(hr, "Failed to read package id."); | ||
2732 | |||
2733 | hr = PackageFindById(pPackages, sczPackage, &pPackage); | ||
2734 | ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); | ||
2735 | |||
2736 | // Remove the package from the cache. | ||
2737 | hr = CacheRemovePackage(TRUE, pPackage->sczId, pPackage->sczCacheId); | ||
2738 | ExitOnFailure(hr, "Failed to remove from cache package: %ls", pPackage->sczId); | ||
2739 | |||
2740 | LExit: | ||
2741 | ReleaseStr(sczPackage); | ||
2742 | return hr; | ||
2743 | } | ||
2744 | |||
2745 | static HRESULT OnLaunchApprovedExe( | ||
2746 | __in HANDLE hPipe, | ||
2747 | __in BURN_APPROVED_EXES* pApprovedExes, | ||
2748 | __in BURN_VARIABLES* pVariables, | ||
2749 | __in BYTE* pbData, | ||
2750 | __in DWORD cbData | ||
2751 | ) | ||
2752 | { | ||
2753 | HRESULT hr = S_OK; | ||
2754 | SIZE_T iData = 0; | ||
2755 | BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = NULL; | ||
2756 | BURN_APPROVED_EXE* pApprovedExe = NULL; | ||
2757 | REGSAM samDesired = KEY_QUERY_VALUE; | ||
2758 | HKEY hKey = NULL; | ||
2759 | DWORD dwProcessId = 0; | ||
2760 | BYTE* pbSendData = NULL; | ||
2761 | SIZE_T cbSendData = 0; | ||
2762 | DWORD dwResult = 0; | ||
2763 | |||
2764 | pLaunchApprovedExe = (BURN_LAUNCH_APPROVED_EXE*)MemAlloc(sizeof(BURN_LAUNCH_APPROVED_EXE), TRUE); | ||
2765 | |||
2766 | // Deserialize message data. | ||
2767 | hr = BuffReadString(pbData, cbData, &iData, &pLaunchApprovedExe->sczId); | ||
2768 | ExitOnFailure(hr, "Failed to read approved exe id."); | ||
2769 | |||
2770 | hr = BuffReadString(pbData, cbData, &iData, &pLaunchApprovedExe->sczArguments); | ||
2771 | ExitOnFailure(hr, "Failed to read approved exe arguments."); | ||
2772 | |||
2773 | hr = BuffReadNumber(pbData, cbData, &iData, &pLaunchApprovedExe->dwWaitForInputIdleTimeout); | ||
2774 | ExitOnFailure(hr, "Failed to read approved exe WaitForInputIdle timeout."); | ||
2775 | |||
2776 | hr = ApprovedExesFindById(pApprovedExes, pLaunchApprovedExe->sczId, &pApprovedExe); | ||
2777 | ExitOnFailure(hr, "The per-user process requested unknown approved exe with id: %ls", pLaunchApprovedExe->sczId); | ||
2778 | |||
2779 | LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_SEARCH, pApprovedExe->sczKey, pApprovedExe->sczValueName ? pApprovedExe->sczValueName : L"", pApprovedExe->fWin64 ? L"yes" : L"no"); | ||
2780 | |||
2781 | if (pApprovedExe->fWin64) | ||
2782 | { | ||
2783 | samDesired |= KEY_WOW64_64KEY; | ||
2784 | } | ||
2785 | |||
2786 | hr = RegOpen(HKEY_LOCAL_MACHINE, pApprovedExe->sczKey, samDesired, &hKey); | ||
2787 | ExitOnFailure(hr, "Failed to open the registry key for the approved exe path."); | ||
2788 | |||
2789 | hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); | ||
2790 | ExitOnFailure(hr, "Failed to read the value for the approved exe path."); | ||
2791 | |||
2792 | hr = ApprovedExesVerifySecureLocation(pVariables, pLaunchApprovedExe); | ||
2793 | ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); | ||
2794 | if (S_FALSE == hr) | ||
2795 | { | ||
2796 | LogStringLine(REPORT_STANDARD, "The executable path is not in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); | ||
2797 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)); | ||
2798 | } | ||
2799 | |||
2800 | hr = ApprovedExesLaunch(pVariables, pLaunchApprovedExe, &dwProcessId); | ||
2801 | ExitOnFailure(hr, "Failed to launch approved exe: %ls", pLaunchApprovedExe->sczExecutablePath); | ||
2802 | |||
2803 | //send process id over pipe | ||
2804 | hr = BuffWriteNumber(&pbSendData, &cbSendData, dwProcessId); | ||
2805 | ExitOnFailure(hr, "Failed to write the approved exe process id to message buffer."); | ||
2806 | |||
2807 | hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, pbSendData, cbSendData, NULL, NULL, &dwResult); | ||
2808 | ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID message to per-user process."); | ||
2809 | |||
2810 | LExit: | ||
2811 | ReleaseBuffer(pbSendData); | ||
2812 | ApprovedExesUninitializeLaunch(pLaunchApprovedExe); | ||
2813 | return hr; | ||
2814 | } | ||