aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-03-30 17:08:40 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-04-01 22:06:11 -0500
commit386a3578413ba16b3c0615d47870ee44a0e461f6 (patch)
tree1dfcea9e5080f1f15cc880aba1541a962426c58b /src/burn
parentd97c0d1685ef4c3840776327e76ce25d4dbdbeb1 (diff)
downloadwix-386a3578413ba16b3c0615d47870ee44a0e461f6.tar.gz
wix-386a3578413ba16b3c0615d47870ee44a0e461f6.tar.bz2
wix-386a3578413ba16b3c0615d47870ee44a0e461f6.zip
Implement BundlePackage.
3693
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/apply.cpp102
-rw-r--r--src/burn/engine/bundlepackageengine.cpp272
-rw-r--r--src/burn/engine/bundlepackageengine.h26
-rw-r--r--src/burn/engine/core.cpp16
-rw-r--r--src/burn/engine/core.h1
-rw-r--r--src/burn/engine/elevation.cpp176
-rw-r--r--src/burn/engine/elevation.h9
-rw-r--r--src/burn/engine/exeengine.cpp24
-rw-r--r--src/burn/engine/logging.cpp2
-rw-r--r--src/burn/engine/package.cpp18
-rw-r--r--src/burn/engine/package.h4
-rw-r--r--src/burn/engine/plan.cpp24
-rw-r--r--src/burn/engine/plan.h8
-rw-r--r--src/burn/engine/registration.cpp5
-rw-r--r--src/burn/engine/registration.h2
-rw-r--r--src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj1
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp141
-rw-r--r--src/burn/test/BurnUnitTest/TestData/PlanTest/BundlePackage_Multiple_manifest.xml1
18 files changed, 765 insertions, 67 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index 6af5c040..9ee7b58c 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -216,6 +216,15 @@ static HRESULT DoRestoreRelatedBundleActions(
216 __in BURN_EXECUTE_CONTEXT* pContext, 216 __in BURN_EXECUTE_CONTEXT* pContext,
217 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 217 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
218 ); 218 );
219static HRESULT ExecuteBundlePackage(
220 __in BURN_ENGINE_STATE* pEngineState,
221 __in BURN_EXECUTE_ACTION* pExecuteAction,
222 __in BURN_EXECUTE_CONTEXT* pContext,
223 __in BOOL fRollback,
224 __out BOOL* pfRetry,
225 __out BOOL* pfSuspend,
226 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
227 );
219static HRESULT ExecuteExePackage( 228static HRESULT ExecuteExePackage(
220 __in BURN_ENGINE_STATE* pEngineState, 229 __in BURN_ENGINE_STATE* pEngineState,
221 __in BURN_EXECUTE_ACTION* pExecuteAction, 230 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -732,6 +741,9 @@ extern "C" HRESULT ApplyExecute(
732 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: 741 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
733 wzId = pExecuteAction->relatedBundle.pRelatedBundle->package.sczId; 742 wzId = pExecuteAction->relatedBundle.pRelatedBundle->package.sczId;
734 break; 743 break;
744 case BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE:
745 wzId = pExecuteAction->bundlePackage.pPackage->sczId;
746 break;
735 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 747 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
736 wzId = pExecuteAction->exePackage.pPackage->sczId; 748 wzId = pExecuteAction->exePackage.pPackage->sczId;
737 break; 749 break;
@@ -2352,6 +2364,11 @@ static HRESULT DoExecuteAction(
2352 ExitOnFailure(hr, "Failed to execute related bundle."); 2364 ExitOnFailure(hr, "Failed to execute related bundle.");
2353 break; 2365 break;
2354 2366
2367 case BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE:
2368 hr = ExecuteBundlePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2369 ExitOnFailure(hr, "Failed to execute BUNDLE package.");
2370 break;
2371
2355 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 2372 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2356 hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart); 2373 hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2357 ExitOnFailure(hr, "Failed to execute EXE package."); 2374 ExitOnFailure(hr, "Failed to execute EXE package.");
@@ -2479,6 +2496,11 @@ static HRESULT DoRollbackActions(
2479 ExitOnFailure(hr, "Failed to execute related bundle."); 2496 ExitOnFailure(hr, "Failed to execute related bundle.");
2480 break; 2497 break;
2481 2498
2499 case BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE:
2500 hr = ExecuteBundlePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2501 IgnoreRollbackError(hr, "Failed to rollback BUNDLE package.");
2502 break;
2503
2482 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 2504 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2483 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); 2505 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2484 IgnoreRollbackError(hr, "Failed to rollback EXE package."); 2506 IgnoreRollbackError(hr, "Failed to rollback EXE package.");
@@ -2682,6 +2704,86 @@ LExit:
2682 return hr; 2704 return hr;
2683} 2705}
2684 2706
2707static HRESULT ExecuteBundlePackage(
2708 __in BURN_ENGINE_STATE* pEngineState,
2709 __in BURN_EXECUTE_ACTION* pExecuteAction,
2710 __in BURN_EXECUTE_CONTEXT* pContext,
2711 __in BOOL fRollback,
2712 __out BOOL* pfRetry,
2713 __out BOOL* pfSuspend,
2714 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
2715 )
2716{
2717 HRESULT hr = S_OK;
2718 HRESULT hrExecute = S_OK;
2719 GENERIC_EXECUTE_MESSAGE message = { };
2720 int nResult = 0;
2721 BOOL fBeginCalled = FALSE;
2722 BOOL fExecuted = FALSE;
2723 BURN_PACKAGE* pPackage = pExecuteAction->bundlePackage.pPackage;
2724
2725 Assert(pContext->fRollback == fRollback);
2726
2727 if (ShouldSkipPackage(pPackage, fRollback))
2728 {
2729 ExitFunction1(hr = S_OK);
2730 }
2731
2732 pContext->wzExecutingPackageId = pPackage->sczId;
2733 fBeginCalled = TRUE;
2734
2735 // Send package execute begin to BA.
2736 hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->bundlePackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
2737 ExitOnRootFailure(hr, "BA aborted execute BUNDLE package begin.");
2738
2739 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
2740 message.dwUIHint = MB_OKCANCEL;
2741 message.progress.dwPercentage = fRollback ? 100 : 0;
2742 nResult = GenericExecuteMessageHandler(&message, pContext);
2743 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult);
2744 ExitOnRootFailure(hr, "BA aborted BUNDLE progress.");
2745
2746 fExecuted = TRUE;
2747
2748 // Execute package.
2749 if (pPackage->fPerMachine)
2750 {
2751 hrExecute = ElevationExecuteBundlePackage(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
2752 ExitOnFailure(hrExecute, "Failed to configure per-machine BUNDLE package.");
2753 }
2754 else
2755 {
2756 hrExecute = BundlePackageEngineExecutePackage(pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
2757 ExitOnFailure(hrExecute, "Failed to configure per-user BUNDLE package.");
2758 }
2759
2760 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
2761 message.dwUIHint = MB_OKCANCEL;
2762 message.progress.dwPercentage = fRollback ? 0 : 100;
2763 nResult = GenericExecuteMessageHandler(&message, pContext);
2764 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult);
2765 ExitOnRootFailure(hr, "BA aborted BUNDLE progress.");
2766
2767 pContext->cExecutedPackages += fRollback ? -1 : 1;
2768
2769 hr = ReportOverallProgressTicks(&pEngineState->userExperience, fRollback, pEngineState->plan.cOverallProgressTicksTotal, pContext->pApplyContext);
2770 ExitOnRootFailure(hr, "BA aborted BUNDLE package execute progress.");
2771
2772LExit:
2773 if (fExecuted)
2774 {
2775 BundlePackageEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute);
2776 }
2777
2778 if (fBeginCalled)
2779 {
2780 pPackage->fAbandonedProcess = pContext->fAbandonedProcess;
2781 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, pPackage->fAbandonedProcess, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2782 }
2783
2784 return hr;
2785}
2786
2685static HRESULT ExecuteExePackage( 2787static HRESULT ExecuteExePackage(
2686 __in BURN_ENGINE_STATE* pEngineState, 2788 __in BURN_ENGINE_STATE* pEngineState,
2687 __in BURN_EXECUTE_ACTION* pExecuteAction, 2789 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index 89488b91..f3badfc1 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -2,16 +2,80 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5static HRESULT ExecuteBundle(
6 __in BURN_CACHE* pCache,
7 __in BURN_VARIABLES* pVariables,
8 __in BOOL fRollback,
9 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
10 __in LPVOID pvContext,
11 __in BOOTSTRAPPER_ACTION_STATE action,
12 __in BOOTSTRAPPER_RELATION_TYPE relationType,
13 __in BURN_PACKAGE* pPackage,
14 __in_z_opt LPCWSTR wzIgnoreDependencies,
15 __in_z_opt LPCWSTR wzAncestors,
16 __in_z_opt LPCWSTR wzEngineWorkingDirectory,
17 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
18 );
5static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType( 19static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType(
6 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relationType 20 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relationType
7 ); 21 );
8 22
9// function definitions 23// function definitions
10 24
25extern "C" HRESULT BundlePackageEngineParsePackageFromXml(
26 __in IXMLDOMNode* pixnBundlePackage,
27 __in BURN_PACKAGE* pPackage
28 )
29{
30 HRESULT hr = S_OK;
31 BOOL fFoundXml = FALSE;
32 LPWSTR scz = NULL;
33
34 // @DetectCondition
35 hr = XmlGetAttributeEx(pixnBundlePackage, L"BundleId", &pPackage->Bundle.sczBundleId);
36 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @BundleId.");
37
38 // @InstallArguments
39 hr = XmlGetAttributeEx(pixnBundlePackage, L"InstallArguments", &pPackage->Bundle.sczInstallArguments);
40 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArguments.");
41
42 // @UninstallArguments
43 hr = XmlGetAttributeEx(pixnBundlePackage, L"UninstallArguments", &pPackage->Bundle.sczUninstallArguments);
44 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @UninstallArguments.");
45
46 // @RepairArguments
47 hr = XmlGetAttributeEx(pixnBundlePackage, L"RepairArguments", &pPackage->Bundle.sczRepairArguments);
48 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments.");
49
50 // @SupportsBurnProtocol
51 hr = XmlGetYesNoAttribute(pixnBundlePackage, L"SupportsBurnProtocol", &pPackage->Bundle.fSupportsBurnProtocol);
52 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @SupportsBurnProtocol.");
53
54 // @Win64
55 hr = XmlGetYesNoAttribute(pixnBundlePackage, L"Win64", &pPackage->Bundle.fWin64);
56 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Win64.");
57
58 hr = ExeEngineParseExitCodesFromXml(pixnBundlePackage, &pPackage->Bundle.rgExitCodes, &pPackage->Bundle.cExitCodes);
59 ExitOnFailure(hr, "Failed to parse exit codes.");
60
61 hr = ExeEngineParseCommandLineArgumentsFromXml(pixnBundlePackage, &pPackage->Bundle.rgCommandLineArguments, &pPackage->Bundle.cCommandLineArguments);
62 ExitOnFailure(hr, "Failed to parse command lines.");
63
64 hr = StrAllocFormatted(&pPackage->Bundle.sczRegistrationKey, L"%ls\\%ls", BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, pPackage->Bundle.sczBundleId);
65 ExitOnFailure(hr, "Failed to build uninstall registry key path.");
66
67LExit:
68 ReleaseStr(scz);
69
70 return hr;
71}
72
11extern "C" void BundlePackageEnginePackageUninitialize( 73extern "C" void BundlePackageEnginePackageUninitialize(
12 __in BURN_PACKAGE* pPackage 74 __in BURN_PACKAGE* pPackage
13 ) 75 )
14{ 76{
77 ReleaseStr(pPackage->Bundle.sczBundleId);
78 ReleaseStr(pPackage->Bundle.sczRegistrationKey);
15 ReleaseStr(pPackage->Bundle.sczInstallArguments); 79 ReleaseStr(pPackage->Bundle.sczInstallArguments);
16 ReleaseStr(pPackage->Bundle.sczRepairArguments); 80 ReleaseStr(pPackage->Bundle.sczRepairArguments);
17 ReleaseStr(pPackage->Bundle.sczUninstallArguments); 81 ReleaseStr(pPackage->Bundle.sczUninstallArguments);
@@ -32,6 +96,44 @@ extern "C" void BundlePackageEnginePackageUninitialize(
32 memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle)); 96 memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle));
33} 97}
34 98
99extern "C" HRESULT BundlePackageEngineDetectPackage(
100 __in BURN_PACKAGE* pPackage
101 )
102{
103 HRESULT hr = S_OK;
104 HKEY hkRegistration = NULL;
105 DWORD dwInstalled = 0;
106 BOOL fDetected = FALSE;
107 HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
108 REG_KEY_BITNESS bitness = pPackage->Bundle.fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT;
109
110 // TODO: detect all related bundles, so that the Obsolete state can be detected.
111 hr = RegOpenEx(hkRoot, pPackage->Bundle.sczRegistrationKey, KEY_QUERY_VALUE, bitness, &hkRegistration);
112 if (SUCCEEDED(hr))
113 {
114 hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_INSTALLED, &dwInstalled);
115 }
116
117 // Not finding the key or value is okay.
118 if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr)
119 {
120 hr = S_OK;
121 }
122
123 fDetected = (1 == dwInstalled);
124
125 // update detect state
126 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
127
128 if (pPackage->fCanAffectRegistration)
129 {
130 pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
131 }
132
133 ReleaseRegKey(hkRegistration);
134 return hr;
135}
136
35// 137//
36// PlanCalculate - calculates the execute and rollback state for the requested package state. 138// PlanCalculate - calculates the execute and rollback state for the requested package state.
37// 139//
@@ -151,6 +253,79 @@ LExit:
151// 253//
152// PlanAdd - adds the calculated execute and rollback actions for the package. 254// PlanAdd - adds the calculated execute and rollback actions for the package.
153// 255//
256extern "C" HRESULT BundlePackageEnginePlanAddPackage(
257 __in BURN_PACKAGE* pPackage,
258 __in BURN_PLAN* pPlan,
259 __in BURN_LOGGING* pLog,
260 __in BURN_VARIABLES* pVariables
261 )
262{
263 HRESULT hr = S_OK;
264 BURN_EXECUTE_ACTION* pAction = NULL;
265
266 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
267 ExitOnFailure(hr, "Failed to plan package dependency actions.");
268
269 // add rollback action
270 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
271 {
272 hr = PlanAppendRollbackAction(pPlan, &pAction);
273 ExitOnFailure(hr, "Failed to append rollback action.");
274
275 pAction->type = BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE;
276 pAction->bundlePackage.pPackage = pPackage;
277 pAction->bundlePackage.action = pPackage->rollback;
278
279 if (pPackage->Bundle.wzAncestors)
280 {
281 hr = StrAllocString(&pAction->bundlePackage.sczAncestors, pPackage->Bundle.wzAncestors, 0);
282 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
283 }
284
285 if (pPackage->Bundle.wzEngineWorkingDirectory)
286 {
287 hr = StrAllocString(&pAction->bundlePackage.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0);
288 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
289 }
290
291 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
292
293 hr = PlanExecuteCheckpoint(pPlan);
294 ExitOnFailure(hr, "Failed to append execute checkpoint.");
295 }
296
297 // add execute action
298 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
299 {
300 hr = PlanAppendExecuteAction(pPlan, &pAction);
301 ExitOnFailure(hr, "Failed to append execute action.");
302
303 pAction->type = BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE;
304 pAction->bundlePackage.pPackage = pPackage;
305 pAction->bundlePackage.action = pPackage->execute;
306
307 if (pPackage->Bundle.wzAncestors)
308 {
309 hr = StrAllocString(&pAction->bundlePackage.sczAncestors, pPackage->Bundle.wzAncestors, 0);
310 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
311 }
312
313 if (pPackage->Bundle.wzEngineWorkingDirectory)
314 {
315 hr = StrAllocString(&pAction->bundlePackage.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0);
316 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
317 }
318
319 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
320 }
321
322LExit:
323 return hr;
324}
325
326//
327// PlanAdd - adds the calculated execute and rollback actions for the related bundle.
328//
154extern "C" HRESULT BundlePackageEnginePlanAddRelatedBundle( 329extern "C" HRESULT BundlePackageEnginePlanAddRelatedBundle(
155 __in_opt DWORD *pdwInsertSequence, 330 __in_opt DWORD *pdwInsertSequence,
156 __in BURN_RELATED_BUNDLE* pRelatedBundle, 331 __in BURN_RELATED_BUNDLE* pRelatedBundle,
@@ -164,7 +339,7 @@ extern "C" HRESULT BundlePackageEnginePlanAddRelatedBundle(
164 BURN_PACKAGE* pPackage = &pRelatedBundle->package; 339 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
165 340
166 hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan); 341 hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
167 ExitOnFailure(hr, "Failed to plan package dependency actions."); 342 ExitOnFailure(hr, "Failed to plan related bundle dependency actions.");
168 343
169 // add execute action 344 // add execute action
170 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) 345 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
@@ -240,6 +415,26 @@ LExit:
240 return hr; 415 return hr;
241} 416}
242 417
418extern "C" HRESULT BundlePackageEngineExecutePackage(
419 __in BURN_EXECUTE_ACTION* pExecuteAction,
420 __in BURN_CACHE* pCache,
421 __in BURN_VARIABLES* pVariables,
422 __in BOOL fRollback,
423 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
424 __in LPVOID pvContext,
425 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
426 )
427{
428 BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->bundlePackage.action;
429 LPCWSTR wzIgnoreDependencies = pExecuteAction->bundlePackage.sczIgnoreDependencies;
430 LPCWSTR wzAncestors = pExecuteAction->bundlePackage.sczAncestors;
431 LPCWSTR wzEngineWorkingDirectory = pExecuteAction->bundlePackage.sczEngineWorkingDirectory;
432 BOOTSTRAPPER_RELATION_TYPE relationType = BOOTSTRAPPER_RELATION_CHAIN_PACKAGE;
433 BURN_PACKAGE* pPackage = pExecuteAction->bundlePackage.pPackage;
434
435 return ExecuteBundle(pCache, pVariables, fRollback, pfnGenericMessageHandler, pvContext, action, relationType, pPackage, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart);
436}
437
243extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( 438extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
244 __in BURN_EXECUTE_ACTION* pExecuteAction, 439 __in BURN_EXECUTE_ACTION* pExecuteAction,
245 __in BURN_CACHE* pCache, 440 __in BURN_CACHE* pCache,
@@ -250,6 +445,57 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
250 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 445 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
251 ) 446 )
252{ 447{
448 BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action;
449 LPCWSTR wzIgnoreDependencies = pExecuteAction->relatedBundle.sczIgnoreDependencies;
450 LPCWSTR wzAncestors = pExecuteAction->relatedBundle.sczAncestors;
451 LPCWSTR wzEngineWorkingDirectory = pExecuteAction->relatedBundle.sczEngineWorkingDirectory;
452 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
453 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pRelatedBundle->planRelationType);
454 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
455
456 return ExecuteBundle(pCache, pVariables, fRollback, pfnGenericMessageHandler, pvContext, action, relationType, pPackage, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart);
457}
458
459extern "C" void BundlePackageEngineUpdateInstallRegistrationState(
460 __in BURN_EXECUTE_ACTION* pAction,
461 __in HRESULT hrExecute
462 )
463{
464 BURN_PACKAGE* pPackage = pAction->bundlePackage.pPackage;
465
466 if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration)
467 {
468 ExitFunction();
469 }
470
471 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->bundlePackage.action)
472 {
473 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
474 }
475 else
476 {
477 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
478 }
479
480LExit:
481 return;
482}
483
484static HRESULT ExecuteBundle(
485 __in BURN_CACHE* pCache,
486 __in BURN_VARIABLES* pVariables,
487 __in BOOL fRollback,
488 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
489 __in LPVOID pvContext,
490 __in BOOTSTRAPPER_ACTION_STATE action,
491 __in BOOTSTRAPPER_RELATION_TYPE relationType,
492 __in BURN_PACKAGE* pPackage,
493 __in_z_opt LPCWSTR wzIgnoreDependencies,
494 __in_z_opt LPCWSTR wzAncestors,
495 __in_z_opt LPCWSTR wzEngineWorkingDirectory,
496 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
497 )
498{
253 HRESULT hr = S_OK; 499 HRESULT hr = S_OK;
254 LPCWSTR wzArguments = NULL; 500 LPCWSTR wzArguments = NULL;
255 LPWSTR sczCachedDirectory = NULL; 501 LPWSTR sczCachedDirectory = NULL;
@@ -264,10 +510,6 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
264 PROCESS_INFORMATION pi = { }; 510 PROCESS_INFORMATION pi = { };
265 DWORD dwExitCode = 0; 511 DWORD dwExitCode = 0;
266 GENERIC_EXECUTE_MESSAGE message = { }; 512 GENERIC_EXECUTE_MESSAGE message = { };
267 BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action;
268 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
269 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pRelatedBundle->planRelationType);
270 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
271 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; 513 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
272 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType); 514 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
273 LPCWSTR wzOperationCommandLine = NULL; 515 LPCWSTR wzOperationCommandLine = NULL;
@@ -376,21 +618,29 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
376 } 618 }
377 619
378 // Add the list of dependencies to ignore, if any, to the burn command line. 620 // Add the list of dependencies to ignore, if any, to the burn command line.
379 if (pExecuteAction->relatedBundle.sczIgnoreDependencies) 621 if (BOOTSTRAPPER_RELATION_CHAIN_PACKAGE == relationType)
380 { 622 {
381 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies); 623 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=ALL", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES);
624 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
625 }
626 else if (wzIgnoreDependencies)
627 {
628 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, wzIgnoreDependencies);
382 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); 629 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
383 } 630 }
384 631
385 // Add the list of ancestors, if any, to the burn command line. 632 // Add the list of ancestors, if any, to the burn command line.
386 if (pExecuteAction->relatedBundle.sczAncestors) 633 if (wzAncestors)
387 { 634 {
388 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors); 635 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, wzAncestors);
389 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); 636 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
390 } 637 }
391 638
392 hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczBaseCommand, NULL); 639 if (wzEngineWorkingDirectory)
393 ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line."); 640 {
641 hr = CoreAppendEngineWorkingDirectoryToCommandLine(wzEngineWorkingDirectory, &sczBaseCommand, NULL);
642 ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line.");
643 }
394 644
395 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL); 645 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL);
396 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); 646 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
diff --git a/src/burn/engine/bundlepackageengine.h b/src/burn/engine/bundlepackageengine.h
index 0d59907d..9271ac6a 100644
--- a/src/burn/engine/bundlepackageengine.h
+++ b/src/burn/engine/bundlepackageengine.h
@@ -9,12 +9,25 @@ extern "C" {
9 9
10// function declarations 10// function declarations
11 11
12HRESULT BundlePackageEngineParsePackageFromXml(
13 __in IXMLDOMNode* pixnBundlePackage,
14 __in BURN_PACKAGE* pPackage
15 );
12void BundlePackageEnginePackageUninitialize( 16void BundlePackageEnginePackageUninitialize(
13 __in BURN_PACKAGE* pPackage 17 __in BURN_PACKAGE* pPackage
14 ); 18 );
19HRESULT BundlePackageEngineDetectPackage(
20 __in BURN_PACKAGE* pPackage
21 );
15HRESULT BundlePackageEnginePlanCalculatePackage( 22HRESULT BundlePackageEnginePlanCalculatePackage(
16 __in BURN_PACKAGE* pPackage 23 __in BURN_PACKAGE* pPackage
17 ); 24 );
25HRESULT BundlePackageEnginePlanAddPackage(
26 __in BURN_PACKAGE* pPackage,
27 __in BURN_PLAN* pPlan,
28 __in BURN_LOGGING* pLog,
29 __in BURN_VARIABLES* pVariables
30 );
18HRESULT BundlePackageEnginePlanAddRelatedBundle( 31HRESULT BundlePackageEnginePlanAddRelatedBundle(
19 __in_opt DWORD *pdwInsertSequence, 32 __in_opt DWORD *pdwInsertSequence,
20 __in BURN_RELATED_BUNDLE* pRelatedBundle, 33 __in BURN_RELATED_BUNDLE* pRelatedBundle,
@@ -22,6 +35,15 @@ HRESULT BundlePackageEnginePlanAddRelatedBundle(
22 __in BURN_LOGGING* pLog, 35 __in BURN_LOGGING* pLog,
23 __in BURN_VARIABLES* pVariables 36 __in BURN_VARIABLES* pVariables
24 ); 37 );
38HRESULT BundlePackageEngineExecutePackage(
39 __in BURN_EXECUTE_ACTION* pExecuteAction,
40 __in BURN_CACHE* pCache,
41 __in BURN_VARIABLES* pVariables,
42 __in BOOL fRollback,
43 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
44 __in LPVOID pvContext,
45 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
46 );
25HRESULT BundlePackageEngineExecuteRelatedBundle( 47HRESULT BundlePackageEngineExecuteRelatedBundle(
26 __in BURN_EXECUTE_ACTION* pExecuteAction, 48 __in BURN_EXECUTE_ACTION* pExecuteAction,
27 __in BURN_CACHE* pCache, 49 __in BURN_CACHE* pCache,
@@ -31,6 +53,10 @@ HRESULT BundlePackageEngineExecuteRelatedBundle(
31 __in LPVOID pvContext, 53 __in LPVOID pvContext,
32 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 54 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
33 ); 55 );
56void BundlePackageEngineUpdateInstallRegistrationState(
57 __in BURN_EXECUTE_ACTION* pAction,
58 __in HRESULT hrExecute
59 );
34 60
35 61
36#if defined(__cplusplus) 62#if defined(__cplusplus)
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 551843f2..3370ad05 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -956,6 +956,9 @@ extern "C" LPCWSTR CoreRelationTypeToCommandLineString(
956 case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH: 956 case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH:
957 wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH; 957 wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH;
958 break; 958 break;
959 case BOOTSTRAPPER_RELATION_CHAIN_PACKAGE:
960 wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE;
961 break;
959 case BOOTSTRAPPER_RELATION_NONE: __fallthrough; 962 case BOOTSTRAPPER_RELATION_NONE: __fallthrough;
960 default: 963 default:
961 wzRelationTypeCommandLine = NULL; 964 wzRelationTypeCommandLine = NULL;
@@ -1709,6 +1712,12 @@ extern "C" HRESULT CoreParseCommandLine(
1709 1712
1710 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1713 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1711 } 1714 }
1715 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE, -1))
1716 {
1717 pCommand->relationType = BOOTSTRAPPER_RELATION_CHAIN_PACKAGE;
1718
1719 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1720 }
1712 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PASSTHROUGH, -1)) 1721 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PASSTHROUGH, -1))
1713 { 1722 {
1714 pCommand->fPassthrough = TRUE; 1723 pCommand->fPassthrough = TRUE;
@@ -2111,6 +2120,10 @@ static HRESULT DetectPackage(
2111 // Use the correct engine to detect the package. 2120 // Use the correct engine to detect the package.
2112 switch (pPackage->type) 2121 switch (pPackage->type)
2113 { 2122 {
2123 case BURN_PACKAGE_TYPE_BUNDLE:
2124 hr = BundlePackageEngineDetectPackage(pPackage);
2125 break;
2126
2114 case BURN_PACKAGE_TYPE_EXE: 2127 case BURN_PACKAGE_TYPE_EXE:
2115 hr = ExeEngineDetectPackage(pPackage, &pEngineState->registration, &pEngineState->variables); 2128 hr = ExeEngineDetectPackage(pPackage, &pEngineState->registration, &pEngineState->variables);
2116 break; 2129 break;
@@ -2128,8 +2141,7 @@ static HRESULT DetectPackage(
2128 break; 2141 break;
2129 2142
2130 default: 2143 default:
2131 hr = E_NOTIMPL; 2144 ExitWithRootFailure(hr, E_NOTIMPL, "Package type not supported by detect yet.");
2132 ExitOnRootFailure(hr, "Package type not supported by detect yet.");
2133 } 2145 }
2134 2146
2135LExit: 2147LExit:
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index cee71aec..556124d6 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -27,6 +27,7 @@ const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_ADDON = L"burn.related.d
27const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_PATCH = L"burn.related.patch"; 27const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_PATCH = L"burn.related.patch";
28const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH = L"burn.related.dependent.patch"; 28const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH = L"burn.related.dependent.patch";
29const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_UPDATE = L"burn.related.update"; 29const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_UPDATE = L"burn.related.update";
30const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE = L"burn.related.chain.package";
30const LPCWSTR BURN_COMMANDLINE_SWITCH_PASSTHROUGH = L"burn.passthrough"; 31const LPCWSTR BURN_COMMANDLINE_SWITCH_PASSTHROUGH = L"burn.passthrough";
31const LPCWSTR BURN_COMMANDLINE_SWITCH_DISABLE_UNELEVATE = L"burn.disable.unelevate"; 32const LPCWSTR BURN_COMMANDLINE_SWITCH_DISABLE_UNELEVATE = L"burn.disable.unelevate";
32const LPCWSTR BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES = L"burn.ignoredependencies"; 33const LPCWSTR BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES = L"burn.ignoredependencies";
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 8488b649..504ddaea 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -20,6 +20,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
20 BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, 20 BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP,
21 BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, 21 BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION,
22 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, 22 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE,
23 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE,
23 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, 24 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE,
24 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, 25 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE,
25 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, 26 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE,
@@ -250,6 +251,14 @@ static HRESULT OnExecuteRelatedBundle(
250 __in BYTE* pbData, 251 __in BYTE* pbData,
251 __in SIZE_T cbData 252 __in SIZE_T cbData
252 ); 253 );
254static HRESULT OnExecuteBundlePackage(
255 __in HANDLE hPipe,
256 __in BURN_CACHE* pCache,
257 __in BURN_PACKAGES* pPackages,
258 __in BURN_VARIABLES* pVariables,
259 __in BYTE* pbData,
260 __in SIZE_T cbData
261 );
253static HRESULT OnExecuteExePackage( 262static HRESULT OnExecuteExePackage(
254 __in HANDLE hPipe, 263 __in HANDLE hPipe,
255 __in BURN_CACHE* pCache, 264 __in BURN_CACHE* pCache,
@@ -911,6 +920,63 @@ LExit:
911} 920}
912 921
913/******************************************************************* 922/*******************************************************************
923 ElevationExecuteBundlePackage -
924
925*******************************************************************/
926extern "C" HRESULT ElevationExecuteBundlePackage(
927 __in HANDLE hPipe,
928 __in BURN_EXECUTE_ACTION* pExecuteAction,
929 __in BURN_VARIABLES* pVariables,
930 __in BOOL fRollback,
931 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
932 __in LPVOID pvContext,
933 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
934 )
935{
936 HRESULT hr = S_OK;
937 BYTE* pbData = NULL;
938 SIZE_T cbData = 0;
939 BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT context = { };
940 DWORD dwResult = 0;
941
942 // serialize message data
943 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.pPackage->sczId);
944 ExitOnFailure(hr, "Failed to write package id to message buffer.");
945
946 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->bundlePackage.action);
947 ExitOnFailure(hr, "Failed to write action to message buffer.");
948
949 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
950 ExitOnFailure(hr, "Failed to write rollback.");
951
952 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczIgnoreDependencies);
953 ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
954
955 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczAncestors);
956 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
957
958 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczEngineWorkingDirectory);
959 ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer.");
960
961 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
962 ExitOnFailure(hr, "Failed to write variables.");
963
964 // send message
965 context.pfnGenericMessageHandler = pfnGenericMessageHandler;
966 context.pvContext = pvContext;
967
968 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
969 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE message to per-machine process.");
970
971 hr = ProcessResult(dwResult, pRestart);
972
973LExit:
974 ReleaseBuffer(pbData);
975
976 return hr;
977}
978
979/*******************************************************************
914 ElevationExecuteExePackage - 980 ElevationExecuteExePackage -
915 981
916*******************************************************************/ 982*******************************************************************/
@@ -940,9 +1006,6 @@ extern "C" HRESULT ElevationExecuteExePackage(
940 hr = BuffWriteNumber(&pbData, &cbData, fRollback); 1006 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
941 ExitOnFailure(hr, "Failed to write rollback."); 1007 ExitOnFailure(hr, "Failed to write rollback.");
942 1008
943 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies);
944 ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
945
946 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); 1009 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors);
947 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); 1010 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
948 1011
@@ -2124,6 +2187,10 @@ static HRESULT ProcessElevatedChildMessage(
2124 hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2187 hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
2125 break; 2188 break;
2126 2189
2190 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE:
2191 hrResult = OnExecuteBundlePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
2192 break;
2193
2127 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE: 2194 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE:
2128 hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2195 hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
2129 break; 2196 break;
@@ -2839,7 +2906,7 @@ LExit:
2839 return hr; 2906 return hr;
2840} 2907}
2841 2908
2842static HRESULT OnExecuteExePackage( 2909static HRESULT OnExecuteBundlePackage(
2843 __in HANDLE hPipe, 2910 __in HANDLE hPipe,
2844 __in BURN_CACHE* pCache, 2911 __in BURN_CACHE* pCache,
2845 __in BURN_PACKAGES* pPackages, 2912 __in BURN_PACKAGES* pPackages,
@@ -2856,15 +2923,15 @@ static HRESULT OnExecuteExePackage(
2856 LPWSTR sczIgnoreDependencies = NULL; 2923 LPWSTR sczIgnoreDependencies = NULL;
2857 LPWSTR sczAncestors = NULL; 2924 LPWSTR sczAncestors = NULL;
2858 LPWSTR sczEngineWorkingDirectory = NULL; 2925 LPWSTR sczEngineWorkingDirectory = NULL;
2859 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2926 BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2860 2927
2861 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 2928 executeAction.type = BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE;
2862 2929
2863 // Deserialize message data. 2930 // Deserialize message data.
2864 hr = BuffReadString(pbData, cbData, &iData, &sczPackage); 2931 hr = BuffReadString(pbData, cbData, &iData, &sczPackage);
2865 ExitOnFailure(hr, "Failed to read EXE package id."); 2932 ExitOnFailure(hr, "Failed to read EXE package id.");
2866 2933
2867 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action); 2934 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.bundlePackage.action);
2868 ExitOnFailure(hr, "Failed to read action."); 2935 ExitOnFailure(hr, "Failed to read action.");
2869 2936
2870 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); 2937 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
@@ -2882,24 +2949,110 @@ static HRESULT OnExecuteExePackage(
2882 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); 2949 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2883 ExitOnFailure(hr, "Failed to read variables."); 2950 ExitOnFailure(hr, "Failed to read variables.");
2884 2951
2885 hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage); 2952 hr = PackageFindById(pPackages, sczPackage, &executeAction.bundlePackage.pPackage);
2886 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 2953 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2887 2954
2888 if (BURN_PACKAGE_TYPE_EXE != executeAction.exePackage.pPackage->type) 2955 if (BURN_PACKAGE_TYPE_BUNDLE != executeAction.bundlePackage.pPackage->type)
2889 { 2956 {
2890 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage); 2957 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not a BUNDLE package: %ls", sczPackage);
2891 } 2958 }
2892 2959
2893 // Pass the list of dependencies to ignore, if any, to the related bundle. 2960 // Pass the list of dependencies to ignore, if any, to the related bundle.
2894 if (sczIgnoreDependencies && *sczIgnoreDependencies) 2961 if (sczIgnoreDependencies && *sczIgnoreDependencies)
2895 { 2962 {
2896 hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0); 2963 hr = StrAllocString(&executeAction.bundlePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2897 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); 2964 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
2898 } 2965 }
2899 2966
2900 // Pass the list of ancestors, if any, to the related bundle. 2967 // Pass the list of ancestors, if any, to the related bundle.
2901 if (sczAncestors && *sczAncestors) 2968 if (sczAncestors && *sczAncestors)
2902 { 2969 {
2970 hr = StrAllocString(&executeAction.bundlePackage.sczAncestors, sczAncestors, 0);
2971 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2972 }
2973
2974 if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory)
2975 {
2976 hr = StrAllocString(&executeAction.bundlePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2977 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
2978 }
2979
2980 // Execute BUNDLE package.
2981 hr = BundlePackageEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &bundleRestart);
2982 ExitOnFailure(hr, "Failed to execute BUNDLE package.");
2983
2984LExit:
2985 ReleaseStr(sczEngineWorkingDirectory);
2986 ReleaseStr(sczAncestors);
2987 ReleaseStr(sczIgnoreDependencies);
2988 ReleaseStr(sczPackage);
2989 PlanUninitializeExecuteAction(&executeAction);
2990
2991 if (SUCCEEDED(hr))
2992 {
2993 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == bundleRestart)
2994 {
2995 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
2996 }
2997 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == bundleRestart)
2998 {
2999 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
3000 }
3001 }
3002
3003 return hr;
3004}
3005
3006static HRESULT OnExecuteExePackage(
3007 __in HANDLE hPipe,
3008 __in BURN_CACHE* pCache,
3009 __in BURN_PACKAGES* pPackages,
3010 __in BURN_VARIABLES* pVariables,
3011 __in BYTE* pbData,
3012 __in SIZE_T cbData
3013 )
3014{
3015 HRESULT hr = S_OK;
3016 SIZE_T iData = 0;
3017 LPWSTR sczPackage = NULL;
3018 DWORD dwRollback = 0;
3019 BURN_EXECUTE_ACTION executeAction = { };
3020 LPWSTR sczAncestors = NULL;
3021 LPWSTR sczEngineWorkingDirectory = NULL;
3022 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
3023
3024 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
3025
3026 // Deserialize message data.
3027 hr = BuffReadString(pbData, cbData, &iData, &sczPackage);
3028 ExitOnFailure(hr, "Failed to read EXE package id.");
3029
3030 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action);
3031 ExitOnFailure(hr, "Failed to read action.");
3032
3033 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
3034 ExitOnFailure(hr, "Failed to read rollback.");
3035
3036 hr = BuffReadString(pbData, cbData, &iData, &sczAncestors);
3037 ExitOnFailure(hr, "Failed to read the list of ancestors.");
3038
3039 hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory);
3040 ExitOnFailure(hr, "Failed to read the custom working directory.");
3041
3042 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
3043 ExitOnFailure(hr, "Failed to read variables.");
3044
3045 hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage);
3046 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3047
3048 if (BURN_PACKAGE_TYPE_EXE != executeAction.exePackage.pPackage->type)
3049 {
3050 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage);
3051 }
3052
3053 // Pass the list of ancestors, if any, to the related bundle.
3054 if (sczAncestors && *sczAncestors)
3055 {
2903 hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0); 3056 hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0);
2904 ExitOnFailure(hr, "Failed to allocate the list of ancestors."); 3057 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2905 } 3058 }
@@ -2917,7 +3070,6 @@ static HRESULT OnExecuteExePackage(
2917LExit: 3070LExit:
2918 ReleaseStr(sczEngineWorkingDirectory); 3071 ReleaseStr(sczEngineWorkingDirectory);
2919 ReleaseStr(sczAncestors); 3072 ReleaseStr(sczAncestors);
2920 ReleaseStr(sczIgnoreDependencies);
2921 ReleaseStr(sczPackage); 3073 ReleaseStr(sczPackage);
2922 PlanUninitializeExecuteAction(&executeAction); 3074 PlanUninitializeExecuteAction(&executeAction);
2923 3075
diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h
index c2fa0627..3484057e 100644
--- a/src/burn/engine/elevation.h
+++ b/src/burn/engine/elevation.h
@@ -89,6 +89,15 @@ HRESULT ElevationExecuteRelatedBundle(
89 __in LPVOID pvContext, 89 __in LPVOID pvContext,
90 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 90 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
91 ); 91 );
92HRESULT ElevationExecuteBundlePackage(
93 __in HANDLE hPipe,
94 __in BURN_EXECUTE_ACTION* pExecuteAction,
95 __in BURN_VARIABLES* pVariables,
96 __in BOOL fRollback,
97 __in PFN_GENERICMESSAGEHANDLER pfnGenericExecuteProgress,
98 __in LPVOID pvContext,
99 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
100 );
92HRESULT ElevationExecuteExePackage( 101HRESULT ElevationExecuteExePackage(
93 __in HANDLE hPipe, 102 __in HANDLE hPipe,
94 __in BURN_EXECUTE_ACTION* pExecuteAction, 103 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index 0a2084e5..a287d171 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -91,7 +91,6 @@ extern "C" void ExeEnginePackageUninitialize(
91 ReleaseStr(pPackage->Exe.sczInstallArguments); 91 ReleaseStr(pPackage->Exe.sczInstallArguments);
92 ReleaseStr(pPackage->Exe.sczRepairArguments); 92 ReleaseStr(pPackage->Exe.sczRepairArguments);
93 ReleaseStr(pPackage->Exe.sczUninstallArguments); 93 ReleaseStr(pPackage->Exe.sczUninstallArguments);
94 ReleaseStr(pPackage->Exe.sczIgnoreDependencies);
95 ReleaseMem(pPackage->Exe.rgExitCodes); 94 ReleaseMem(pPackage->Exe.rgExitCodes);
96 95
97 // free command-line arguments 96 // free command-line arguments
@@ -291,12 +290,6 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
291 pAction->exePackage.pPackage = pPackage; 290 pAction->exePackage.pPackage = pPackage;
292 pAction->exePackage.action = pPackage->rollback; 291 pAction->exePackage.action = pPackage->rollback;
293 292
294 if (pPackage->Exe.sczIgnoreDependencies)
295 {
296 hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
297 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
298 }
299
300 if (pPackage->Exe.wzAncestors) 293 if (pPackage->Exe.wzAncestors)
301 { 294 {
302 hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0); 295 hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
@@ -325,12 +318,6 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
325 pAction->exePackage.pPackage = pPackage; 318 pAction->exePackage.pPackage = pPackage;
326 pAction->exePackage.action = pPackage->execute; 319 pAction->exePackage.action = pPackage->execute;
327 320
328 if (pPackage->Exe.sczIgnoreDependencies)
329 {
330 hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
331 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
332 }
333
334 if (pPackage->Exe.wzAncestors) 321 if (pPackage->Exe.wzAncestors)
335 { 322 {
336 hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0); 323 hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
@@ -455,12 +442,11 @@ extern "C" HRESULT ExeEngineExecutePackage(
455 hr = StrAllocConcat(&sczBaseCommand, L" -norestart", 0); 442 hr = StrAllocConcat(&sczBaseCommand, L" -norestart", 0);
456 ExitOnFailure(hr, "Failed to append norestart argument."); 443 ExitOnFailure(hr, "Failed to append norestart argument.");
457 444
458 // Add the list of dependencies to ignore, if any, to the burn command line. 445 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE);
459 if (pExecuteAction->exePackage.sczIgnoreDependencies) 446 ExitOnFailure(hr, "Failed to append the relation type to the command line.");
460 { 447
461 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); 448 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=ALL", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES);
462 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); 449 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
463 }
464 450
465 // Add the list of ancestors, if any, to the burn command line. 451 // Add the list of ancestors, if any, to the burn command line.
466 if (pExecuteAction->exePackage.sczAncestors) 452 if (pExecuteAction->exePackage.sczAncestors)
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index de332f84..a766b896 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -781,6 +781,8 @@ extern "C" LPCSTR LoggingRelationTypeToString(
781 return "DependentPatch"; 781 return "DependentPatch";
782 case BOOTSTRAPPER_RELATION_UPDATE: 782 case BOOTSTRAPPER_RELATION_UPDATE:
783 return "Update"; 783 return "Update";
784 case BOOTSTRAPPER_RELATION_CHAIN_PACKAGE:
785 return "ChainPackage";
784 default: 786 default:
785 return "Invalid"; 787 return "Invalid";
786 } 788 }
diff --git a/src/burn/engine/package.cpp b/src/burn/engine/package.cpp
index 8a80194e..89203ada 100644
--- a/src/burn/engine/package.cpp
+++ b/src/burn/engine/package.cpp
@@ -87,7 +87,7 @@ extern "C" HRESULT PackagesParseFromXml(
87 ReleaseNullObject(pixnNodes); // done with the RollbackBoundary elements. 87 ReleaseNullObject(pixnNodes); // done with the RollbackBoundary elements.
88 88
89 // select package nodes 89 // select package nodes
90 hr = XmlSelectNodes(pixnBundle, L"Chain/ExePackage|Chain/MsiPackage|Chain/MspPackage|Chain/MsuPackage", &pixnNodes); 90 hr = XmlSelectNodes(pixnBundle, L"Chain/BundlePackage|Chain/ExePackage|Chain/MsiPackage|Chain/MspPackage|Chain/MsuPackage", &pixnNodes);
91 ExitOnFailure(hr, "Failed to select package nodes."); 91 ExitOnFailure(hr, "Failed to select package nodes.");
92 92
93 // get package node count 93 // get package node count
@@ -199,7 +199,14 @@ extern "C" HRESULT PackagesParseFromXml(
199 } 199 }
200 200
201 // read type specific attributes 201 // read type specific attributes
202 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"ExePackage", -1)) 202 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"BundlePackage", -1))
203 {
204 pPackage->type = BURN_PACKAGE_TYPE_BUNDLE;
205
206 hr = BundlePackageEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization
207 ExitOnFailure(hr, "Failed to parse BUNDLE package.");
208 }
209 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"ExePackage", -1))
203 { 210 {
204 pPackage->type = BURN_PACKAGE_TYPE_EXE; 211 pPackage->type = BURN_PACKAGE_TYPE_EXE;
205 212
@@ -231,7 +238,7 @@ extern "C" HRESULT PackagesParseFromXml(
231 } 238 }
232 else 239 else
233 { 240 {
234 // ignore other package types for now 241 ExitWithRootFailure(hr, E_UNEXPECTED, "Invalid package type: %ls", bstrNodeName);
235 } 242 }
236 243
237 if (!pPackage->fPermanent) 244 if (!pPackage->fPermanent)
@@ -371,7 +378,7 @@ extern "C" void PackageUninitialize(
371 switch (pPackage->type) 378 switch (pPackage->type)
372 { 379 {
373 case BURN_PACKAGE_TYPE_BUNDLE: 380 case BURN_PACKAGE_TYPE_BUNDLE:
374 BundlePackageEnginePackageUninitialize(pPackage); 381 BundlePackageEnginePackageUninitialize(pPackage); // TODO: Modularization
375 break; 382 break;
376 case BURN_PACKAGE_TYPE_EXE: 383 case BURN_PACKAGE_TYPE_EXE:
377 ExeEnginePackageUninitialize(pPackage); // TODO: Modularization 384 ExeEnginePackageUninitialize(pPackage); // TODO: Modularization
@@ -648,7 +655,6 @@ static HRESULT ParsePatchTargetCode(
648 IXMLDOMNodeList* pixnNodes = NULL; 655 IXMLDOMNodeList* pixnNodes = NULL;
649 IXMLDOMNode* pixnNode = NULL; 656 IXMLDOMNode* pixnNode = NULL;
650 DWORD cNodes = 0; 657 DWORD cNodes = 0;
651 BSTR bstrNodeText = NULL;
652 BOOL fProduct; 658 BOOL fProduct;
653 659
654 hr = XmlSelectNodes(pixnBundle, L"PatchTargetCode", &pixnNodes); 660 hr = XmlSelectNodes(pixnBundle, L"PatchTargetCode", &pixnNodes);
@@ -688,12 +694,10 @@ static HRESULT ParsePatchTargetCode(
688 pTargetCode->type = fProduct ? BURN_PATCH_TARGETCODE_TYPE_PRODUCT : BURN_PATCH_TARGETCODE_TYPE_UPGRADE; 694 pTargetCode->type = fProduct ? BURN_PATCH_TARGETCODE_TYPE_PRODUCT : BURN_PATCH_TARGETCODE_TYPE_UPGRADE;
689 695
690 // prepare next iteration 696 // prepare next iteration
691 ReleaseNullBSTR(bstrNodeText);
692 ReleaseNullObject(pixnNode); 697 ReleaseNullObject(pixnNode);
693 } 698 }
694 699
695LExit: 700LExit:
696 ReleaseBSTR(bstrNodeText);
697 ReleaseObject(pixnNode); 701 ReleaseObject(pixnNode);
698 ReleaseObject(pixnNodes); 702 ReleaseObject(pixnNodes);
699 703
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index deab47b7..c13c651b 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -302,6 +302,8 @@ typedef struct _BURN_PACKAGE
302 { 302 {
303 struct 303 struct
304 { 304 {
305 LPWSTR sczBundleId;
306 LPWSTR sczRegistrationKey;
305 LPWSTR sczInstallArguments; 307 LPWSTR sczInstallArguments;
306 LPWSTR sczRepairArguments; 308 LPWSTR sczRepairArguments;
307 LPWSTR sczUninstallArguments; 309 LPWSTR sczUninstallArguments;
@@ -310,6 +312,7 @@ typedef struct _BURN_PACKAGE
310 LPCWSTR wzAncestors; // points directly into engine state. 312 LPCWSTR wzAncestors; // points directly into engine state.
311 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. 313 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
312 314
315 BOOL fWin64;
313 BOOL fSupportsBurnProtocol; 316 BOOL fSupportsBurnProtocol;
314 317
315 BURN_EXE_EXIT_CODE* rgExitCodes; 318 BURN_EXE_EXIT_CODE* rgExitCodes;
@@ -324,7 +327,6 @@ typedef struct _BURN_PACKAGE
324 LPWSTR sczInstallArguments; 327 LPWSTR sczInstallArguments;
325 LPWSTR sczRepairArguments; 328 LPWSTR sczRepairArguments;
326 LPWSTR sczUninstallArguments; 329 LPWSTR sczUninstallArguments;
327 LPWSTR sczIgnoreDependencies;
328 LPCWSTR wzAncestors; // points directly into engine state. 330 LPCWSTR wzAncestors; // points directly into engine state.
329 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. 331 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
330 332
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index cb50b0c9..1d008dba 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -292,7 +292,6 @@ extern "C" void PlanUninitializeExecuteAction(
292 break; 292 break;
293 293
294 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 294 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
295 ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies);
296 ReleaseStr(pExecuteAction->exePackage.sczAncestors); 295 ReleaseStr(pExecuteAction->exePackage.sczAncestors);
297 ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory); 296 ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory);
298 break; 297 break;
@@ -1181,6 +1180,10 @@ extern "C" HRESULT PlanExecutePackage(
1181 // Add execute actions. 1180 // Add execute actions.
1182 switch (pPackage->type) 1181 switch (pPackage->type)
1183 { 1182 {
1183 case BURN_PACKAGE_TYPE_BUNDLE:
1184 hr = BundlePackageEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables);
1185 break;
1186
1184 case BURN_PACKAGE_TYPE_EXE: 1187 case BURN_PACKAGE_TYPE_EXE:
1185 hr = ExeEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables); 1188 hr = ExeEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables);
1186 break; 1189 break;
@@ -1506,16 +1509,16 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1506 1509
1507 switch (pPlan->rgExecuteActions[i].type) 1510 switch (pPlan->rgExecuteActions[i].type)
1508 { 1511 {
1509 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: 1512 case BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE:
1510 packageAction = pPlan->rgExecuteActions[i].relatedBundle.action; 1513 packageAction = pPlan->rgExecuteActions[i].bundlePackage.action;
1511 pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package; 1514 pPackage = pPlan->rgExecuteActions[i].bundlePackage.pPackage;
1512 fBundle = TRUE; 1515 fBundle = TRUE;
1513 break; 1516 break;
1514 1517
1515 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 1518 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1516 packageAction = pPlan->rgExecuteActions[i].exePackage.action; 1519 packageAction = pPlan->rgExecuteActions[i].exePackage.action;
1517 pPackage = pPlan->rgExecuteActions[i].exePackage.pPackage; 1520 pPackage = pPlan->rgExecuteActions[i].exePackage.pPackage;
1518 fBundle = TRUE; 1521 fBundle = pPackage->Exe.fBundle;
1519 break; 1522 break;
1520 1523
1521 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 1524 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
@@ -2751,6 +2754,10 @@ static HRESULT CalculateExecuteActions(
2751 // Calculate execute actions. 2754 // Calculate execute actions.
2752 switch (pPackage->type) 2755 switch (pPackage->type)
2753 { 2756 {
2757 case BURN_PACKAGE_TYPE_BUNDLE:
2758 hr = BundlePackageEnginePlanCalculatePackage(pPackage);
2759 break;
2760
2754 case BURN_PACKAGE_TYPE_EXE: 2761 case BURN_PACKAGE_TYPE_EXE:
2755 hr = ExeEnginePlanCalculatePackage(pPackage); 2762 hr = ExeEnginePlanCalculatePackage(pPackage);
2756 break; 2763 break;
@@ -2784,7 +2791,8 @@ static BOOL NeedsCache(
2784 ) 2791 )
2785{ 2792{
2786 BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback; 2793 BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback;
2787 if (BURN_PACKAGE_TYPE_EXE == pPackage->type) // Exe packages require the package for all operations (even uninstall). 2794 // TODO: bundles could theoretically use package cache
2795 if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type || BURN_PACKAGE_TYPE_EXE == pPackage->type) // Bundle and Exe packages require the package for all operations (even uninstall).
2788 { 2796 {
2789 return BOOTSTRAPPER_ACTION_STATE_NONE != action; 2797 return BOOTSTRAPPER_ACTION_STATE_NONE != action;
2790 } 2798 }
@@ -2918,6 +2926,10 @@ static void ExecuteActionLog(
2918 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); 2926 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);
2919 break; 2927 break;
2920 2928
2929 case BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE:
2930 LogStringLine(PlanDumpLevel, "%ls action[%u]: BUNDLE_PACKAGE package id: %ls, action: %hs", wzBase, iAction, pAction->bundlePackage.pPackage->sczId, LoggingActionStateToString(pAction->bundlePackage.action));
2931 break;
2932
2921 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 2933 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2922 LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action)); 2934 LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action));
2923 break; 2935 break;
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 6e9a1ff5..5b6ee0fb 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -43,6 +43,7 @@ enum BURN_EXECUTE_ACTION_TYPE
43 BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE, 43 BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE,
44 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE, 44 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE,
45 BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE, 45 BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE,
46 BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE,
46 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, 47 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE,
47 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, 48 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE,
48 BURN_EXECUTE_ACTION_TYPE_MSP_TARGET, 49 BURN_EXECUTE_ACTION_TYPE_MSP_TARGET,
@@ -167,6 +168,13 @@ typedef struct _BURN_EXECUTE_ACTION
167 LPWSTR sczIgnoreDependencies; 168 LPWSTR sczIgnoreDependencies;
168 LPWSTR sczAncestors; 169 LPWSTR sczAncestors;
169 LPWSTR sczEngineWorkingDirectory; 170 LPWSTR sczEngineWorkingDirectory;
171 } bundlePackage;
172 struct
173 {
174 BURN_PACKAGE* pPackage;
175 BOOTSTRAPPER_ACTION_STATE action;
176 LPWSTR sczAncestors;
177 LPWSTR sczEngineWorkingDirectory;
170 } exePackage; 178 } exePackage;
171 struct 179 struct
172 { 180 {
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index a65c30d3..78f8eeb1 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -7,7 +7,6 @@
7 7
8const LPCWSTR REGISTRY_RUN_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; 8const LPCWSTR REGISTRY_RUN_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
9const LPCWSTR REGISTRY_RUN_ONCE_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"; 9const LPCWSTR REGISTRY_RUN_ONCE_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
10const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
11const LPCWSTR REGISTRY_BUNDLE_DISPLAY_ICON = L"DisplayIcon"; 10const LPCWSTR REGISTRY_BUNDLE_DISPLAY_ICON = L"DisplayIcon";
12const LPCWSTR REGISTRY_BUNDLE_DISPLAY_VERSION = L"DisplayVersion"; 11const LPCWSTR REGISTRY_BUNDLE_DISPLAY_VERSION = L"DisplayVersion";
13const LPCWSTR REGISTRY_BUNDLE_ESTIMATED_SIZE = L"EstimatedSize"; 12const LPCWSTR REGISTRY_BUNDLE_ESTIMATED_SIZE = L"EstimatedSize";
@@ -1219,7 +1218,7 @@ static HRESULT SetPaths(
1219 pRegistration->hkRoot = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 1218 pRegistration->hkRoot = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1220 1219
1221 // build uninstall registry key path 1220 // build uninstall registry key path
1222 hr = StrAllocFormatted(&pRegistration->sczRegistrationKey, L"%s\\%s", BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, pRegistration->sczId); 1221 hr = StrAllocFormatted(&pRegistration->sczRegistrationKey, L"%ls\\%ls", BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, pRegistration->sczId);
1223 ExitOnFailure(hr, "Failed to build uninstall registry key path."); 1222 ExitOnFailure(hr, "Failed to build uninstall registry key path.");
1224 1223
1225 // build cache directory 1224 // build cache directory
@@ -1231,7 +1230,7 @@ static HRESULT SetPaths(
1231 ExitOnFailure(hr, "Failed to build cached executable path."); 1230 ExitOnFailure(hr, "Failed to build cached executable path.");
1232 1231
1233 // build state file path 1232 // build state file path
1234 hr = StrAllocFormatted(&pRegistration->sczStateFile, L"%s\\state.rsm", sczCacheDirectory); 1233 hr = StrAllocFormatted(&pRegistration->sczStateFile, L"%ls\\state.rsm", sczCacheDirectory);
1235 ExitOnFailure(hr, "Failed to build state file path."); 1234 ExitOnFailure(hr, "Failed to build state file path.");
1236 1235
1237LExit: 1236LExit:
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h
index e4dd6f4a..58c883da 100644
--- a/src/burn/engine/registration.h
+++ b/src/burn/engine/registration.h
@@ -22,6 +22,8 @@ const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProto
22const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; 22const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey";
23const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag"; 23const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag";
24 24
25const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
26
25enum BURN_RESUME_MODE 27enum BURN_RESUME_MODE
26{ 28{
27 BURN_RESUME_MODE_NONE, 29 BURN_RESUME_MODE_NONE,
diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
index 35415dc3..b0159840 100644
--- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
+++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
@@ -80,6 +80,7 @@
80 <ItemGroup> 80 <ItemGroup>
81 <None Include="TestData\CacheTest\CacheSignatureTest.File" CopyToOutputDirectory="PreserveNewest" /> 81 <None Include="TestData\CacheTest\CacheSignatureTest.File" CopyToOutputDirectory="PreserveNewest" />
82 <None Include="TestData\PlanTest\BasicFunctionality_BundleA_manifest.xml" CopyToOutputDirectory="PreserveNewest" /> 82 <None Include="TestData\PlanTest\BasicFunctionality_BundleA_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
83 <None Include="TestData\PlanTest\BundlePackage_Multiple_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
83 <None Include="TestData\PlanTest\Failure_BundleD_manifest.xml" CopyToOutputDirectory="PreserveNewest" /> 84 <None Include="TestData\PlanTest\Failure_BundleD_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
84 <None Include="TestData\PlanTest\MsiTransaction_BundleAv1_manifest.xml" CopyToOutputDirectory="PreserveNewest" /> 85 <None Include="TestData\PlanTest\MsiTransaction_BundleAv1_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
85 <None Include="TestData\PlanTest\MsuPackageFixture_manifest.xml" CopyToOutputDirectory="PreserveNewest" /> 86 <None Include="TestData\PlanTest\MsuPackageFixture_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 143ca7d7..536e5351 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -10,6 +10,7 @@ static HRESULT WINAPI PlanTestBAProc(
10 ); 10 );
11 11
12static LPCWSTR wzMsiTransactionManifestFileName = L"MsiTransaction_BundleAv1_manifest.xml"; 12static LPCWSTR wzMsiTransactionManifestFileName = L"MsiTransaction_BundleAv1_manifest.xml";
13static LPCWSTR wzMultipleBundlePackageManifestFileName = L"BundlePackage_Multiple_manifest.xml";
13static LPCWSTR wzSingleExeManifestFileName = L"Failure_BundleD_manifest.xml"; 14static LPCWSTR wzSingleExeManifestFileName = L"Failure_BundleD_manifest.xml";
14static LPCWSTR wzSingleMsiManifestFileName = L"BasicFunctionality_BundleA_manifest.xml"; 15static LPCWSTR wzSingleMsiManifestFileName = L"BasicFunctionality_BundleA_manifest.xml";
15static LPCWSTR wzSingleMsuManifestFileName = L"MsuPackageFixture_manifest.xml"; 16static LPCWSTR wzSingleMsuManifestFileName = L"MsuPackageFixture_manifest.xml";
@@ -340,6 +341,121 @@ namespace Bootstrapper
340 } 341 }
341 342
342 [Fact] 343 [Fact]
344 void MultipleBundlePackageInstallTest()
345 {
346 HRESULT hr = S_OK;
347 BURN_ENGINE_STATE engineState = { };
348 BURN_ENGINE_STATE* pEngineState = &engineState;
349 BURN_PLAN* pPlan = &engineState.plan;
350
351 InitializeEngineStateForCorePlan(wzMultipleBundlePackageManifestFileName, pEngineState);
352 DetectAttachedContainerAsAttached(pEngineState);
353 DetectPermanentPackagesAsPresentAndCached(pEngineState);
354
355 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
356 NativeAssert::Succeeded(hr, "CorePlan failed");
357
358 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
359 NativeAssert::StringEqual(L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", pPlan->wzBundleId);
360 NativeAssert::StringEqual(L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", pPlan->wzBundleProviderKey);
361 Assert::Equal<BOOL>(FALSE, pPlan->fEnabledForwardCompatibleBundle);
362 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
363 Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState);
364 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
365 Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval);
366 Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade);
367
368 BOOL fRollback = FALSE;
369 DWORD dwIndex = 0;
370 ValidateDependentRegistrationAction(pPlan, fRollback, dwIndex++, TRUE, L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}");
371 Assert::Equal(dwIndex, pPlan->cRegistrationActions);
372
373 fRollback = TRUE;
374 dwIndex = 0;
375 ValidateDependentRegistrationAction(pPlan, fRollback, dwIndex++, FALSE, L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}");
376 Assert::Equal(dwIndex, pPlan->cRollbackRegistrationActions);
377
378 fRollback = FALSE;
379 dwIndex = 0;
380 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
381 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
382 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
383 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 6);
384 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
385 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
386 Assert::Equal(dwIndex, pPlan->cCacheActions);
387
388 fRollback = TRUE;
389 dwIndex = 0;
390 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
391
392 Assert::Equal(18575450ull, pPlan->qwEstimatedSize);
393 Assert::Equal(78462280ull, pPlan->qwCacheSizeTotal);
394
395 fRollback = FALSE;
396 dwIndex = 0;
397 DWORD dwExecuteCheckpointId = 2;
398 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
399 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
400 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
401 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
402 ValidateExecuteBundlePackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL);
403 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
404 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", registerActions1, 1);
405 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
406 dwExecuteCheckpointId += 1; // cache checkpoints
407 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
408 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
409 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
410 ValidateExecuteBundlePackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL);
411 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
412 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", registerActions1, 1);
413 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
414 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
415 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
416 Assert::Equal(dwIndex, pPlan->cExecuteActions);
417
418 fRollback = TRUE;
419 dwIndex = 0;
420 dwExecuteCheckpointId = 2;
421 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
422 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
423 ValidateExecuteBundlePackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
424 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
425 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", unregisterActions1, 1);
426 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
427 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
428 dwExecuteCheckpointId += 1; // cache checkpoints
429 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
430 ValidateExecuteBundlePackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
431 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
432 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", unregisterActions1, 1);
433 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
434 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
435 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
436 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
437 Assert::Equal(dwIndex, pPlan->cRollbackActions);
438
439 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
440 Assert::Equal(4ul, pPlan->cOverallProgressTicksTotal);
441
442 dwIndex = 0;
443 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
444
445 dwIndex = 0;
446 ValidateCleanAction(pPlan, dwIndex++, L"NetFx48Web");
447 Assert::Equal(dwIndex, pPlan->cCleanActions);
448
449 UINT uIndex = 0;
450 ValidatePlannedProvider(pPlan, uIndex++, L"{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}", NULL);
451 Assert::Equal(uIndex, pPlan->cPlannedProviders);
452
453 Assert::Equal(3ul, pEngineState->packages.cPackages);
454 ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[1], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT);
455 ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[2], L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT);
456 }
457
458 [Fact]
343 void OrphanCompatiblePackageTest() 459 void OrphanCompatiblePackageTest()
344 { 460 {
345 HRESULT hr = S_OK; 461 HRESULT hr = S_OK;
@@ -716,7 +832,7 @@ namespace Bootstrapper
716 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 832 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
717 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA"); 833 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA");
718 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 834 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
719 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); 835 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL);
720 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 836 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
721 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 837 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
722 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 838 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
@@ -727,7 +843,7 @@ namespace Bootstrapper
727 dwExecuteCheckpointId = 2; 843 dwExecuteCheckpointId = 2;
728 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 844 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
729 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 845 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
730 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); 846 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
731 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 847 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
732 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 848 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
733 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 849 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2125,7 +2241,7 @@ namespace Bootstrapper
2125 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2241 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2126 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2242 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2127 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web"); 2243 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2128 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); 2244 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", BOOTSTRAPPER_ACTION_STATE_INSTALL);
2129 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2245 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2130 dwExecuteCheckpointId += 1; // cache checkpoints 2246 dwExecuteCheckpointId += 1; // cache checkpoints
2131 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2247 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2678,20 +2794,33 @@ namespace Bootstrapper
2678 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 2794 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
2679 } 2795 }
2680 2796
2797 void ValidateExecuteBundlePackage(
2798 __in BURN_PLAN* pPlan,
2799 __in BOOL fRollback,
2800 __in DWORD dwIndex,
2801 __in LPCWSTR wzPackageId,
2802 __in BOOTSTRAPPER_ACTION_STATE action
2803 )
2804 {
2805 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
2806 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE, pAction->type);
2807 NativeAssert::StringEqual(wzPackageId, pAction->bundlePackage.pPackage->sczId);
2808 Assert::Equal<DWORD>(action, pAction->bundlePackage.action);
2809 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
2810 }
2811
2681 void ValidateExecuteExePackage( 2812 void ValidateExecuteExePackage(
2682 __in BURN_PLAN* pPlan, 2813 __in BURN_PLAN* pPlan,
2683 __in BOOL fRollback, 2814 __in BOOL fRollback,
2684 __in DWORD dwIndex, 2815 __in DWORD dwIndex,
2685 __in LPCWSTR wzPackageId, 2816 __in LPCWSTR wzPackageId,
2686 __in BOOTSTRAPPER_ACTION_STATE action, 2817 __in BOOTSTRAPPER_ACTION_STATE action
2687 __in LPCWSTR wzIgnoreDependencies
2688 ) 2818 )
2689 { 2819 {
2690 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); 2820 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
2691 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type); 2821 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
2692 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId); 2822 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
2693 Assert::Equal<DWORD>(action, pAction->exePackage.action); 2823 Assert::Equal<DWORD>(action, pAction->exePackage.action);
2694 NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
2695 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 2824 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
2696 } 2825 }
2697 2826
diff --git a/src/burn/test/BurnUnitTest/TestData/PlanTest/BundlePackage_Multiple_manifest.xml b/src/burn/test/BurnUnitTest/TestData/PlanTest/BundlePackage_Multiple_manifest.xml
new file mode 100644
index 00000000..6c60085f
--- /dev/null
+++ b/src/burn/test/BurnUnitTest/TestData/PlanTest/BundlePackage_Multiple_manifest.xml
@@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><BurnManifest xmlns="http://wixtoolset.org/schemas/v4/2008/Burn"><Log PathVariable="WixBundleLog" Prefix="~BundlePackageTests_MultipleBundlePackagesBundle" Extension=".log" /><RelatedBundle Id="{86D214FB-8D74-456C-99B3-6557ECA6159C}" Action="Upgrade" /><Variable Id="TestGroupName" Value="BundlePackageTests" Type="string" Hidden="no" Persisted="no" /><Variable Id="WixBundleInProgressName" Hidden="no" Persisted="yes" /><Variable Id="WixBundleName" Hidden="no" Persisted="yes" /><Variable Id="WixBundleOriginalSource" Hidden="no" Persisted="yes" /><Variable Id="WixBundleOriginalSourceFolder" Hidden="no" Persisted="yes" /><Variable Id="WixBundleLastUsedSource" Hidden="no" Persisted="yes" /><RegistrySearch Id="NETFRAMEWORK45" Variable="NETFRAMEWORK45" Root="HKLM" Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Value="Release" Type="value" VariableType="string" /><UX><Payload Id="WixManagedBootstrapperApplicationHost" FilePath="mbahost.dll" SourcePath="u30" /><Payload Id="payO60IVK4ATGzPpMz3rwVbUWl6DyU" FilePath="WixToolset.Mba.Host.config" SourcePath="u0" /><Payload Id="payxj4zDAKL2NVlz4ohp0GvwFHepyI" FilePath="TestBA.dll" SourcePath="u1" /><Payload Id="pay1hOSAUC8_D633cD2TXpIXCL30OU" FilePath="mbanative.dll" SourcePath="u2" /><Payload Id="payujy6Izl_BlUNfHt2eI.ADfjYAv4" FilePath="WixToolset.Mba.Core.dll" SourcePath="u3" /><Payload Id="payR4EbR4OTDZpPEycWaSSM_gZRBWM" FilePath="mbapreq.thm" SourcePath="u4" /><Payload Id="paylVCy2Ecl8pHPdJTCQZryUG4T9us" FilePath="mbapreq.png" SourcePath="u5" /><Payload Id="payTaG4B_lob1aLcKFaOqSSG3MPMpU" FilePath="mbapreq.wxl" SourcePath="u6" /><Payload Id="payZwIGuiezVTitZOoZKxyh2DdRSGs" FilePath="1028\mbapreq.wxl" SourcePath="u7" /><Payload Id="pay.herBWX.LlOh8jLsx24aWdunV_0" FilePath="1029\mbapreq.wxl" SourcePath="u8" /><Payload Id="pay8DkMszYsoxxdgX14huLDMYXylQg" FilePath="1030\mbapreq.wxl" SourcePath="u9" /><Payload Id="payPaHpoTeOdkW.TK99IDwktNLhTAg" FilePath="1031\mbapreq.wxl" SourcePath="u10" /><Payload Id="pay45AtAzterLTMzZgdxxtuYvaiXwU" FilePath="1032\mbapreq.wxl" SourcePath="u11" /><Payload Id="payA2VEKIqhePyNIEmr14eyH3JoVLc" FilePath="1035\mbapreq.wxl" SourcePath="u12" /><Payload Id="payvre23ObscjzhcaFIifUAkXMdPa8" FilePath="1036\mbapreq.wxl" SourcePath="u13" /><Payload Id="paytxUV3vuBbG2c.a9c.d_sZX2x6wA" FilePath="1038\mbapreq.wxl" SourcePath="u14" /><Payload Id="payYvMWRK9xelo5.sQn7jRkJIaBp9A" FilePath="1040\mbapreq.wxl" SourcePath="u15" /><Payload Id="pay68KKSApyQimbA25t6kSbqhdeH10" FilePath="1041\mbapreq.wxl" SourcePath="u16" /><Payload Id="paypiqxaHpYZqx.9eDVjQrj1igLbRY" FilePath="1042\mbapreq.wxl" SourcePath="u17" /><Payload Id="payTO0YwZzxKpbqdrBVUcVRTu3BFe8" FilePath="1043\mbapreq.wxl" SourcePath="u18" /><Payload Id="payIXg2ldBJukRzhqWolJVOEbTmF34" FilePath="1044\mbapreq.wxl" SourcePath="u19" /><Payload Id="payOHIZbSkIvrpwKkkXI173tv3u3B4" FilePath="1045\mbapreq.wxl" SourcePath="u20" /><Payload Id="payQRQ_UZl_R2UtV0xDXB2yeH2bg3E" FilePath="1046\mbapreq.wxl" SourcePath="u21" /><Payload Id="payhrejLLBfc1i27iN._QPhQ4K337I" FilePath="1049\mbapreq.wxl" SourcePath="u22" /><Payload Id="payqEzaDNzxB68vGp29jgDcCos6dvg" FilePath="1051\mbapreq.wxl" SourcePath="u23" /><Payload Id="paydz8Vk8xSTyYohgGXTSIxWGXL5.Q" FilePath="1053\mbapreq.wxl" SourcePath="u24" /><Payload Id="pay0HRUZTlbC3taSOffJBsEj92Br8Y" FilePath="1055\mbapreq.wxl" SourcePath="u25" /><Payload Id="payIvUOkc_EMH7laMFehefNolV8hZo" FilePath="1060\mbapreq.wxl" SourcePath="u26" /><Payload Id="payLFhOb.rHuk4sW5CYAPMShG0NjGI" FilePath="2052\mbapreq.wxl" SourcePath="u27" /><Payload Id="payqIKCmERK7Nhxx_nNXvRxdKqKDbI" FilePath="2070\mbapreq.wxl" SourcePath="u28" /><Payload Id="payqeWUzIVaEqjuRXN0z8ECC3Y4tCc" FilePath="3082\mbapreq.wxl" SourcePath="u29" /><Payload Id="paylfeHEjJSSTnNzY9QMZM2Ye3Ipy4" FilePath="mbapreq.dll" SourcePath="u31" /><Payload Id="payDPxs6uy8nbky.R7zhir2RRAfc.c" FilePath="WixToolset.Mba.Host.dll" SourcePath="u32" /><Payload Id="uxTxMXPVMXwQrPTMIGa5WGt93w0Ns" FilePath="BootstrapperApplicationData.xml" SourcePath="u33" /><Payload Id="uxYRbgitOs0K878jn5L_z7LdJ21KI" FilePath="BundleExtensionData.xml" SourcePath="u34" /></UX><Container Id="WixAttachedContainer" FileSize="15696370" Hash="0F9966B421400E481D394DB4C4D7F0F92548E5BEB79B98880C926E817E8C1F381EC8A17053E2E66AE7132A3C9ECE441629E6A1FB3452C5C9282280C40252F141" FilePath="MultipleBundlePackagesBundle.exe" AttachedIndex="1" Attached="yes" Primary="yes" /><Payload Id="NetFx48Web" FilePath="redist\ndp48-web.exe" FileSize="1439328" CertificateRootPublicKeyIdentifier="F49F9B33E25E33CCA0BFB15A62B7C29FFAB3880B" CertificateRootThumbprint="ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B" DownloadUrl="https://go.microsoft.com/fwlink/?LinkId=2085155" Packaging="external" SourcePath="redist\ndp48-web.exe" /><Payload Id="PackageA" FilePath="BundleA.exe" FileSize="5241635" Hash="20E1AFF76DE4693CB2876DC6BCCA0152DB16BE49AEDE2CD581C03FC39AB89DEA12BC25CB435F06E4D7D2B4443CE8A8935D5E92E2E49A4981B60A273980E4B29B" Packaging="embedded" SourcePath="a0" Container="WixAttachedContainer" /><Payload Id="PackageB" FilePath="BundleB_x64.exe" FileSize="10450821" Hash="43A58873D61D6E0FA83F6C5266F2F05FEA9BC85D11C195493B7FD9F0B4AA799C1EFCB78D76DCED32124D2EC62A4E7114B62CDE6F0B87E42A7E28CDBB0DA0FF8E" Packaging="embedded" SourcePath="a1" Container="WixAttachedContainer" /><RollbackBoundary Id="WixDefaultBoundary" Vital="yes" Transaction="no" /><Registration Id="{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}" ExecutableName="MultipleBundlePackagesBundle.exe" PerMachine="yes" Tag="" Version="1.0.0.0" ProviderKey="{35192ED0-C70A-49B2-9D12-3B1FA39B5E6F}"><Arp Register="yes" DisplayName="~BundlePackageTests - MultipleBundlePackagesBundle" DisplayVersion="1.0.0.0" /></Registration><Chain><ExePackage Id="NetFx48Web" Cache="remove" CacheId="642721C60D52051C7F3434D8710FE3406A7CFE10B2B39E90EA847719ED1697D7C614F2DF44AD50412B1DF8C98DD78FDC57CA1D047D28C81AC158092E5FB18040" InstallSize="1439328" Size="1439328" PerMachine="yes" Permanent="yes" Vital="yes" RollbackBoundaryForward="WixDefaultBoundary" LogPathVariable="NetFx48WebLog" RollbackLogPathVariable="WixBundleRollbackLog_NetFx48Web" DetectCondition="NETFRAMEWORK45 &gt;= 528040" InstallArguments="/q /norestart /log &quot;[NetFx48WebLog].html&quot;" UninstallArguments="" Uninstallable="no" RepairArguments="" Repairable="no" Protocol="netfx4"><PayloadRef Id="NetFx48Web" /></ExePackage><BundlePackage Id="PackageA" Cache="keep" CacheId="{B39CEE4D-CCD7-4797-BE3A-6613BD1DC4BE}v1.0.0.0" InstallSize="2169" Size="5241635" PerMachine="yes" Permanent="no" Vital="yes" LogPathVariable="WixBundleLog_PackageA" RollbackLogPathVariable="WixBundleRollbackLog_PackageA" BundleId="{B39CEE4D-CCD7-4797-BE3A-6613BD1DC4BE}" InstallArguments="" UninstallArguments="" RepairArguments="" SupportsBurnProtocol="yes" Win64="no"><Provides Key="{B39CEE4D-CCD7-4797-BE3A-6613BD1DC4BE}" Version="1.0.0.0" DisplayName="~BasicFunctionalityTests - BundleA" Imported="yes" /><PayloadRef Id="PackageA" /></BundlePackage><BundlePackage Id="PackageB" Cache="keep" CacheId="{7506235A-7C59-4750-82C7-EB460A87ED3A}v1.0.0.0" InstallSize="1441497" Size="10450821" PerMachine="yes" Permanent="no" Vital="yes" RollbackBoundaryBackward="WixDefaultBoundary" LogPathVariable="WixBundleLog_PackageB" RollbackLogPathVariable="WixBundleRollbackLog_PackageB" BundleId="{7506235A-7C59-4750-82C7-EB460A87ED3A}" InstallArguments="" UninstallArguments="" RepairArguments="" SupportsBurnProtocol="yes" Win64="yes"><Provides Key="{7506235A-7C59-4750-82C7-EB460A87ED3A}" Version="1.0.0.0" DisplayName="~BasicFunctionalityTests - BundleB_x64" Imported="yes" /><PayloadRef Id="PackageB" /></BundlePackage></Chain><CommandLine Variables="upperCase" /></BurnManifest> \ No newline at end of file