@joebigelow / wix / commits / 1f531430

Don't assume Exe packages with Burn protocol are bundles.

Related to #3693

Sean Hall committed Jan 3, 2022 at 15:35 UTC 1f5314302b3c8bc1977aed79df1d05c52608f382
19 files changed +1018 -410
src/burn/engine/apply.cpp
+94
@@ -201,6 +201,15 @@ static HRESULT DoRollbackActions(
201 __in DWORD dwCheckpoint,
202 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
203 );
204 +static HRESULT ExecuteRelatedBundle(
205 + __in BURN_ENGINE_STATE* pEngineState,
206 + __in BURN_EXECUTE_ACTION* pExecuteAction,
207 + __in BURN_EXECUTE_CONTEXT* pContext,
208 + __in BOOL fRollback,
209 + __out BOOL* pfRetry,
210 + __out BOOL* pfSuspend,
211 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
212 + );
213 static HRESULT ExecuteExePackage(
214 __in BURN_ENGINE_STATE* pEngineState,
215 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -686,6 +695,9 @@ extern "C" HRESULT ApplyExecute(
695 LPCWSTR wzId = NULL;
696 switch (pExecuteAction->type)
697 {
698 + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
699 + wzId = pExecuteAction->relatedBundle.pRelatedBundle->package.sczId;
700 + break;
701 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
702 wzId = pExecuteAction->exePackage.pPackage->sczId;
703 break;
@@ -2285,6 +2297,11 @@ static HRESULT DoExecuteAction(
2297 }
2298 break;
2299
2300 + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2301 + hr = ExecuteRelatedBundle(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2302 + ExitOnFailure(hr, "Failed to execute related bundle.");
2303 + break;
2304 +
2305 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2306 hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2307 ExitOnFailure(hr, "Failed to execute EXE package.");
@@ -2399,6 +2416,11 @@ static HRESULT DoRollbackActions(
2416 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
2417 break;
2418
2419 + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2420 + hr = ExecuteRelatedBundle(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2421 + ExitOnFailure(hr, "Failed to execute related bundle.");
2422 + break;
2423 +
2424 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2425 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2426 IgnoreRollbackError(hr, "Failed to rollback EXE package.");
@@ -2462,6 +2484,78 @@ LExit:
2484 return hr;
2485 }
2486
2487 +static HRESULT ExecuteRelatedBundle(
2488 + __in BURN_ENGINE_STATE* pEngineState,
2489 + __in BURN_EXECUTE_ACTION* pExecuteAction,
2490 + __in BURN_EXECUTE_CONTEXT* pContext,
2491 + __in BOOL fRollback,
2492 + __out BOOL* pfRetry,
2493 + __out BOOL* pfSuspend,
2494 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
2495 + )
2496 +{
2497 + HRESULT hr = S_OK;
2498 + HRESULT hrExecute = S_OK;
2499 + GENERIC_EXECUTE_MESSAGE message = { };
2500 + int nResult = 0;
2501 + BOOL fBeginCalled = FALSE;
2502 + BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
2503 + BURN_PACKAGE* pPackage = &pRelatedBundle->package;
2504 +
2505 + if (FAILED(pPackage->hrCacheResult))
2506 + {
2507 + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2508 + ExitFunction1(hr = S_OK);
2509 + }
2510 +
2511 + Assert(pContext->fRollback == fRollback);
2512 + pContext->pExecutingPackage = pPackage;
2513 + fBeginCalled = TRUE;
2514 +
2515 + // Send package execute begin to BA.
2516 + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->relatedBundle.action, INSTALLUILEVEL_NOCHANGE, FALSE);
2517 + ExitOnRootFailure(hr, "BA aborted execute related bundle begin.");
2518 +
2519 + message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
2520 + message.dwUIHint = MB_OKCANCEL;
2521 + message.progress.dwPercentage = fRollback ? 100 : 0;
2522 + nResult = GenericExecuteMessageHandler(&message, pContext);
2523 + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult);
2524 + ExitOnRootFailure(hr, "BA aborted related bundle progress.");
2525 +
2526 + // Execute package.
2527 + if (pPackage->fPerMachine)
2528 + {
2529 + hrExecute = ElevationExecuteRelatedBundle(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
2530 + ExitOnFailure(hrExecute, "Failed to configure per-machine related bundle.");
2531 + }
2532 + else
2533 + {
2534 + hrExecute = BundlePackageEngineExecuteRelatedBundle(pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
2535 + ExitOnFailure(hrExecute, "Failed to configure per-user related bundle.");
2536 + }
2537 +
2538 + message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
2539 + message.dwUIHint = MB_OKCANCEL;
2540 + message.progress.dwPercentage = fRollback ? 0 : 100;
2541 + nResult = GenericExecuteMessageHandler(&message, pContext);
2542 + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult);
2543 + ExitOnRootFailure(hr, "BA aborted related bundle progress.");
2544 +
2545 + pContext->cExecutedPackages += fRollback ? -1 : 1;
2546 +
2547 + hr = ReportOverallProgressTicks(&pEngineState->userExperience, fRollback, pEngineState->plan.cOverallProgressTicksTotal, pContext->pApplyContext);
2548 + ExitOnRootFailure(hr, "BA aborted related bundle execute progress.");
2549 +
2550 +LExit:
2551 + if (fBeginCalled)
2552 + {
2553 + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2554 + }
2555 +
2556 + return hr;
2557 +}
2558 +
2559 static HRESULT ExecuteExePackage(
2560 __in BURN_ENGINE_STATE* pEngineState,
2561 __in BURN_EXECUTE_ACTION* pExecuteAction,
src/burn/engine/bundlepackageengine.cpp new
+460
@@ -0,0 +1,460 @@
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 +
7 +// function definitions
8 +
9 +extern "C" void BundlePackageEnginePackageUninitialize(
10 + __in BURN_PACKAGE* pPackage
11 + )
12 +{
13 + ReleaseStr(pPackage->Bundle.sczInstallArguments);
14 + ReleaseStr(pPackage->Bundle.sczRepairArguments);
15 + ReleaseStr(pPackage->Bundle.sczUninstallArguments);
16 + ReleaseStr(pPackage->Bundle.sczIgnoreDependencies);
17 + ReleaseMem(pPackage->Bundle.rgExitCodes);
18 +
19 + // free command-line arguments
20 + if (pPackage->Bundle.rgCommandLineArguments)
21 + {
22 + for (DWORD i = 0; i < pPackage->Bundle.cCommandLineArguments; ++i)
23 + {
24 + ExeEngineCommandLineArgumentUninitialize(pPackage->Bundle.rgCommandLineArguments + i);
25 + }
26 + MemFree(pPackage->Bundle.rgCommandLineArguments);
27 + }
28 +
29 + // clear struct
30 + memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle));
31 +}
32 +
33 +//
34 +// PlanCalculate - calculates the execute and rollback state for the requested package state.
35 +//
36 +extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
37 + __in BURN_PACKAGE* pPackage
38 + )
39 +{
40 + HRESULT hr = S_OK;
41 + BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
42 + BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
43 +
44 + // execute action
45 + switch (pPackage->currentState)
46 + {
47 + case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
48 + switch (pPackage->requested)
49 + {
50 + case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
51 + execute = pPackage->Bundle.fPseudoBundle ? BOOTSTRAPPER_ACTION_STATE_INSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
52 + break;
53 + case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
54 + execute = pPackage->Bundle.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE;
55 + break;
56 + case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough;
57 + case BOOTSTRAPPER_REQUEST_STATE_CACHE:
58 + execute = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
59 + break;
60 + case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
61 + execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
62 + break;
63 + default:
64 + execute = BOOTSTRAPPER_ACTION_STATE_NONE;
65 + break;
66 + }
67 + break;
68 +
69 + case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
70 + switch (pPackage->requested)
71 + {
72 + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
73 + case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
74 + execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
75 + break;
76 + default:
77 + execute = BOOTSTRAPPER_ACTION_STATE_NONE;
78 + break;
79 + }
80 + break;
81 +
82 + default:
83 + hr = E_INVALIDARG;
84 + ExitOnRootFailure(hr, "Invalid package current state: %d.", pPackage->currentState);
85 + }
86 +
87 + // Calculate the rollback action if there is an execute action.
88 + if (BOOTSTRAPPER_ACTION_STATE_NONE != execute)
89 + {
90 + switch (pPackage->currentState)
91 + {
92 + case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
93 + switch (pPackage->requested)
94 + {
95 + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
96 + case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
97 + rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
98 + break;
99 + case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
100 + case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
101 + rollback = BOOTSTRAPPER_ACTION_STATE_INSTALL;
102 + break;
103 + default:
104 + rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
105 + break;
106 + }
107 + break;
108 +
109 + case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
110 + switch (pPackage->requested)
111 + {
112 + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
113 + case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
114 + rollback = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
115 + break;
116 + case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
117 + case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
118 + rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
119 + break;
120 + default:
121 + rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
122 + break;
123 + }
124 + break;
125 +
126 + default:
127 + hr = E_INVALIDARG;
128 + ExitOnRootFailure(hr, "Invalid package expected state.");
129 + }
130 + }
131 +
132 + // return values
133 + pPackage->execute = execute;
134 + pPackage->rollback = rollback;
135 +
136 +LExit:
137 + return hr;
138 +}
139 +
140 +//
141 +// PlanAdd - adds the calculated execute and rollback actions for the package.
142 +//
143 +extern "C" HRESULT BundlePackageEnginePlanAddRelatedBundle(
144 + __in_opt DWORD *pdwInsertSequence,
145 + __in BURN_RELATED_BUNDLE* pRelatedBundle,
146 + __in BURN_PLAN* pPlan,
147 + __in BURN_LOGGING* pLog,
148 + __in BURN_VARIABLES* pVariables
149 + )
150 +{
151 + HRESULT hr = S_OK;
152 + BURN_EXECUTE_ACTION* pAction = NULL;
153 + BURN_PACKAGE* pPackage = &pRelatedBundle->package;
154 +
155 + hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
156 + ExitOnFailure(hr, "Failed to plan package dependency actions.");
157 +
158 + // add execute action
159 + if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
160 + {
161 + if (pdwInsertSequence)
162 + {
163 + hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction);
164 + ExitOnFailure(hr, "Failed to insert execute action.");
165 + }
166 + else
167 + {
168 + hr = PlanAppendExecuteAction(pPlan, &pAction);
169 + ExitOnFailure(hr, "Failed to append execute action.");
170 + }
171 +
172 + pAction->type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
173 + pAction->relatedBundle.pRelatedBundle = pRelatedBundle;
174 + pAction->relatedBundle.action = pPackage->execute;
175 +
176 + if (pPackage->Bundle.sczIgnoreDependencies)
177 + {
178 + hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pPackage->Bundle.sczIgnoreDependencies, 0);
179 + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
180 + }
181 +
182 + if (pPackage->Bundle.wzAncestors)
183 + {
184 + hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pPackage->Bundle.wzAncestors, 0);
185 + ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
186 + }
187 +
188 + if (pPackage->Bundle.wzEngineWorkingDirectory)
189 + {
190 + hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0);
191 + ExitOnFailure(hr, "Failed to allocate the custom working directory.");
192 + }
193 +
194 + LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
195 + }
196 +
197 + // add rollback action
198 + if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
199 + {
200 + hr = PlanAppendRollbackAction(pPlan, &pAction);
201 + ExitOnFailure(hr, "Failed to append rollback action.");
202 +
203 + pAction->type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
204 + pAction->relatedBundle.pRelatedBundle = pRelatedBundle;
205 + pAction->relatedBundle.action = pPackage->rollback;
206 +
207 + if (pPackage->Bundle.sczIgnoreDependencies)
208 + {
209 + hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pPackage->Bundle.sczIgnoreDependencies, 0);
210 + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
211 + }
212 +
213 + if (pPackage->Bundle.wzAncestors)
214 + {
215 + hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pPackage->Bundle.wzAncestors, 0);
216 + ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
217 + }
218 +
219 + if (pPackage->Bundle.wzEngineWorkingDirectory)
220 + {
221 + hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0);
222 + ExitOnFailure(hr, "Failed to allocate the custom working directory.");
223 + }
224 +
225 + LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
226 + }
227 +
228 +LExit:
229 + return hr;
230 +}
231 +
232 +extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
233 + __in BURN_EXECUTE_ACTION* pExecuteAction,
234 + __in BURN_CACHE* pCache,
235 + __in BURN_VARIABLES* pVariables,
236 + __in BOOL fRollback,
237 + __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
238 + __in LPVOID pvContext,
239 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
240 + )
241 +{
242 + HRESULT hr = S_OK;
243 + int nResult = IDNOACTION;
244 + LPCWSTR wzArguments = NULL;
245 + LPWSTR sczArguments = NULL;
246 + LPWSTR sczArgumentsFormatted = NULL;
247 + LPWSTR sczArgumentsObfuscated = NULL;
248 + LPWSTR sczCachedDirectory = NULL;
249 + LPWSTR sczExecutablePath = NULL;
250 + LPWSTR sczCommand = NULL;
251 + LPWSTR sczCommandObfuscated = NULL;
252 + HANDLE hExecutableFile = INVALID_HANDLE_VALUE;
253 + STARTUPINFOW si = { };
254 + PROCESS_INFORMATION pi = { };
255 + DWORD dwExitCode = 0;
256 + GENERIC_EXECUTE_MESSAGE message = { };
257 + BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action;
258 + BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
259 + BOOTSTRAPPER_RELATION_TYPE relationType = pRelatedBundle->relationType;
260 + BURN_PACKAGE* pPackage = &pRelatedBundle->package;
261 + BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
262 + LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
263 + LPCWSTR wzOperationCommandLine = NULL;
264 + BOOL fRunEmbedded = pPackage->Bundle.fSupportsBurnProtocol;
265 +
266 + // get cached executable path
267 + hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
268 + ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
269 +
270 + // Best effort to set the execute package cache folder and action variables.
271 + VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
272 + VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, action, TRUE);
273 +
274 + hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
275 + ExitOnFailure(hr, "Failed to build executable path.");
276 +
277 + // pick arguments
278 + switch (action)
279 + {
280 + case BOOTSTRAPPER_ACTION_STATE_INSTALL:
281 + wzArguments = pPackage->Bundle.sczInstallArguments;
282 + break;
283 +
284 + case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
285 + wzOperationCommandLine = L"-uninstall";
286 + wzArguments = pPackage->Bundle.sczUninstallArguments;
287 + break;
288 +
289 + case BOOTSTRAPPER_ACTION_STATE_REPAIR:
290 + wzOperationCommandLine = L"-repair";
291 + wzArguments = pPackage->Bundle.sczRepairArguments;
292 + break;
293 +
294 + default:
295 + hr = E_INVALIDARG;
296 + ExitOnFailure(hr, "Invalid Bundle package action: %d.", action);
297 + }
298 +
299 + // now add optional arguments
300 + if (wzArguments && *wzArguments)
301 + {
302 + hr = StrAllocString(&sczArguments, wzArguments, 0);
303 + ExitOnFailure(hr, "Failed to copy package arguments.");
304 + }
305 +
306 + for (DWORD i = 0; i < pPackage->Bundle.cCommandLineArguments; ++i)
307 + {
308 + BURN_EXE_COMMAND_LINE_ARGUMENT* commandLineArgument = &pPackage->Bundle.rgCommandLineArguments[i];
309 + BOOL fCondition = FALSE;
310 +
311 + hr = ConditionEvaluate(pVariables, commandLineArgument->sczCondition, &fCondition);
312 + ExitOnFailure(hr, "Failed to evaluate bundle package command-line condition.");
313 +
314 + if (fCondition)
315 + {
316 + if (sczArguments)
317 + {
318 + hr = StrAllocConcat(&sczArguments, L" ", 0);
319 + ExitOnFailure(hr, "Failed to separate command-line arguments.");
320 + }
321 +
322 + switch (action)
323 + {
324 + case BOOTSTRAPPER_ACTION_STATE_INSTALL:
325 + hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0);
326 + ExitOnFailure(hr, "Failed to get command-line argument for install.");
327 + break;
328 +
329 + case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
330 + hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0);
331 + ExitOnFailure(hr, "Failed to get command-line argument for uninstall.");
332 + break;
333 +
334 + case BOOTSTRAPPER_ACTION_STATE_REPAIR:
335 + hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0);
336 + ExitOnFailure(hr, "Failed to get command-line argument for repair.");
337 + break;
338 +
339 + default:
340 + hr = E_INVALIDARG;
341 + ExitOnFailure(hr, "Invalid Bundle package action: %d.", action);
342 + }
343 + }
344 + }
345 +
346 + // build command
347 + AppAppendCommandLineArgument(&sczCommand, sczExecutablePath);
348 + ExitOnFailure(hr, "Failed to create executable command.");
349 +
350 + if (!fRunEmbedded)
351 + {
352 + hr = StrAllocConcat(&sczCommand, L" -quiet", 0);
353 + ExitOnFailure(hr, "Failed to append quiet argument.");
354 + }
355 +
356 + if (wzOperationCommandLine)
357 + {
358 + hr = StrAllocConcatFormatted(&sczCommand, L" %ls", wzOperationCommandLine);
359 + ExitOnFailure(hr, "Failed to append operation argument.");
360 + }
361 +
362 + if (wzRelationTypeCommandLine)
363 + {
364 + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls", wzRelationTypeCommandLine);
365 + ExitOnFailure(hr, "Failed to append relation type argument.");
366 + }
367 +
368 + // Add the list of dependencies to ignore, if any, to the burn command line.
369 + if (pExecuteAction->relatedBundle.sczIgnoreDependencies)
370 + {
371 + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies);
372 + ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
373 + }
374 +
375 + // Add the list of ancestors, if any, to the burn command line.
376 + if (pExecuteAction->relatedBundle.sczAncestors)
377 + {
378 + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors);
379 + ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
380 + }
381 +
382 + hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczCommand, NULL);
383 + ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line.");
384 +
385 + hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL);
386 + ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
387 +
388 + // Always add user supplied arguments last.
389 + if (sczArguments && *sczArguments)
390 + {
391 + hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
392 + ExitOnFailure(hr, "Failed to format argument string.");
393 +
394 + hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
395 + ExitOnFailure(hr, "Failed to format obfuscated argument string.");
396 +
397 + hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated);
398 + ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments.");
399 +
400 + hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
401 + ExitOnFailure(hr, "Failed to copy formatted arguments.");
402 + }
403 +
404 + // Log before we add the secret pipe name and client token for embedded processes.
405 + LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated);
406 +
407 + if (fRunEmbedded)
408 + {
409 + hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
410 + ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
411 + }
412 + else // create and wait for the executable process while sending fake progress to allow cancel.
413 + {
414 + // Make the cache location of the executable the current directory to help those executables
415 + // that expect stuff to be relative to them.
416 + si.cb = sizeof(si);
417 + if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, sczCachedDirectory, &si, &pi))
418 + {
419 + ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
420 + }
421 +
422 + do
423 + {
424 + message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
425 + message.dwUIHint = MB_OKCANCEL;
426 + message.progress.dwPercentage = 50;
427 + nResult = pfnGenericMessageHandler(&message, pvContext);
428 + hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
429 + ExitOnRootFailure(hr, "Bootstrapper application aborted during BUNDLE progress.");
430 +
431 + hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode);
432 + if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
433 + {
434 + ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath);
435 + }
436 + } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
437 + }
438 +
439 + hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, dwExitCode, pRestart);
440 + ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
441 +
442 +LExit:
443 + StrSecureZeroFreeString(sczArguments);
444 + StrSecureZeroFreeString(sczArgumentsFormatted);
445 + ReleaseStr(sczArgumentsObfuscated);
446 + ReleaseStr(sczCachedDirectory);
447 + ReleaseStr(sczExecutablePath);
448 + StrSecureZeroFreeString(sczCommand);
449 + ReleaseStr(sczCommandObfuscated);
450 +
451 + ReleaseHandle(pi.hThread);
452 + ReleaseHandle(pi.hProcess);
453 + ReleaseFileHandle(hExecutableFile);
454 +
455 + // Best effort to clear the execute package cache folder and action variables.
456 + VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, NULL, TRUE, FALSE);
457 + VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, NULL, TRUE, FALSE);
458 +
459 + return hr;
460 +}
src/burn/engine/bundlepackageengine.h new
+38
@@ -0,0 +1,38 @@
1 +#pragma once
2 +// 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.
3 +
4 +
5 +#if defined(__cplusplus)
6 +extern "C" {
7 +#endif
8 +
9 +
10 +// function declarations
11 +
12 +void BundlePackageEnginePackageUninitialize(
13 + __in BURN_PACKAGE* pPackage
14 + );
15 +HRESULT BundlePackageEnginePlanCalculatePackage(
16 + __in BURN_PACKAGE* pPackage
17 + );
18 +HRESULT BundlePackageEnginePlanAddRelatedBundle(
19 + __in_opt DWORD *pdwInsertSequence,
20 + __in BURN_RELATED_BUNDLE* pRelatedBundle,
21 + __in BURN_PLAN* pPlan,
22 + __in BURN_LOGGING* pLog,
23 + __in BURN_VARIABLES* pVariables
24 + );
25 +HRESULT BundlePackageEngineExecuteRelatedBundle(
26 + __in BURN_EXECUTE_ACTION* pExecuteAction,
27 + __in BURN_CACHE* pCache,
28 + __in BURN_VARIABLES* pVariables,
29 + __in BOOL fRollback,
30 + __in PFN_GENERICMESSAGEHANDLER pfnGenericExecuteProgress,
31 + __in LPVOID pvContext,
32 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
33 + );
34 +
35 +
36 +#if defined(__cplusplus)
37 +}
38 +#endif
src/burn/engine/core.cpp
+7 -7
@@ -228,11 +228,11 @@ extern "C" HRESULT CoreInitializeConstants(
228 {
229 BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
230
231 - if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) // TODO: Don't assume exePackages with burn protocol are bundles.
231 + if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type)
232 {
233 // Pass along any ancestors and ourself to prevent infinite loops.
234 - pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors;
235 - pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
234 + pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
235 + pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
236 }
237 }
238
@@ -518,7 +518,7 @@ extern "C" HRESULT CorePlan(
518 ExitOnFailure(hr, "Failed to plan the layout of the bundle.");
519
520 // Plan the packages' layout.
521 - hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
521 + hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
522 ExitOnFailure(hr, "Failed to plan packages.");
523 }
524 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action)
@@ -527,7 +527,7 @@ extern "C" HRESULT CorePlan(
527
528 pUpgradeBundlePackage = &pEngineState->update.package;
529
530 - hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
530 + hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
531 ExitOnFailure(hr, "Failed to plan update.");
532 }
533 else
@@ -541,7 +541,7 @@ extern "C" HRESULT CorePlan(
541
542 pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle;
543
544 - hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
544 + hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
545 ExitOnFailure(hr, "Failed to plan passthrough.");
546 }
547 else // doing an action that modifies the machine state.
@@ -562,7 +562,7 @@ extern "C" HRESULT CorePlan(
562 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
563 ExitOnFailure(hr, "Failed to plan related bundles.");
564
565 - hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
565 + hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
566 ExitOnFailure(hr, "Failed to plan packages.");
567
568 // Schedule the update of related bundles last.
src/burn/engine/elevation.cpp
+139 -27
@@ -19,6 +19,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
19 BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD,
20 BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP,
21 BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION,
22 + BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE,
23 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE,
24 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE,
25 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE,
@@ -230,11 +231,18 @@ static HRESULT OnProcessDependentRegistration(
231 __in BYTE* pbData,
232 __in SIZE_T cbData
233 );
234 +static HRESULT OnExecuteRelatedBundle(
235 + __in HANDLE hPipe,
236 + __in BURN_CACHE* pCache,
237 + __in BURN_RELATED_BUNDLES* pRelatedBundles,
238 + __in BURN_VARIABLES* pVariables,
239 + __in BYTE* pbData,
240 + __in SIZE_T cbData
241 + );
242 static HRESULT OnExecuteExePackage(
243 __in HANDLE hPipe,
244 __in BURN_CACHE* pCache,
245 __in BURN_PACKAGES* pPackages,
237 - __in BURN_RELATED_BUNDLES* pRelatedBundles,
246 __in BURN_VARIABLES* pVariables,
247 __in BYTE* pbData,
248 __in SIZE_T cbData
@@ -818,10 +826,10 @@ LExit:
826 }
827
828 /*******************************************************************
821 - ElevationExecuteExePackage -
829 + ElevationExecuteRelatedBundle -
830
831 *******************************************************************/
824 -extern "C" HRESULT ElevationExecuteExePackage(
832 +extern "C" HRESULT ElevationExecuteRelatedBundle(
833 __in HANDLE hPipe,
834 __in BURN_EXECUTE_ACTION* pExecuteAction,
835 __in BURN_VARIABLES* pVariables,
@@ -838,22 +846,22 @@ extern "C" HRESULT ElevationExecuteExePackage(
846 DWORD dwResult = 0;
847
848 // serialize message data
841 - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId);
849 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.pRelatedBundle->package.sczId);
850 ExitOnFailure(hr, "Failed to write package id to message buffer.");
851
844 - hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action);
852 + hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action);
853 ExitOnFailure(hr, "Failed to write action to message buffer.");
854
855 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
856 ExitOnFailure(hr, "Failed to write rollback.");
857
850 - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies);
858 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczIgnoreDependencies);
859 ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
860
853 - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors);
861 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczAncestors);
862 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
863
856 - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory);
864 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
865 ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer.");
866
867 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
@@ -863,6 +871,54 @@ extern "C" HRESULT ElevationExecuteExePackage(
871 context.pfnGenericMessageHandler = pfnGenericMessageHandler;
872 context.pvContext = pvContext;
873
874 + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
875 + ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE message to per-machine process.");
876 +
877 + hr = ProcessResult(dwResult, pRestart);
878 +
879 +LExit:
880 + ReleaseBuffer(pbData);
881 +
882 + return hr;
883 +}
884 +
885 +/*******************************************************************
886 + ElevationExecuteExePackage -
887 +
888 +*******************************************************************/
889 +extern "C" HRESULT ElevationExecuteExePackage(
890 + __in HANDLE hPipe,
891 + __in BURN_EXECUTE_ACTION* pExecuteAction,
892 + __in BURN_VARIABLES* pVariables,
893 + __in BOOL fRollback,
894 + __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
895 + __in LPVOID pvContext,
896 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
897 + )
898 +{
899 + HRESULT hr = S_OK;
900 + BYTE* pbData = NULL;
901 + SIZE_T cbData = 0;
902 + BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT context = { };
903 + DWORD dwResult = 0;
904 +
905 + // serialize message data
906 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId);
907 + ExitOnFailure(hr, "Failed to write package id to message buffer.");
908 +
909 + hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action);
910 + ExitOnFailure(hr, "Failed to write action to message buffer.");
911 +
912 + hr = BuffWriteNumber(&pbData, &cbData, fRollback);
913 + ExitOnFailure(hr, "Failed to write rollback.");
914 +
915 + hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
916 + ExitOnFailure(hr, "Failed to write variables.");
917 +
918 + // send message
919 + context.pfnGenericMessageHandler = pfnGenericMessageHandler;
920 + context.pvContext = pvContext;
921 +
922 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
923 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process.");
924
@@ -1911,8 +1967,12 @@ static HRESULT ProcessElevatedChildMessage(
1967 hrResult = OnProcessDependentRegistration(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData);
1968 break;
1969
1970 + case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE:
1971 + hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
1972 + break;
1973 +
1974 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE:
1915 - hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
1975 + hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
1976 break;
1977
1978 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE:
@@ -2473,10 +2533,9 @@ LExit:
2533 return hr;
2534 }
2535
2476 -static HRESULT OnExecuteExePackage(
2536 +static HRESULT OnExecuteRelatedBundle(
2537 __in HANDLE hPipe,
2538 __in BURN_CACHE* pCache,
2479 - __in BURN_PACKAGES* pPackages,
2539 __in BURN_RELATED_BUNDLES* pRelatedBundles,
2540 __in BURN_VARIABLES* pVariables,
2541 __in BYTE* pbData,
@@ -2491,15 +2550,15 @@ static HRESULT OnExecuteExePackage(
2550 LPWSTR sczIgnoreDependencies = NULL;
2551 LPWSTR sczAncestors = NULL;
2552 LPWSTR sczEngineWorkingDirectory = NULL;
2494 - BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2553 + BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2554
2496 - executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
2555 + executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
2556
2557 // Deserialize message data.
2558 hr = BuffReadString(pbData, cbData, &iData, &sczPackage);
2500 - ExitOnFailure(hr, "Failed to read EXE package id.");
2559 + ExitOnFailure(hr, "Failed to read related bundle id.");
2560
2502 - hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action);
2561 + hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action);
2562 ExitOnFailure(hr, "Failed to read action.");
2563
2564 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
@@ -2517,36 +2576,32 @@ static HRESULT OnExecuteExePackage(
2576 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2577 ExitOnFailure(hr, "Failed to read variables.");
2578
2520 - hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage);
2521 - if (E_NOTFOUND == hr)
2522 - {
2523 - hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.exePackage.pPackage);
2524 - }
2525 - ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2579 + hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle);
2580 + ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage);
2581
2582 // Pass the list of dependencies to ignore, if any, to the related bundle.
2583 if (sczIgnoreDependencies && *sczIgnoreDependencies)
2584 {
2530 - hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2585 + hr = StrAllocString(&executeAction.relatedBundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2586 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
2587 }
2588
2589 // Pass the list of ancestors, if any, to the related bundle.
2590 if (sczAncestors && *sczAncestors)
2591 {
2537 - hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0);
2592 + hr = StrAllocString(&executeAction.relatedBundle.sczAncestors, sczAncestors, 0);
2593 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2594 }
2595
2596 if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory)
2597 {
2543 - hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2598 + hr = StrAllocString(&executeAction.relatedBundle.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2599 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
2600 }
2601
2547 - // Execute EXE package.
2548 - hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
2549 - ExitOnFailure(hr, "Failed to execute EXE package.");
2602 + // Execute related bundle.
2603 + hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &bundleRestart);
2604 + ExitOnFailure(hr, "Failed to execute related bundle.");
2605
2606 LExit:
2607 ReleaseStr(sczEngineWorkingDirectory);
@@ -2555,6 +2610,63 @@ LExit:
2610 ReleaseStr(sczPackage);
2611 PlanUninitializeExecuteAction(&executeAction);
2612
2613 + if (SUCCEEDED(hr))
2614 + {
2615 + if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == bundleRestart)
2616 + {
2617 + hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
2618 + }
2619 + else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == bundleRestart)
2620 + {
2621 + hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
2622 + }
2623 + }
2624 +
2625 + return hr;
2626 +}
2627 +
2628 +static HRESULT OnExecuteExePackage(
2629 + __in HANDLE hPipe,
2630 + __in BURN_CACHE* pCache,
2631 + __in BURN_PACKAGES* pPackages,
2632 + __in BURN_VARIABLES* pVariables,
2633 + __in BYTE* pbData,
2634 + __in SIZE_T cbData
2635 + )
2636 +{
2637 + HRESULT hr = S_OK;
2638 + SIZE_T iData = 0;
2639 + LPWSTR sczPackage = NULL;
2640 + DWORD dwRollback = 0;
2641 + BURN_EXECUTE_ACTION executeAction = { };
2642 + BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2643 +
2644 + executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
2645 +
2646 + // Deserialize message data.
2647 + hr = BuffReadString(pbData, cbData, &iData, &sczPackage);
2648 + ExitOnFailure(hr, "Failed to read EXE package id.");
2649 +
2650 + hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action);
2651 + ExitOnFailure(hr, "Failed to read action.");
2652 +
2653 + hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
2654 + ExitOnFailure(hr, "Failed to read rollback.");
2655 +
2656 + hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2657 + ExitOnFailure(hr, "Failed to read variables.");
2658 +
2659 + hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage);
2660 + ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2661 +
2662 + // Execute EXE package.
2663 + hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
2664 + ExitOnFailure(hr, "Failed to execute EXE package.");
2665 +
2666 +LExit:
2667 + ReleaseStr(sczPackage);
2668 + PlanUninitializeExecuteAction(&executeAction);
2669 +
2670 if (SUCCEEDED(hr))
2671 {
2672 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart)
src/burn/engine/elevation.h
+9
@@ -80,6 +80,15 @@ HRESULT ElevationProcessDependentRegistration(
80 __in HANDLE hPipe,
81 __in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction
82 );
83 +HRESULT ElevationExecuteRelatedBundle(
84 + __in HANDLE hPipe,
85 + __in BURN_EXECUTE_ACTION* pExecuteAction,
86 + __in BURN_VARIABLES* pVariables,
87 + __in BOOL fRollback,
88 + __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
89 + __in LPVOID pvContext,
90 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
91 + );
92 HRESULT ElevationExecuteExePackage(
93 __in HANDLE hPipe,
94 __in BURN_EXECUTE_ACTION* pExecuteAction,
src/burn/engine/engine.vcxproj
+2
@@ -52,6 +52,7 @@
52 <ItemGroup>
53 <ClCompile Include="apply.cpp" />
54 <ClCompile Include="approvedexe.cpp" />
55 + <ClCompile Include="bundlepackageengine.cpp" />
56 <ClCompile Include="burnextension.cpp" />
57 <ClCompile Include="detect.cpp" />
58 <ClCompile Include="embedded.cpp" />
@@ -101,6 +102,7 @@
102 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" />
103 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtension.h" />
104 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtensionEngine.h" />
105 + <ClInclude Include="bundlepackageengine.h" />
106 <ClInclude Include="burnextension.h" />
107 <ClInclude Include="cabextract.h" />
108 <ClInclude Include="cache.h" />
src/burn/engine/exeengine.cpp
+46 -131
@@ -3,23 +3,6 @@
3 #include "precomp.h"
4
5
6 -// internal function declarations
7 -
8 -static HRESULT HandleExitCode(
9 - __in BURN_PACKAGE* pPackage,
10 - __in DWORD dwExitCode,
11 - __out BOOTSTRAPPER_APPLY_RESTART* pRestart
12 - );
13 -static HRESULT ParseCommandLineArgumentsFromXml(
14 - __in IXMLDOMNode* pixnExePackage,
15 - __in BURN_PACKAGE* pPackage
16 - );
17 -static HRESULT ParseExitCodesFromXml(
18 - __in IXMLDOMNode* pixnExePackage,
19 - __in BURN_PACKAGE* pPackage
20 - );
21 -
22 -
6 // function definitions
7
8 extern "C" HRESULT ExeEngineParsePackageFromXml(
@@ -82,10 +65,10 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
65 ExitOnFailure(hr, "Failed to get @Protocol.");
66 }
67
85 - hr = ParseExitCodesFromXml(pixnExePackage, pPackage);
68 + hr = ExeEngineParseExitCodesFromXml(pixnExePackage, &pPackage->Exe.rgExitCodes, &pPackage->Exe.cExitCodes);
69 ExitOnFailure(hr, "Failed to parse exit codes.");
70
88 - hr = ParseCommandLineArgumentsFromXml(pixnExePackage, pPackage);
71 + hr = ExeEngineParseCommandLineArgumentsFromXml(pixnExePackage, &pPackage->Exe.rgCommandLineArguments, &pPackage->Exe.cCommandLineArguments);
72 ExitOnFailure(hr, "Failed to parse command lines.");
73
74 LExit:
@@ -104,8 +87,6 @@ extern "C" void ExeEnginePackageUninitialize(
87 ReleaseStr(pPackage->Exe.sczInstallArguments);
88 ReleaseStr(pPackage->Exe.sczRepairArguments);
89 ReleaseStr(pPackage->Exe.sczUninstallArguments);
107 - ReleaseStr(pPackage->Exe.sczIgnoreDependencies);
108 - //ReleaseStr(pPackage->Exe.sczProgressSwitch);
90 ReleaseMem(pPackage->Exe.rgExitCodes);
91
92 // free command-line arguments
@@ -113,11 +94,7 @@ extern "C" void ExeEnginePackageUninitialize(
94 {
95 for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i)
96 {
116 - BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i];
117 - ReleaseStr(pCommandLineArgument->sczInstallArgument);
118 - ReleaseStr(pCommandLineArgument->sczUninstallArgument);
119 - ReleaseStr(pCommandLineArgument->sczRepairArgument);
120 - ReleaseStr(pCommandLineArgument->sczCondition);
97 + ExeEngineCommandLineArgumentUninitialize(pPackage->Exe.rgCommandLineArguments + i);
98 }
99 MemFree(pPackage->Exe.rgCommandLineArguments);
100 }
@@ -126,6 +103,16 @@ extern "C" void ExeEnginePackageUninitialize(
103 memset(&pPackage->Exe, 0, sizeof(pPackage->Exe));
104 }
105
106 +extern "C" void ExeEngineCommandLineArgumentUninitialize(
107 + __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument
108 + )
109 +{
110 + ReleaseStr(pCommandLineArgument->sczInstallArgument);
111 + ReleaseStr(pCommandLineArgument->sczUninstallArgument);
112 + ReleaseStr(pCommandLineArgument->sczRepairArgument);
113 + ReleaseStr(pCommandLineArgument->sczCondition);
114 +}
115 +
116 extern "C" HRESULT ExeEngineDetectPackage(
117 __in BURN_PACKAGE* pPackage,
118 __in BURN_VARIABLES* pVariables
@@ -264,7 +251,6 @@ LExit:
251 // PlanAdd - adds the calculated execute and rollback actions for the package.
252 //
253 extern "C" HRESULT ExeEnginePlanAddPackage(
267 - __in_opt DWORD *pdwInsertSequence,
254 __in BURN_PACKAGE* pPackage,
255 __in BURN_PLAN* pPlan,
256 __in BURN_LOGGING* pLog,
@@ -274,46 +260,19 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
260 HRESULT hr = S_OK;
261 BURN_EXECUTE_ACTION* pAction = NULL;
262
277 - hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
263 + hr = DependencyPlanPackage(NULL, pPackage, pPlan);
264 ExitOnFailure(hr, "Failed to plan package dependency actions.");
265
266 // add execute action
267 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
268 {
283 - if (NULL != pdwInsertSequence)
284 - {
285 - hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction);
286 - ExitOnFailure(hr, "Failed to insert execute action.");
287 - }
288 - else
289 - {
290 - hr = PlanAppendExecuteAction(pPlan, &pAction);
291 - ExitOnFailure(hr, "Failed to append execute action.");
292 - }
269 + hr = PlanAppendExecuteAction(pPlan, &pAction);
270 + ExitOnFailure(hr, "Failed to append execute action.");
271
272 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
273 pAction->exePackage.pPackage = pPackage;
296 - pAction->exePackage.fFireAndForget = (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action);
274 pAction->exePackage.action = pPackage->execute;
275
299 - if (pPackage->Exe.sczIgnoreDependencies)
300 - {
301 - hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
302 - ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
303 - }
304 -
305 - if (pPackage->Exe.wzAncestors)
306 - {
307 - hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
308 - ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
309 - }
310 -
311 - if (pPackage->Exe.wzEngineWorkingDirectory)
312 - {
313 - hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0);
314 - ExitOnFailure(hr, "Failed to allocate the custom working directory.");
315 - }
316 -
276 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
277 }
278
@@ -327,18 +286,6 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
286 pAction->exePackage.pPackage = pPackage;
287 pAction->exePackage.action = pPackage->rollback;
288
330 - if (pPackage->Exe.sczIgnoreDependencies)
331 - {
332 - hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
333 - ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
334 - }
335 -
336 - if (pPackage->Exe.wzAncestors)
337 - {
338 - hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
339 - ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
340 - }
341 -
289 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
290 }
291
@@ -452,13 +399,13 @@ extern "C" HRESULT ExeEngineExecutePackage(
399 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
400 ExitOnFailure(hr, "Failed to format argument string.");
401
455 - hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %s", sczExecutablePath, sczArgumentsFormatted);
402 + hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsFormatted);
403 ExitOnFailure(hr, "Failed to create executable command.");
404
405 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
406 ExitOnFailure(hr, "Failed to format obfuscated argument string.");
407
461 - hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", sczExecutablePath, sczArgumentsObfuscated);
408 + hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsObfuscated);
409 }
410 else
411 {
@@ -469,47 +416,15 @@ extern "C" HRESULT ExeEngineExecutePackage(
416 }
417 ExitOnFailure(hr, "Failed to create obfuscated executable command.");
418
472 - if (pPackage->Exe.fSupportsAncestors)
473 - {
474 - // Add the list of dependencies to ignore, if any, to the burn command line.
475 - if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
476 - {
477 - hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
478 - ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
479 -
480 - hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
481 - ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the obfuscated command line.");
482 - }
483 -
484 - // Add the list of ancestors, if any, to the burn command line.
485 - if (pExecuteAction->exePackage.sczAncestors)
486 - {
487 - hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
488 - ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
489 -
490 - hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
491 - ExitOnFailure(hr, "Failed to append the list of ancestors to the obfuscated command line.");
492 - }
493 - }
494 -
495 - if (BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
496 - {
497 - hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, &sczCommandObfuscated);
498 - ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line.");
499 -
500 - hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated);
501 - ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
502 - }
503 -
419 // Log before we add the secret pipe name and client token for embedded processes.
420 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
421
507 - if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
422 + if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
423 {
424 hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
510 - ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
425 + ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath);
426 }
512 - else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
427 + else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
428 {
429 hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
430 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
@@ -524,7 +439,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
439 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
440 }
441
527 - if (pExecuteAction->exePackage.fFireAndForget)
442 + if (pPackage->Exe.fFireAndForget)
443 {
444 ::WaitForInputIdle(pi.hProcess, 5000);
445 ExitFunction();
@@ -547,7 +462,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
462 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
463 }
464
550 - hr = HandleExitCode(pPackage, dwExitCode, pRestart);
465 + hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart);
466 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
467
468 LExit:
@@ -595,12 +510,10 @@ LExit:
510 return;
511 }
512
598 -
599 -// internal helper functions
600 -
601 -static HRESULT ParseExitCodesFromXml(
602 - __in IXMLDOMNode* pixnExePackage,
603 - __in BURN_PACKAGE* pPackage
513 +extern "C" HRESULT ExeEngineParseExitCodesFromXml(
514 + __in IXMLDOMNode* pixnPackage,
515 + __inout BURN_EXE_EXIT_CODE** prgExitCodes,
516 + __inout DWORD* pcExitCodes
517 )
518 {
519 HRESULT hr = S_OK;
@@ -610,7 +523,7 @@ static HRESULT ParseExitCodesFromXml(
523 LPWSTR scz = NULL;
524
525 // select exit code nodes
613 - hr = XmlSelectNodes(pixnExePackage, L"ExitCode", &pixnNodes);
526 + hr = XmlSelectNodes(pixnPackage, L"ExitCode", &pixnNodes);
527 ExitOnFailure(hr, "Failed to select exit code nodes.");
528
529 // get exit code node count
@@ -620,15 +533,15 @@ static HRESULT ParseExitCodesFromXml(
533 if (cNodes)
534 {
535 // allocate memory for exit codes
623 - pPackage->Exe.rgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE);
624 - ExitOnNull(pPackage->Exe.rgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs.");
536 + *prgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE);
537 + ExitOnNull(*prgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs.");
538
626 - pPackage->Exe.cExitCodes = cNodes;
539 + *pcExitCodes = cNodes;
540
541 // parse package elements
542 for (DWORD i = 0; i < cNodes; ++i)
543 {
631 - BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i];
544 + BURN_EXE_EXIT_CODE* pExitCode = *prgExitCodes + i;
545
546 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
547 ExitOnFailure(hr, "Failed to get next node.");
@@ -666,9 +579,10 @@ LExit:
579 return hr;
580 }
581
669 -static HRESULT ParseCommandLineArgumentsFromXml(
670 - __in IXMLDOMNode* pixnExePackage,
671 - __in BURN_PACKAGE* pPackage
582 +extern "C" HRESULT ExeEngineParseCommandLineArgumentsFromXml(
583 + __in IXMLDOMNode* pixnPackage,
584 + __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments,
585 + __inout DWORD* pcCommandLineArguments
586 )
587 {
588 HRESULT hr = S_OK;
@@ -678,7 +592,7 @@ static HRESULT ParseCommandLineArgumentsFromXml(
592 LPWSTR scz = NULL;
593
594 // Select command-line argument nodes.
681 - hr = XmlSelectNodes(pixnExePackage, L"CommandLine", &pixnNodes);
595 + hr = XmlSelectNodes(pixnPackage, L"CommandLine", &pixnNodes);
596 ExitOnFailure(hr, "Failed to select command-line argument nodes.");
597
598 // Get command-line argument node count.
@@ -687,15 +601,15 @@ static HRESULT ParseCommandLineArgumentsFromXml(
601
602 if (cNodes)
603 {
690 - pPackage->Exe.rgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE);
691 - ExitOnNull(pPackage->Exe.rgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs.");
604 + *prgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE);
605 + ExitOnNull(*prgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs.");
606
693 - pPackage->Exe.cCommandLineArguments = cNodes;
607 + *pcCommandLineArguments = cNodes;
608
609 // Parse command-line argument elements.
610 for (DWORD i = 0; i < cNodes; ++i)
611 {
698 - BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i];
612 + BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = *prgCommandLineArguments + i;
613
614 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
615 ExitOnFailure(hr, "Failed to get next command-line argument node.");
@@ -731,8 +645,9 @@ LExit:
645 return hr;
646 }
647
734 -static HRESULT HandleExitCode(
735 - __in BURN_PACKAGE* pPackage,
648 +extern "C" HRESULT ExeEngineHandleExitCode(
649 + __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
650 + __in DWORD cCustomExitCodes,
651 __in DWORD dwExitCode,
652 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
653 )
@@ -740,9 +655,9 @@ static HRESULT HandleExitCode(
655 HRESULT hr = S_OK;
656 BURN_EXE_EXIT_CODE_TYPE typeCode = BURN_EXE_EXIT_CODE_TYPE_NONE;
657
743 - for (DWORD i = 0; i < pPackage->Exe.cExitCodes; ++i)
658 + for (DWORD i = 0; i < cCustomExitCodes; ++i)
659 {
745 - BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i];
660 + BURN_EXE_EXIT_CODE* pExitCode = rgCustomExitCodes + i;
661
662 // If this is a wildcard, use the last one we come across.
663 if (pExitCode->fWildcard)
src/burn/engine/exeengine.h
+19 -1
@@ -16,6 +16,9 @@ HRESULT ExeEngineParsePackageFromXml(
16 void ExeEnginePackageUninitialize(
17 __in BURN_PACKAGE* pPackage
18 );
19 +void ExeEngineCommandLineArgumentUninitialize(
20 + __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument
21 + );
22 HRESULT ExeEngineDetectPackage(
23 __in BURN_PACKAGE* pPackage,
24 __in BURN_VARIABLES* pVariables
@@ -24,7 +27,6 @@ HRESULT ExeEnginePlanCalculatePackage(
27 __in BURN_PACKAGE* pPackage
28 );
29 HRESULT ExeEnginePlanAddPackage(
27 - __in_opt DWORD *pdwInsertSequence,
30 __in BURN_PACKAGE* pPackage,
31 __in BURN_PLAN* pPlan,
32 __in BURN_LOGGING* pLog,
@@ -43,6 +45,22 @@ void ExeEngineUpdateInstallRegistrationState(
45 __in BURN_EXECUTE_ACTION* pAction,
46 __in HRESULT hrExecute
47 );
48 +HRESULT ExeEngineParseExitCodesFromXml(
49 + __in IXMLDOMNode* pixnPackage,
50 + __inout BURN_EXE_EXIT_CODE** prgExitCodes,
51 + __inout DWORD* pcExitCodes
52 + );
53 +HRESULT ExeEngineParseCommandLineArgumentsFromXml(
54 + __in IXMLDOMNode* pixnPackage,
55 + __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments,
56 + __inout DWORD* pcCommandLineArguments
57 + );
58 +HRESULT ExeEngineHandleExitCode(
59 + __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
60 + __in DWORD cCustomExitCodes,
61 + __in DWORD dwExitCode,
62 + __out BOOTSTRAPPER_APPLY_RESTART* pRestart
63 + );
64
65
66 #if defined(__cplusplus)
src/burn/engine/package.cpp
+7 -15
@@ -350,6 +350,9 @@ extern "C" void PackageUninitialize(
350
351 switch (pPackage->type)
352 {
353 + case BURN_PACKAGE_TYPE_BUNDLE:
354 + BundlePackageEnginePackageUninitialize(pPackage);
355 + break;
356 case BURN_PACKAGE_TYPE_EXE:
357 ExeEnginePackageUninitialize(pPackage); // TODO: Modularization
358 break;
@@ -439,22 +442,11 @@ extern "C" HRESULT PackageFindRelatedById(
442 )
443 {
444 HRESULT hr = S_OK;
442 - BURN_PACKAGE* pPackage = NULL;
443 -
444 - for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i)
445 - {
446 - pPackage = &pRelatedBundles->rgRelatedBundles[i].package;
447 -
448 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1))
449 - {
450 - *ppPackage = pPackage;
451 - ExitFunction1(hr = S_OK);
452 - }
453 - }
445 + BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
446 +
447 + hr = RelatedBundleFindById(pRelatedBundles, wzId, &pRelatedBundle);
448 + *ppPackage = FAILED(hr) ? NULL : &pRelatedBundle->package;
449
455 - hr = E_NOTFOUND;
456 -
457 -LExit:
450 return hr;
451 }
452
src/burn/engine/package.h
+19 -3
@@ -35,6 +35,7 @@ enum BURN_EXE_PROTOCOL_TYPE
35 enum BURN_PACKAGE_TYPE
36 {
37 BURN_PACKAGE_TYPE_NONE,
38 + BURN_PACKAGE_TYPE_BUNDLE,
39 BURN_PACKAGE_TYPE_EXE,
40 BURN_PACKAGE_TYPE_MSI,
41 BURN_PACKAGE_TYPE_MSP,
@@ -263,21 +264,36 @@ typedef struct _BURN_PACKAGE
264 {
265 struct
266 {
266 - LPWSTR sczDetectCondition;
267 LPWSTR sczInstallArguments;
268 LPWSTR sczRepairArguments;
269 LPWSTR sczUninstallArguments;
270 +
271 LPWSTR sczIgnoreDependencies;
272 LPCWSTR wzAncestors; // points directly into engine state.
273 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
274
275 BOOL fPseudoBundle;
276 + BOOL fRepairable;
277 + BOOL fSupportsBurnProtocol;
278
279 + BURN_EXE_EXIT_CODE* rgExitCodes;
280 + DWORD cExitCodes;
281 +
282 + BURN_EXE_COMMAND_LINE_ARGUMENT* rgCommandLineArguments;
283 + DWORD cCommandLineArguments;
284 + } Bundle;
285 + struct
286 + {
287 + LPWSTR sczDetectCondition;
288 + LPWSTR sczInstallArguments;
289 + LPWSTR sczRepairArguments;
290 + LPWSTR sczUninstallArguments;
291 +
292 + BOOL fPseudoBundle;
293 + BOOL fFireAndForget;
294 BOOL fRepairable;
295 BURN_EXE_PROTOCOL_TYPE protocol;
296
279 - BOOL fSupportsAncestors;
280 -
297 BURN_EXE_EXIT_CODE* rgExitCodes;
298 DWORD cExitCodes;
299
src/burn/engine/plan.cpp
+67 -61
@@ -36,16 +36,13 @@ static HRESULT PlanPackagesHelper(
36 __in BURN_USER_EXPERIENCE* pUX,
37 __in BURN_PLAN* pPlan,
38 __in BURN_LOGGING* pLog,
39 - __in BURN_VARIABLES* pVariables,
40 - __in BOOTSTRAPPER_DISPLAY display,
41 - __in BOOTSTRAPPER_RELATION_TYPE relationType
39 + __in BURN_VARIABLES* pVariables
40 );
41 static HRESULT InitializePackage(
42 __in BURN_PLAN* pPlan,
43 __in BURN_USER_EXPERIENCE* pUX,
44 __in BURN_VARIABLES* pVariables,
47 - __in BURN_PACKAGE* pPackage,
48 - __in BOOTSTRAPPER_RELATION_TYPE relationType
45 + __in BURN_PACKAGE* pPackage
46 );
47 static HRESULT ProcessPackage(
48 __in BOOL fBundlePerMachine,
@@ -54,7 +51,6 @@ static HRESULT ProcessPackage(
51 __in BURN_PACKAGE* pPackage,
52 __in BURN_LOGGING* pLog,
53 __in BURN_VARIABLES* pVariables,
57 - __in BOOTSTRAPPER_DISPLAY display,
54 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
55 );
56 static HRESULT ProcessPackageRollbackBoundary(
@@ -266,10 +262,10 @@ extern "C" void PlanUninitializeExecuteAction(
262 {
263 switch (pExecuteAction->type)
264 {
269 - case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
270 - ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies);
271 - ReleaseStr(pExecuteAction->exePackage.sczAncestors);
272 - ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory);
265 + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
266 + ReleaseStr(pExecuteAction->relatedBundle.sczIgnoreDependencies);
267 + ReleaseStr(pExecuteAction->relatedBundle.sczAncestors);
268 + ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
269 break;
270
271 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
@@ -500,14 +496,12 @@ extern "C" HRESULT PlanPackages(
496 __in BURN_PACKAGES* pPackages,
497 __in BURN_PLAN* pPlan,
498 __in BURN_LOGGING* pLog,
503 - __in BURN_VARIABLES* pVariables,
504 - __in BOOTSTRAPPER_DISPLAY display,
505 - __in BOOTSTRAPPER_RELATION_TYPE relationType
499 + __in BURN_VARIABLES* pVariables
500 )
501 {
502 HRESULT hr = S_OK;
503
510 - hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, pUX, pPlan, pLog, pVariables, display, relationType);
504 + hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, pUX, pPlan, pLog, pVariables);
505
506 return hr;
507 }
@@ -712,15 +706,13 @@ extern "C" HRESULT PlanPassThroughBundle(
706 __in BURN_PACKAGE* pPackage,
707 __in BURN_PLAN* pPlan,
708 __in BURN_LOGGING* pLog,
715 - __in BURN_VARIABLES* pVariables,
716 - __in BOOTSTRAPPER_DISPLAY display,
717 - __in BOOTSTRAPPER_RELATION_TYPE relationType
709 + __in BURN_VARIABLES* pVariables
710 )
711 {
712 HRESULT hr = S_OK;
713
714 // Plan passthrough package.
723 - hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType);
715 + hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables);
716 ExitOnFailure(hr, "Failed to process passthrough package.");
717
718 LExit:
@@ -732,15 +724,17 @@ extern "C" HRESULT PlanUpdateBundle(
724 __in BURN_PACKAGE* pPackage,
725 __in BURN_PLAN* pPlan,
726 __in BURN_LOGGING* pLog,
735 - __in BURN_VARIABLES* pVariables,
736 - __in BOOTSTRAPPER_DISPLAY display,
737 - __in BOOTSTRAPPER_RELATION_TYPE relationType
727 + __in BURN_VARIABLES* pVariables
728 )
729 {
730 HRESULT hr = S_OK;
731
732 + Assert(!pPackage->fPerMachine);
733 + Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type);
734 + pPackage->Exe.fFireAndForget = BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action;
735 +
736 // Plan update package.
743 - hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType);
737 + hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables);
738 ExitOnFailure(hr, "Failed to process update package.");
739
740 LExit:
@@ -753,9 +747,7 @@ static HRESULT PlanPackagesHelper(
747 __in BURN_USER_EXPERIENCE* pUX,
748 __in BURN_PLAN* pPlan,
749 __in BURN_LOGGING* pLog,
756 - __in BURN_VARIABLES* pVariables,
757 - __in BOOTSTRAPPER_DISPLAY display,
758 - __in BOOTSTRAPPER_RELATION_TYPE relationType
750 + __in BURN_VARIABLES* pVariables
751 )
752 {
753 HRESULT hr = S_OK;
@@ -768,7 +760,7 @@ static HRESULT PlanPackagesHelper(
760 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
761 BURN_PACKAGE* pPackage = rgPackages + iPackage;
762
771 - hr = InitializePackage(pPlan, pUX, pVariables, pPackage, relationType);
763 + hr = InitializePackage(pPlan, pUX, pVariables, pPackage);
764 ExitOnFailure(hr, "Failed to initialize package.");
765 }
766
@@ -791,7 +783,7 @@ static HRESULT PlanPackagesHelper(
783 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
784 BURN_PACKAGE* pPackage = rgPackages + iPackage;
785
794 - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &pRollbackBoundary);
786 + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary);
787 ExitOnFailure(hr, "Failed to process package.");
788 }
789
@@ -841,14 +833,24 @@ static HRESULT InitializePackage(
833 __in BURN_PLAN* pPlan,
834 __in BURN_USER_EXPERIENCE* pUX,
835 __in BURN_VARIABLES* pVariables,
844 - __in BURN_PACKAGE* pPackage,
845 - __in BOOTSTRAPPER_RELATION_TYPE relationType
836 + __in BURN_PACKAGE* pPackage
837 )
838 {
839 HRESULT hr = S_OK;
840 BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition = BOOTSTRAPPER_PACKAGE_CONDITION_DEFAULT;
841 BOOL fInstallCondition = FALSE;
842 BOOL fBeginCalled = FALSE;
843 + BOOTSTRAPPER_RELATION_TYPE relationType = pPlan->pCommand->relationType;
844 +
845 + if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fPseudoBundle)
846 + {
847 + // Exe pseudo bundles are not configurable.
848 + // The BA already requested this package to be executed
849 + // * by the overall plan action for UpdateReplace
850 + // * by enabling the forward compatible bundle for Passthrough
851 + pPackage->defaultRequested = pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
852 + ExitFunction();
853 + }
854
855 if (pPackage->fCanAffectRegistration)
856 {
@@ -896,7 +898,6 @@ static HRESULT ProcessPackage(
898 __in BURN_PACKAGE* pPackage,
899 __in BURN_LOGGING* pLog,
900 __in BURN_VARIABLES* pVariables,
899 - __in BOOTSTRAPPER_DISPLAY display,
901 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
902 )
903 {
@@ -920,7 +921,7 @@ static HRESULT ProcessPackage(
921 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
922 {
923 // If the package is in a requested state, plan it.
923 - hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables);
924 + hr = PlanExecutePackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables);
925 ExitOnFailure(hr, "Failed to plan execute package.");
926 }
927 else
@@ -1064,7 +1065,6 @@ LExit:
1065
1066 extern "C" HRESULT PlanExecutePackage(
1067 __in BOOL fPerMachine,
1067 - __in BOOTSTRAPPER_DISPLAY display,
1068 __in BURN_USER_EXPERIENCE* pUserExperience,
1069 __in BURN_PLAN* pPlan,
1070 __in BURN_PACKAGE* pPackage,
@@ -1073,6 +1073,7 @@ extern "C" HRESULT PlanExecutePackage(
1073 )
1074 {
1075 HRESULT hr = S_OK;
1076 + BOOTSTRAPPER_DISPLAY display = pPlan->pCommand->display;
1077 BOOL fRequestedCache = BOOTSTRAPPER_CACHE_TYPE_REMOVE < pPackage->cacheType && (BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested || ForceCache(pPlan, pPackage));
1078
1079 hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary);
@@ -1124,7 +1125,7 @@ extern "C" HRESULT PlanExecutePackage(
1125 switch (pPackage->type)
1126 {
1127 case BURN_PACKAGE_TYPE_EXE:
1127 - hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables);
1128 + hr = ExeEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables);
1129 break;
1130
1131 case BURN_PACKAGE_TYPE_MSI:
@@ -1288,8 +1289,8 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1289 }
1290
1291 // Pass along any ancestors and ourself to prevent infinite loops.
1291 - pRelatedBundle->package.Exe.wzAncestors = pRegistration->sczBundlePackageAncestors;
1292 - pRelatedBundle->package.Exe.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
1292 + pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
1293 + pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
1294
1295 hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested);
1296 ExitOnFailure(hr, "Failed to get default request state for related bundle.");
@@ -1349,37 +1350,38 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1350
1351 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1352 {
1352 - if (BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE == pPlan->rgExecuteActions[i].type && BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action)
1353 + switch (pPlan->rgExecuteActions[i].type)
1354 {
1354 - fExecutingAnyPackage = TRUE;
1355 -
1356 - BURN_PACKAGE* pPackage = pPlan->rgExecuteActions[i].packageProvider.pPackage;
1357 - if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
1355 + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
1356 + if (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].relatedBundle.action)
1357 {
1359 - if (0 < pPackage->cDependencyProviders)
1358 + fExecutingAnyPackage = TRUE;
1359 +
1360 + BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1361 + if (pPackage->cDependencyProviders)
1362 {
1363 // Bundles only support a single provider key.
1364 const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1365 DictAddKey(sdProviderKeys, pProvider->sczKey);
1366 }
1367 }
1366 - }
1367 - else
1368 - {
1369 - switch (pPlan->rgExecuteActions[i].type)
1370 - {
1371 - case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1372 - fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action);
1373 - break;
1368 + break;
1369
1375 - case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1376 - fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action);
1377 - break;
1370 + case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1371 + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action);
1372 + break;
1373
1379 - case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE:
1380 - fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action);
1381 - break;
1382 - }
1374 + case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1375 + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action);
1376 + break;
1377 +
1378 + case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1379 + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action);
1380 + break;
1381 +
1382 + case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE:
1383 + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action);
1384 + break;
1385 }
1386 }
1387
@@ -1422,7 +1424,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1424 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
1425 {
1426 // Addon and patch bundles will be passed a list of dependencies to ignore for planning.
1425 - hr = StrAllocString(&pRelatedBundle->package.Exe.sczIgnoreDependencies, sczIgnoreDependencies, 0);
1427 + hr = StrAllocString(&pRelatedBundle->package.Bundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
1428 ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore.");
1429
1430 // Uninstall addons and patches early in the chain, before other packages are uninstalled.
@@ -1434,8 +1436,8 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1436
1437 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested)
1438 {
1437 - hr = ExeEnginePlanCalculatePackage(&pRelatedBundle->package);
1438 - ExitOnFailure(hr, "Failed to calcuate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1439 + hr = BundlePackageEnginePlanCalculatePackage(&pRelatedBundle->package);
1440 + ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1441
1442 // Calculate package states based on reference count for addon and patch related bundles.
1443 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
@@ -1450,7 +1452,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1452 }
1453 }
1454
1453 - hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables);
1455 + hr = BundlePackageEnginePlanAddRelatedBundle(pdwInsertIndex, pRelatedBundle, pPlan, pLog, pVariables);
1456 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1457
1458 // Calculate package states based on reference count for addon and patch related bundles.
@@ -2603,8 +2605,12 @@ static void ExecuteActionLog(
2605 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE_DEPENDENCY package id: %ls, bundle provider key: %ls, action: %hs", wzBase, iAction, pAction->packageDependency.pPackage->sczId, pAction->packageDependency.sczBundleProviderKey, LoggingDependencyActionToString(pAction->packageDependency.action));
2606 break;
2607
2608 + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2609 + LogStringLine(PlanDumpLevel, "%ls action[%u]: RELATED_BUNDLE package id: %ls, action: %hs, ignore dependencies: %ls", wzBase, iAction, pAction->relatedBundle.pRelatedBundle->package.sczId, LoggingActionStateToString(pAction->relatedBundle.action), pAction->relatedBundle.sczIgnoreDependencies);
2610 + break;
2611 +
2612 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2607 - LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs, ignore dependencies: %ls", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action), pAction->exePackage.sczIgnoreDependencies);
2613 + LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action));
2614 break;
2615
2616 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
src/burn/engine/plan.h
+10 -12
@@ -50,6 +50,7 @@ enum BURN_EXECUTE_ACTION_TYPE
50 BURN_EXECUTE_ACTION_TYPE_CHECKPOINT,
51 BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE,
52 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE,
53 + BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE,
54 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE,
55 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE,
56 BURN_EXECUTE_ACTION_TYPE_MSP_TARGET,
@@ -160,12 +161,16 @@ typedef struct _BURN_EXECUTE_ACTION
161 } uncachePackage;
162 struct
163 {
163 - BURN_PACKAGE* pPackage;
164 - BOOL fFireAndForget;
164 + BURN_RELATED_BUNDLE* pRelatedBundle;
165 BOOTSTRAPPER_ACTION_STATE action;
166 LPWSTR sczIgnoreDependencies;
167 LPWSTR sczAncestors;
168 LPWSTR sczEngineWorkingDirectory;
169 + } relatedBundle;
170 + struct
171 + {
172 + BURN_PACKAGE* pPackage;
173 + BOOTSTRAPPER_ACTION_STATE action;
174 } exePackage;
175 struct
176 {
@@ -339,9 +344,7 @@ HRESULT PlanPackages(
344 __in BURN_PACKAGES* pPackages,
345 __in BURN_PLAN* pPlan,
346 __in BURN_LOGGING* pLog,
342 - __in BURN_VARIABLES* pVariables,
343 - __in BOOTSTRAPPER_DISPLAY display,
344 - __in BOOTSTRAPPER_RELATION_TYPE relationType
347 + __in BURN_VARIABLES* pVariables
348 );
349 HRESULT PlanRegistration(
350 __in BURN_PLAN* pPlan,
@@ -356,18 +359,14 @@ HRESULT PlanPassThroughBundle(
359 __in BURN_PACKAGE* pPackage,
360 __in BURN_PLAN* pPlan,
361 __in BURN_LOGGING* pLog,
359 - __in BURN_VARIABLES* pVariables,
360 - __in BOOTSTRAPPER_DISPLAY display,
361 - __in BOOTSTRAPPER_RELATION_TYPE relationType
362 + __in BURN_VARIABLES* pVariables
363 );
364 HRESULT PlanUpdateBundle(
365 __in BURN_USER_EXPERIENCE* pUX,
366 __in BURN_PACKAGE* pPackage,
367 __in BURN_PLAN* pPlan,
368 __in BURN_LOGGING* pLog,
368 - __in BURN_VARIABLES* pVariables,
369 - __in BOOTSTRAPPER_DISPLAY display,
370 - __in BOOTSTRAPPER_RELATION_TYPE relationType
369 + __in BURN_VARIABLES* pVariables
370 );
371 HRESULT PlanLayoutContainer(
372 __in BURN_PLAN* pPlan,
@@ -379,7 +378,6 @@ HRESULT PlanLayoutPackage(
378 );
379 HRESULT PlanExecutePackage(
380 __in BOOL fPerMachine,
382 - __in BOOTSTRAPPER_DISPLAY display,
381 __in BURN_USER_EXPERIENCE* pUserExperience,
382 __in BURN_PLAN* pPlan,
383 __in BURN_PACKAGE* pPackage,
src/burn/engine/precomp.h
+1
@@ -86,6 +86,7 @@
86 #include "dependency.h"
87 #include "core.h"
88 #include "apply.h"
89 +#include "bundlepackageengine.h"
90 #include "exeengine.h"
91 #include "msiengine.h"
92 #include "mspengine.h"
src/burn/engine/pseudobundle.cpp
+23 -130
@@ -3,36 +3,24 @@
3 #include "precomp.h"
4
5
6 -extern "C" HRESULT PseudoBundleInitialize(
6 +extern "C" HRESULT PseudoBundleInitializeRelated(
7 __in BURN_PACKAGE* pPackage,
8 __in BOOL fSupportsBurnProtocol,
9 __in BOOL fPerMachine,
10 __in_z LPCWSTR wzId,
11 +#ifdef DEBUG
12 __in BOOTSTRAPPER_RELATION_TYPE relationType,
12 - __in BOOTSTRAPPER_PACKAGE_STATE state,
13 +#endif
14 __in BOOL fCached,
15 __in_z LPCWSTR wzFilePath,
15 - __in_z LPCWSTR wzLocalSource,
16 - __in_z_opt LPCWSTR wzDownloadSource,
16 __in DWORD64 qwSize,
18 - __in BOOL fVital,
19 - __in_z_opt LPCWSTR wzInstallArguments,
20 - __in_z_opt LPCWSTR wzRepairArguments,
21 - __in_z_opt LPCWSTR wzUninstallArguments,
22 - __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider,
23 - __in_opt const BYTE* pbHash,
24 - __in const DWORD cbHash
17 + __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider
18 )
19 {
20 HRESULT hr = S_OK;
28 - LPWSTR sczRelationTypeCommandLineSwitch = NULL;
21 BURN_PAYLOAD* pPayload = NULL;
22
31 - LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
32 - if (wzRelationTypeCommandLine)
33 - {
34 - hr = StrAllocFormatted(&sczRelationTypeCommandLineSwitch, L" -%ls", wzRelationTypeCommandLine);
35 - }
23 + AssertSz(BOOTSTRAPPER_RELATION_UPDATE != relationType, "Update pseudo bundles must use PseudoBundleInitializeUpdateBundle instead.");
24
25 // Initialize the single payload, and fill out all the necessary fields
26 pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE);
@@ -51,41 +39,21 @@ extern "C" HRESULT PseudoBundleInitialize(
39 hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0);
40 ExitOnFailure(hr, "Failed to copy filename for pseudo bundle.");
41
54 - hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0);
42 + hr = StrAllocString(&pPayload->sczSourcePath, wzFilePath, 0);
43 ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle.");
44
57 - if (wzDownloadSource && *wzDownloadSource)
58 - {
59 - hr = StrAllocString(&pPayload->downloadSource.sczUrl, wzDownloadSource, 0);
60 - ExitOnFailure(hr, "Failed to copy download source for pseudo bundle.");
61 - }
62 -
63 - if (pbHash)
64 - {
65 - pPayload->pbHash = static_cast<BYTE*>(MemAlloc(cbHash, FALSE));
66 - ExitOnNull(pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for pseudo bundle payload hash.");
67 -
68 - pPayload->cbHash = cbHash;
69 - memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
70 - }
71 -
72 - if (BOOTSTRAPPER_RELATION_UPDATE == relationType)
73 - {
74 - pPayload->verification = BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE;
75 - }
76 -
77 - pPackage->Exe.fPseudoBundle = TRUE;
78 -
79 - pPackage->type = BURN_PACKAGE_TYPE_EXE;
45 + pPackage->type = BURN_PACKAGE_TYPE_BUNDLE;
46 pPackage->fPerMachine = fPerMachine;
81 - pPackage->currentState = state;
47 + pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
48 pPackage->fCached = fCached;
49 pPackage->qwInstallSize = qwSize;
50 pPackage->qwSize = qwSize;
85 - pPackage->fVital = fVital;
51 + pPackage->fVital = FALSE;
52
87 - pPackage->Exe.protocol = fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
88 - pPackage->Exe.fSupportsAncestors = TRUE;
53 + pPackage->fUninstallable = TRUE;
54 + pPackage->Bundle.fPseudoBundle = TRUE;
55 + pPackage->Bundle.fRepairable = TRUE;
56 + pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol;
57
58 hr = StrAllocString(&pPackage->sczId, wzId, 0);
59 ExitOnFailure(hr, "Failed to copy key for pseudo bundle.");
@@ -93,47 +61,6 @@ extern "C" HRESULT PseudoBundleInitialize(
61 hr = StrAllocString(&pPackage->sczCacheId, wzId, 0);
62 ExitOnFailure(hr, "Failed to copy cache id for pseudo bundle.");
63
96 - // If we are a self updating bundle, we don't have to have Install arguments.
97 - if (wzInstallArguments)
98 - {
99 - hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0);
100 - ExitOnFailure(hr, "Failed to copy install arguments for related bundle package");
101 - }
102 -
103 - if (sczRelationTypeCommandLineSwitch)
104 - {
105 - hr = StrAllocConcat(&pPackage->Exe.sczInstallArguments, sczRelationTypeCommandLineSwitch, 0);
106 - ExitOnFailure(hr, "Failed to append relation type to install arguments for related bundle package");
107 - }
108 -
109 - if (wzRepairArguments)
110 - {
111 - hr = StrAllocString(&pPackage->Exe.sczRepairArguments, wzRepairArguments, 0);
112 - ExitOnFailure(hr, "Failed to copy repair arguments for related bundle package");
113 -
114 - if (sczRelationTypeCommandLineSwitch)
115 - {
116 - hr = StrAllocConcat(&pPackage->Exe.sczRepairArguments, sczRelationTypeCommandLineSwitch, 0);
117 - ExitOnFailure(hr, "Failed to append relation type to repair arguments for related bundle package");
118 - }
119 -
120 - pPackage->Exe.fRepairable = TRUE;
121 - }
122 -
123 - if (wzUninstallArguments)
124 - {
125 - hr = StrAllocString(&pPackage->Exe.sczUninstallArguments, wzUninstallArguments, 0);
126 - ExitOnFailure(hr, "Failed to copy uninstall arguments for related bundle package");
127 -
128 - if (sczRelationTypeCommandLineSwitch)
129 - {
130 - hr = StrAllocConcat(&pPackage->Exe.sczUninstallArguments, sczRelationTypeCommandLineSwitch, 0);
131 - ExitOnFailure(hr, "Failed to append relation type to uninstall arguments for related bundle package");
132 - }
133 -
134 - pPackage->fUninstallable = TRUE;
135 - }
136 -
64 if (pDependencyProvider)
65 {
66 pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE);
@@ -153,8 +80,6 @@ extern "C" HRESULT PseudoBundleInitialize(
80 }
81
82 LExit:
156 - ReleaseStr(sczRelationTypeCommandLineSwitch);
157 -
83 return hr;
84 }
85
@@ -165,7 +90,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
90 __in BURN_PACKAGE* pPackage
91 )
92 {
168 - Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type);
93 + Assert(BURN_PACKAGE_TYPE_BUNDLE == pPackage->type);
94
95 HRESULT hr = S_OK;
96 LPWSTR sczArguments = NULL;
@@ -180,59 +105,29 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
105 pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload;
106 }
107
183 - pPassthroughPackage->Exe.fPseudoBundle = TRUE;
184 -
108 pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user.
186 - pPassthroughPackage->type = pPackage->type;
109 + pPassthroughPackage->type = BURN_PACKAGE_TYPE_EXE;
110 pPassthroughPackage->currentState = pPackage->currentState;
111 pPassthroughPackage->fCached = pPackage->fCached;
112 pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize;
113 pPassthroughPackage->qwSize = pPackage->qwSize;
114 pPassthroughPackage->fVital = pPackage->fVital;
115
116 + pPassthroughPackage->Exe.fPseudoBundle = TRUE;
117 + pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
118 +
119 hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0);
120 ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle.");
121
122 hr = StrAllocString(&pPassthroughPackage->sczCacheId, pPackage->sczCacheId, 0);
123 ExitOnFailure(hr, "Failed to copy cache id for passthrough pseudo bundle.");
124
199 - pPassthroughPackage->Exe.protocol = pPackage->Exe.protocol;
200 -
125 hr = CoreCreatePassthroughBundleCommandLine(&sczArguments, pInternalCommand, pCommand);
126 ExitOnFailure(hr, "Failed to create command-line arguments.");
127
128 hr = StrAllocString(&pPassthroughPackage->Exe.sczInstallArguments, sczArguments, 0);
129 ExitOnFailure(hr, "Failed to copy install arguments for passthrough bundle package");
130
207 - hr = StrAllocString(&pPassthroughPackage->Exe.sczRepairArguments, sczArguments, 0);
208 - ExitOnFailure(hr, "Failed to copy related arguments for passthrough bundle package");
209 -
210 - pPassthroughPackage->Exe.fRepairable = TRUE;
211 -
212 - hr = StrAllocString(&pPassthroughPackage->Exe.sczUninstallArguments, sczArguments, 0);
213 - ExitOnFailure(hr, "Failed to copy uninstall arguments for passthrough bundle package");
214 -
215 - pPassthroughPackage->fUninstallable = TRUE;
216 -
217 - // TODO: consider bringing this back in the near future.
218 - //if (pDependencyProvider)
219 - //{
220 - // pPassthroughPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE);
221 - // ExitOnNull(pPassthroughPackage->rgDependencyProviders, hr, E_OUTOFMEMORY, "Failed to allocate memory for dependency providers.");
222 - // pPassthroughPackage->cDependencyProviders = 1;
223 -
224 - // pPassthroughPackage->rgDependencyProviders[0].fImported = pDependencyProvider->fImported;
225 -
226 - // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczKey, pDependencyProvider->sczKey, 0);
227 - // ExitOnFailure(hr, "Failed to copy key for pseudo bundle.");
228 -
229 - // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczVersion, pDependencyProvider->sczVersion, 0);
230 - // ExitOnFailure(hr, "Failed to copy version for pseudo bundle.");
231 -
232 - // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczDisplayName, pDependencyProvider->sczDisplayName, 0);
233 - // ExitOnFailure(hr, "Failed to copy display name for pseudo bundle.");
234 - //}
235 -
131 LExit:
132 ReleaseStr(sczArguments);
133 return hr;
@@ -290,14 +185,16 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
185 memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
186 }
187
293 - pPackage->Exe.fPseudoBundle = TRUE;
294 -
188 pPackage->type = BURN_PACKAGE_TYPE_EXE;
189 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
190 pPackage->qwInstallSize = qwSize;
191 pPackage->qwSize = qwSize;
192 pPackage->fVital = TRUE;
193
194 + // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate.
195 + pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
196 + pPackage->Exe.fPseudoBundle = TRUE;
197 +
198 hr = StrAllocString(&pPackage->sczId, wzId, 0);
199 ExitOnFailure(hr, "Failed to copy id for update bundle.");
200
@@ -307,10 +204,6 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
204 hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0);
205 ExitOnFailure(hr, "Failed to copy install arguments for update bundle package");
206
310 - // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate.
311 - pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
312 - pPackage->Exe.fSupportsAncestors = TRUE;
313 -
207 LExit:
208 return hr;
316 -}
\ No newline at end of file
209 +}
src/burn/engine/pseudobundle.h
+4 -11
@@ -6,25 +6,18 @@
6 extern "C" {
7 #endif
8
9 -HRESULT PseudoBundleInitialize(
9 +HRESULT PseudoBundleInitializeRelated(
10 __in BURN_PACKAGE* pPackage,
11 __in BOOL fSupportsBurnProtocol,
12 __in BOOL fPerMachine,
13 __in_z LPCWSTR wzId,
14 +#ifdef DEBUG
15 __in BOOTSTRAPPER_RELATION_TYPE relationType,
15 - __in BOOTSTRAPPER_PACKAGE_STATE state,
16 +#endif
17 __in BOOL fCached,
18 __in_z LPCWSTR wzFilePath,
18 - __in_z LPCWSTR wzLocalSource,
19 - __in_z_opt LPCWSTR wzDownloadSource,
19 __in DWORD64 qwSize,
21 - __in BOOL fVital,
22 - __in_z_opt LPCWSTR wzInstallArguments,
23 - __in_z_opt LPCWSTR wzRepairArguments,
24 - __in_z_opt LPCWSTR wzUninstallArguments,
25 - __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider,
26 - __in_opt const BYTE* pbHash,
27 - __in const DWORD cbHash
20 + __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider
21 );
22 HRESULT PseudoBundleInitializePassthrough(
23 __in BURN_PACKAGE* pPassthroughPackage,
src/burn/engine/relatedbundle.cpp
+42 -5
@@ -98,6 +98,37 @@ extern "C" void RelatedBundlesUninitialize(
98 }
99
100
101 +extern "C" HRESULT RelatedBundleFindById(
102 + __in BURN_RELATED_BUNDLES* pRelatedBundles,
103 + __in_z LPCWSTR wzId,
104 + __out BURN_RELATED_BUNDLE** ppRelatedBundle
105 + )
106 +{
107 + HRESULT hr = S_OK;
108 + BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
109 + BURN_PACKAGE* pPackage = NULL;
110 +
111 + *ppRelatedBundle = NULL;
112 +
113 + for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i)
114 + {
115 + pRelatedBundle = pRelatedBundles->rgRelatedBundles + i;
116 + pPackage = &pRelatedBundle->package;
117 +
118 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1))
119 + {
120 + *ppRelatedBundle = pRelatedBundle;
121 + ExitFunction1(hr = S_OK);
122 + }
123 + }
124 +
125 + hr = E_NOTFOUND;
126 +
127 +LExit:
128 + return hr;
129 +}
130 +
131 +
132 // internal helper functions
133
134 static HRESULT LoadIfRelatedBundle(
@@ -410,6 +441,7 @@ static HRESULT LoadRelatedBundleFromKey(
441 BOOL fCached = FALSE;
442 DWORD64 qwFileSize = 0;
443 BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
444 + BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL;
445
446 // Only support progress from engines that are compatible.
447 hr = RegReadNumber(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion);
@@ -458,6 +490,11 @@ static HRESULT LoadRelatedBundleFromKey(
490 if (E_FILENOTFOUND != hr)
491 {
492 ExitOnFailure(hr, "Failed to read provider key from registry for bundle: %ls", wzRelatedBundleId);
493 + }
494 +
495 + if (dependencyProvider.sczKey && *dependencyProvider.sczKey)
496 + {
497 + pBundleDependencyProvider = &dependencyProvider;
498
499 dependencyProvider.fImported = TRUE;
500
@@ -480,11 +517,11 @@ static HRESULT LoadRelatedBundleFromKey(
517
518 pRelatedBundle->relationType = relationType;
519
483 - hr = PseudoBundleInitialize(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType,
484 - BOOTSTRAPPER_PACKAGE_STATE_PRESENT, fCached, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE,
485 - L"-quiet", L"-repair -quiet", L"-uninstall -quiet",
486 - (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL,
487 - NULL, 0);
520 + hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId,
521 +#ifdef DEBUG
522 + pRelatedBundle->relationType,
523 +#endif
524 + fCached, sczCachePath, qwFileSize, pBundleDependencyProvider);
525 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId);
526
527 LExit:
src/burn/engine/relatedbundle.h
+5
@@ -14,6 +14,11 @@ HRESULT RelatedBundlesInitializeForScope(
14 void RelatedBundlesUninitialize(
15 __in BURN_RELATED_BUNDLES* pRelatedBundles
16 );
17 +HRESULT RelatedBundleFindById(
18 + __in BURN_RELATED_BUNDLES* pRelatedBundles,
19 + __in_z LPCWSTR wzId,
20 + __out BURN_RELATED_BUNDLE** ppRelatedBundle
21 + );
22
23 #if defined(__cplusplus)
24 }
src/burn/test/BurnUnitTest/PlanTest.cpp
+26 -7
@@ -117,7 +117,7 @@ namespace Bootstrapper
117 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
118 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
119 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
120 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
120 + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
121 Assert::Equal(dwIndex, pPlan->cExecuteActions);
122
123 fRollback = TRUE;
@@ -155,7 +155,7 @@ namespace Bootstrapper
155 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
156 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
157 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
158 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
158 + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
159 Assert::Equal(dwIndex, pPlan->cRollbackActions);
160
161 Assert::Equal(4ul, pPlan->cExecutePackagesTotal);
@@ -496,7 +496,7 @@ namespace Bootstrapper
496 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
497 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
498 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
499 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
499 + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
500 Assert::Equal(dwIndex, pPlan->cExecuteActions);
501
502 fRollback = TRUE;
@@ -514,7 +514,7 @@ namespace Bootstrapper
514 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
515 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
516 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
517 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
517 + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
518 Assert::Equal(dwIndex, pPlan->cRollbackActions);
519
520 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
@@ -1154,7 +1154,11 @@ namespace Bootstrapper
1154 pRelatedBundle->fPlannable = TRUE;
1155 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1156
1157 - hr = PseudoBundleInitialize(&pRelatedBundle->package, TRUE, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, TRUE, wzFilePath, wzFilePath, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0);
1157 + hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, TRUE, TRUE, wzId,
1158 +#ifdef DEBUG
1159 + pRelatedBundle->relationType,
1160 +#endif
1161 + TRUE, wzFilePath, 0, &dependencyProvider);
1162 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
1163
1164 ++pRelatedBundles->cRelatedBundles;
@@ -1310,7 +1314,7 @@ namespace Bootstrapper
1314 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1315 }
1316
1313 - void ValidateExecuteExePackage(
1317 + void ValidateExecuteRelatedBundle(
1318 __in BURN_PLAN* pPlan,
1319 __in BOOL fRollback,
1320 __in DWORD dwIndex,
@@ -1318,12 +1322,27 @@ namespace Bootstrapper
1322 __in BOOTSTRAPPER_ACTION_STATE action,
1323 __in LPCWSTR wzIgnoreDependencies
1324 )
1325 + {
1326 + BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1327 + Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE, pAction->type);
1328 + NativeAssert::StringEqual(wzPackageId, pAction->relatedBundle.pRelatedBundle->package.sczId);
1329 + Assert::Equal<DWORD>(action, pAction->relatedBundle.action);
1330 + NativeAssert::StringEqual(wzIgnoreDependencies, pAction->relatedBundle.sczIgnoreDependencies);
1331 + Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1332 + }
1333 +
1334 + void ValidateExecuteExePackage(
1335 + __in BURN_PLAN* pPlan,
1336 + __in BOOL fRollback,
1337 + __in DWORD dwIndex,
1338 + __in LPCWSTR wzPackageId,
1339 + __in BOOTSTRAPPER_ACTION_STATE action
1340 + )
1341 {
1342 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1343 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
1344 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
1345 Assert::Equal<DWORD>(action, pAction->exePackage.action);
1326 - NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
1346 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1347 }
1348