aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-02-18 10:44:49 -0600
committerSean Hall <r.sean.hall@gmail.com>2021-02-22 20:25:06 -0600
commitb29af5d005c2cc802aa60a123d435042038ba8ef (patch)
treecb86e61b6abb327f8e1ebc33162acfca28bb89e9
parentdbd55be5e707f07eb044c8c7f13c3dfd246148c0 (diff)
downloadwix-b29af5d005c2cc802aa60a123d435042038ba8ef.tar.gz
wix-b29af5d005c2cc802aa60a123d435042038ba8ef.tar.bz2
wix-b29af5d005c2cc802aa60a123d435042038ba8ef.zip
Get all request states up front before building the plan.
-rw-r--r--src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h19
-rw-r--r--src/engine/core.cpp20
-rw-r--r--src/engine/engine.mc2
-rw-r--r--src/engine/msiengine.cpp62
-rw-r--r--src/engine/msiengine.h7
-rw-r--r--src/engine/mspengine.cpp36
-rw-r--r--src/engine/mspengine.h5
-rw-r--r--src/engine/package.h10
-rw-r--r--src/engine/plan.cpp256
-rw-r--r--src/engine/plan.h5
-rw-r--r--src/engine/userexperience.cpp39
-rw-r--r--src/engine/userexperience.h13
12 files changed, 317 insertions, 157 deletions
diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index 1ba25cd7..0a89b3f4 100644
--- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -142,6 +142,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
142 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPAUSEAUTOMATICUPDATESCOMPLETE, 142 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPAUSEAUTOMATICUPDATESCOMPLETE,
143 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTBEGIN, 143 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTBEGIN,
144 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTCOMPLETE, 144 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTCOMPLETE,
145 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDPACKAGE,
145}; 146};
146 147
147enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION 148enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -885,10 +886,25 @@ struct BA_ONPLANMSIPACKAGE_RESULTS
885 BOOL fDisableExternalUiHandler; 886 BOOL fDisableExternalUiHandler;
886}; 887};
887 888
889struct BA_ONPLANNEDPACKAGE_ARGS
890{
891 DWORD cbSize;
892 LPCWSTR wzPackageId;
893 BOOTSTRAPPER_ACTION_STATE execute;
894 BOOTSTRAPPER_ACTION_STATE rollback;
895};
896
897struct BA_ONPLANNEDPACKAGE_RESULTS
898{
899 DWORD cbSize;
900};
901
888struct BA_ONPLANPACKAGEBEGIN_ARGS 902struct BA_ONPLANPACKAGEBEGIN_ARGS
889{ 903{
890 DWORD cbSize; 904 DWORD cbSize;
891 LPCWSTR wzPackageId; 905 LPCWSTR wzPackageId;
906 BOOTSTRAPPER_PACKAGE_STATE state;
907 BOOL fInstallCondition;
892 BOOTSTRAPPER_REQUEST_STATE recommendedState; 908 BOOTSTRAPPER_REQUEST_STATE recommendedState;
893}; 909};
894 910
@@ -904,10 +920,7 @@ struct BA_ONPLANPACKAGECOMPLETE_ARGS
904 DWORD cbSize; 920 DWORD cbSize;
905 LPCWSTR wzPackageId; 921 LPCWSTR wzPackageId;
906 HRESULT hrStatus; 922 HRESULT hrStatus;
907 BOOTSTRAPPER_PACKAGE_STATE state;
908 BOOTSTRAPPER_REQUEST_STATE requested; 923 BOOTSTRAPPER_REQUEST_STATE requested;
909 BOOTSTRAPPER_ACTION_STATE execute;
910 BOOTSTRAPPER_ACTION_STATE rollback;
911}; 924};
912 925
913struct BA_ONPLANPACKAGECOMPLETE_RESULTS 926struct BA_ONPLANPACKAGECOMPLETE_RESULTS
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index b90d4b92..b68681fb 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -490,7 +490,7 @@ extern "C" HRESULT CorePlan(
490 ExitOnFailure(hr, "Failed to plan the layout of the bundle."); 490 ExitOnFailure(hr, "Failed to plan the layout of the bundle.");
491 491
492 // Plan the packages' layout. 492 // Plan the packages' layout.
493 hr = PlanPackages(&pEngineState->registration, &pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, FALSE, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory, &hSyncpointEvent); 493 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory, &hSyncpointEvent);
494 ExitOnFailure(hr, "Failed to plan packages."); 494 ExitOnFailure(hr, "Failed to plan packages.");
495 } 495 }
496 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) 496 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action)
@@ -529,7 +529,7 @@ extern "C" HRESULT CorePlan(
529 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); 529 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
530 ExitOnFailure(hr, "Failed to plan related bundles."); 530 ExitOnFailure(hr, "Failed to plan related bundles.");
531 531
532 hr = PlanPackages(&pEngineState->registration, &pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->registration.fInstalled, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent); 532 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent);
533 ExitOnFailure(hr, "Failed to plan packages."); 533 ExitOnFailure(hr, "Failed to plan packages.");
534 534
535 // Schedule the update of related bundles last. 535 // Schedule the update of related bundles last.
@@ -538,10 +538,6 @@ extern "C" HRESULT CorePlan(
538 } 538 }
539 } 539 }
540 540
541 // Remove unnecessary actions.
542 hr = PlanFinalizeActions(&pEngineState->plan);
543 ExitOnFailure(hr, "Failed to remove unnecessary actions from plan.");
544
545 if (fContinuePlanning) 541 if (fContinuePlanning)
546 { 542 {
547 // Finally, display all packages and related bundles in the log. 543 // Finally, display all packages and related bundles in the log.
@@ -1814,6 +1810,18 @@ static void LogPackages(
1814 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; 1810 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage];
1815 1811
1816 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); 1812 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState));
1813
1814 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.cFeatures)
1815 {
1816 LogId(REPORT_STANDARD, MSG_PLANNED_MSI_FEATURES, pPackage->Msi.cFeatures, pPackage->sczId);
1817
1818 for (DWORD j = 0; j < pPackage->Msi.cFeatures; ++j)
1819 {
1820 const BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[j];
1821
1822 LogId(REPORT_STANDARD, MSG_PLANNED_MSI_FEATURE, pFeature->sczId, LoggingMsiFeatureStateToString(pFeature->currentState), LoggingMsiFeatureStateToString(pFeature->defaultRequested), LoggingMsiFeatureStateToString(pFeature->requested), LoggingMsiFeatureActionToString(pFeature->execute), LoggingMsiFeatureActionToString(pFeature->rollback));
1823 }
1824 }
1817 } 1825 }
1818 1826
1819 // Display related bundles last if caching, installing, modifying, or repairing. 1827 // Display related bundles last if caching, installing, modifying, or repairing.
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index 8e0a8a66..fb11430b 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -326,7 +326,7 @@ Planned feature: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested:
326 326
327MessageId=204 327MessageId=204
328Severity=Success 328Severity=Success
329SymbolicName=MSG_PLAN_MSI_FEATURES 329SymbolicName=MSG_PLANNED_MSI_FEATURES
330Language=English 330Language=English
331Plan %1!u! msi features for package: %2!ls! 331Plan %1!u! msi features for package: %2!ls!
332. 332.
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index 4fdf2b7a..252a17b7 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -674,13 +674,46 @@ LExit:
674 return hr; 674 return hr;
675} 675}
676 676
677extern "C" HRESULT MsiEnginePlanInitializePackage(
678 __in BURN_PACKAGE* pPackage,
679 __in BURN_VARIABLES* pVariables,
680 __in BURN_USER_EXPERIENCE* pUserExperience
681 )
682{
683 HRESULT hr = S_OK;
684
685 if (pPackage->Msi.cFeatures)
686 {
687 // get feature request states
688 for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i)
689 {
690 BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i];
691
692 // Evaluate feature conditions.
693 hr = EvaluateActionStateConditions(pVariables, pFeature->sczAddLocalCondition, pFeature->sczAddSourceCondition, pFeature->sczAdvertiseCondition, &pFeature->defaultRequested);
694 ExitOnFailure(hr, "Failed to evaluate requested state conditions.");
695
696 hr = EvaluateActionStateConditions(pVariables, pFeature->sczRollbackAddLocalCondition, pFeature->sczRollbackAddSourceCondition, pFeature->sczRollbackAdvertiseCondition, &pFeature->expectedState);
697 ExitOnFailure(hr, "Failed to evaluate expected state conditions.");
698
699 // Remember the default feature requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it.
700 pFeature->requested = pFeature->defaultRequested;
701
702 // Send plan MSI feature message to BA.
703 hr = UserExperienceOnPlanMsiFeature(pUserExperience, pPackage->sczId, pFeature->sczId, &pFeature->requested);
704 ExitOnRootFailure(hr, "BA aborted plan MSI feature.");
705 }
706 }
707
708LExit:
709 return hr;
710}
711
677// 712//
678// PlanCalculate - calculates the execute and rollback state for the requested package state. 713// PlanCalculate - calculates the execute and rollback state for the requested package state.
679// 714//
680extern "C" HRESULT MsiEnginePlanCalculatePackage( 715extern "C" HRESULT MsiEnginePlanCalculatePackage(
681 __in BURN_PACKAGE* pPackage, 716 __in BURN_PACKAGE* pPackage,
682 __in BURN_VARIABLES* pVariables,
683 __in BURN_USER_EXPERIENCE* pUserExperience,
684 __in BOOL fInsideMsiTransaction, 717 __in BOOL fInsideMsiTransaction,
685 __out_opt BOOL* pfBARequestedCache 718 __out_opt BOOL* pfBARequestedCache
686 ) 719 )
@@ -702,38 +735,17 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
702 // If the package is present and we're repairing it. 735 // If the package is present and we're repairing it.
703 BOOL fRepairingPackage = (BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested); 736 BOOL fRepairingPackage = (BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested);
704 737
705 LogId(REPORT_STANDARD, MSG_PLAN_MSI_FEATURES, pPackage->Msi.cFeatures, pPackage->sczId);
706
707 // plan features 738 // plan features
708 for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i) 739 for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i)
709 { 740 {
710 BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i]; 741 BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i];
711 BOOTSTRAPPER_FEATURE_STATE defaultFeatureRequestedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
712 BOOTSTRAPPER_FEATURE_STATE featureRequestedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
713 BOOTSTRAPPER_FEATURE_STATE featureExpectedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
714
715 // Evaluate feature conditions.
716 hr = EvaluateActionStateConditions(pVariables, pFeature->sczAddLocalCondition, pFeature->sczAddSourceCondition, pFeature->sczAdvertiseCondition, &defaultFeatureRequestedState);
717 ExitOnFailure(hr, "Failed to evaluate requested state conditions.");
718
719 hr = EvaluateActionStateConditions(pVariables, pFeature->sczRollbackAddLocalCondition, pFeature->sczRollbackAddSourceCondition, pFeature->sczRollbackAdvertiseCondition, &featureExpectedState);
720 ExitOnFailure(hr, "Failed to evaluate expected state conditions.");
721
722 // Remember the default feature requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it.
723 featureRequestedState = defaultFeatureRequestedState;
724
725 // Send plan MSI feature message to BA.
726 hr = UserExperienceOnPlanMsiFeature(pUserExperience, pPackage->sczId, pFeature->sczId, &featureRequestedState);
727 ExitOnRootFailure(hr, "BA aborted plan MSI feature.");
728 742
729 // Calculate feature actions. 743 // Calculate feature actions.
730 hr = CalculateFeatureAction(pFeature->currentState, featureRequestedState, fRepairingPackage, &pFeature->execute, &fFeatureActionDelta); 744 hr = CalculateFeatureAction(pFeature->currentState, pFeature->requested, fRepairingPackage, &pFeature->execute, &fFeatureActionDelta);
731 ExitOnFailure(hr, "Failed to calculate execute feature state."); 745 ExitOnFailure(hr, "Failed to calculate execute feature state.");
732 746
733 hr = CalculateFeatureAction(featureRequestedState, BOOTSTRAPPER_FEATURE_ACTION_NONE == pFeature->execute ? featureExpectedState : pFeature->currentState, FALSE, &pFeature->rollback, &fRollbackFeatureActionDelta); 747 hr = CalculateFeatureAction(pFeature->requested, BOOTSTRAPPER_FEATURE_ACTION_NONE == pFeature->execute ? pFeature->expectedState : pFeature->currentState, FALSE, &pFeature->rollback, &fRollbackFeatureActionDelta);
734 ExitOnFailure(hr, "Failed to calculate rollback feature state."); 748 ExitOnFailure(hr, "Failed to calculate rollback feature state.");
735
736 LogId(REPORT_STANDARD, MSG_PLANNED_MSI_FEATURE, pFeature->sczId, LoggingMsiFeatureStateToString(pFeature->currentState), LoggingMsiFeatureStateToString(defaultFeatureRequestedState), LoggingMsiFeatureStateToString(featureRequestedState), LoggingMsiFeatureActionToString(pFeature->execute), LoggingMsiFeatureActionToString(pFeature->rollback));
737 } 749 }
738 } 750 }
739 751
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index d1e46da8..b06866cd 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -31,10 +31,13 @@ HRESULT MsiEngineDetectPackage(
31 __in BURN_PACKAGE* pPackage, 31 __in BURN_PACKAGE* pPackage,
32 __in BURN_USER_EXPERIENCE* pUserExperience 32 __in BURN_USER_EXPERIENCE* pUserExperience
33 ); 33 );
34HRESULT MsiEnginePlanCalculatePackage( 34HRESULT MsiEnginePlanInitializePackage(
35 __in BURN_PACKAGE* pPackage, 35 __in BURN_PACKAGE* pPackage,
36 __in BURN_VARIABLES* pVariables, 36 __in BURN_VARIABLES* pVariables,
37 __in BURN_USER_EXPERIENCE* pUserExperience, 37 __in BURN_USER_EXPERIENCE* pUserExperience
38 );
39HRESULT MsiEnginePlanCalculatePackage(
40 __in BURN_PACKAGE* pPackage,
38 __in BOOL fInsideMsiTransaction, 41 __in BOOL fInsideMsiTransaction,
39 __out_opt BOOL* pfBARequestedCache 42 __out_opt BOOL* pfBARequestedCache
40 ); 43 );
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp
index 7f591d82..f742ecef 100644
--- a/src/engine/mspengine.cpp
+++ b/src/engine/mspengine.cpp
@@ -279,12 +279,32 @@ LExit:
279 return hr; 279 return hr;
280} 280}
281 281
282extern "C" HRESULT MspEnginePlanInitializePackage(
283 __in BURN_PACKAGE* pPackage,
284 __in BURN_USER_EXPERIENCE* pUserExperience
285 )
286{
287 HRESULT hr = S_OK;
288
289 for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
290 {
291 BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
292
293 pTargetProduct->requested = pPackage->requested;
294
295 hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &pTargetProduct->requested);
296 ExitOnRootFailure(hr, "BA aborted plan patch target.");
297 }
298
299LExit:
300 return hr;
301}
302
282// 303//
283// PlanCalculate - calculates the execute and rollback state for the requested package state. 304// PlanCalculate - calculates the execute and rollback state for the requested package state.
284// 305//
285extern "C" HRESULT MspEnginePlanCalculatePackage( 306extern "C" HRESULT MspEnginePlanCalculatePackage(
286 __in BURN_PACKAGE* pPackage, 307 __in BURN_PACKAGE* pPackage,
287 __in BURN_USER_EXPERIENCE* pUserExperience,
288 __in BOOL fInsideMsiTransaction, 308 __in BOOL fInsideMsiTransaction,
289 __out BOOL* pfBARequestedCache 309 __out BOOL* pfBARequestedCache
290 ) 310 )
@@ -296,18 +316,14 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
296 { 316 {
297 BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; 317 BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
298 318
299 BOOTSTRAPPER_REQUEST_STATE requested = pPackage->requested;
300 BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE; 319 BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
301 BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 320 BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
302 321
303 hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &requested);
304 ExitOnRootFailure(hr, "BA aborted plan patch target.");
305
306 // Calculate the execute action. 322 // Calculate the execute action.
307 switch (pTargetProduct->patchPackageState) 323 switch (pTargetProduct->patchPackageState)
308 { 324 {
309 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: 325 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
310 switch (requested) 326 switch (pTargetProduct->requested)
311 { 327 {
312 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 328 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
313 execute = BOOTSTRAPPER_ACTION_STATE_REPAIR; 329 execute = BOOTSTRAPPER_ACTION_STATE_REPAIR;
@@ -329,7 +345,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
329 break; 345 break;
330 346
331 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: 347 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
332 switch (requested) 348 switch (pTargetProduct->requested)
333 { 349 {
334 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 350 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
335 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 351 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
@@ -354,7 +370,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
354 switch (pPackage->currentState) 370 switch (pPackage->currentState)
355 { 371 {
356 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: 372 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
357 switch (requested) 373 switch (pTargetProduct->requested)
358 { 374 {
359 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough; 375 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
360 case BOOTSTRAPPER_REQUEST_STATE_ABSENT: 376 case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
@@ -369,7 +385,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
369 385
370 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: __fallthrough; 386 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: __fallthrough;
371 case BOOTSTRAPPER_PACKAGE_STATE_CACHED: 387 case BOOTSTRAPPER_PACKAGE_STATE_CACHED:
372 switch (requested) 388 switch (pTargetProduct->requested)
373 { 389 {
374 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 390 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
375 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 391 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
@@ -408,8 +424,6 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
408 *pfBARequestedCache = fBARequestedCache; 424 *pfBARequestedCache = fBARequestedCache;
409 } 425 }
410 426
411LExit:
412
413 return hr; 427 return hr;
414} 428}
415 429
diff --git a/src/engine/mspengine.h b/src/engine/mspengine.h
index 7cc9a119..7ee01e8e 100644
--- a/src/engine/mspengine.h
+++ b/src/engine/mspengine.h
@@ -32,9 +32,12 @@ HRESULT MspEngineDetectPackage(
32 __in BURN_PACKAGE* pPackage, 32 __in BURN_PACKAGE* pPackage,
33 __in BURN_USER_EXPERIENCE* pUserExperience 33 __in BURN_USER_EXPERIENCE* pUserExperience
34 ); 34 );
35HRESULT MspEnginePlanInitializePackage(
36 __in BURN_PACKAGE* pPackage,
37 __in BURN_USER_EXPERIENCE* pUserExperience
38 );
35HRESULT MspEnginePlanCalculatePackage( 39HRESULT MspEnginePlanCalculatePackage(
36 __in BURN_PACKAGE* pPackage, 40 __in BURN_PACKAGE* pPackage,
37 __in BURN_USER_EXPERIENCE* pUserExperience,
38 __in BOOL fInsideMsiTransaction, 41 __in BOOL fInsideMsiTransaction,
39 __out_opt BOOL* pfBARequestedCache 42 __out_opt BOOL* pfBARequestedCache
40 ); 43 );
diff --git a/src/engine/package.h b/src/engine/package.h
index 71aecd95..a728fcc6 100644
--- a/src/engine/package.h
+++ b/src/engine/package.h
@@ -112,6 +112,7 @@ typedef struct _BURN_MSPTARGETPRODUCT
112 BOOL fSlipstream; 112 BOOL fSlipstream;
113 113
114 BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect. 114 BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect.
115 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan.
115 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. 116 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
116 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. 117 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
117 118
@@ -137,9 +138,12 @@ typedef struct _BURN_MSIFEATURE
137 LPWSTR sczRollbackAddSourceCondition; 138 LPWSTR sczRollbackAddSourceCondition;
138 LPWSTR sczRollbackAdvertiseCondition; 139 LPWSTR sczRollbackAdvertiseCondition;
139 140
140 BOOTSTRAPPER_FEATURE_STATE currentState; // only valid after Detect. 141 BOOTSTRAPPER_FEATURE_STATE currentState; // only valid after Detect.
141 BOOTSTRAPPER_FEATURE_ACTION execute; // only valid during Plan. 142 BOOTSTRAPPER_FEATURE_STATE expectedState; // only valid during Plan.
142 BOOTSTRAPPER_FEATURE_ACTION rollback; // only valid during Plan. 143 BOOTSTRAPPER_FEATURE_STATE defaultRequested; // only valid during Plan.
144 BOOTSTRAPPER_FEATURE_STATE requested; // only valid during Plan.
145 BOOTSTRAPPER_FEATURE_ACTION execute; // only valid during Plan.
146 BOOTSTRAPPER_FEATURE_ACTION rollback; // only valid during Plan.
143} BURN_MSIFEATURE; 147} BURN_MSIFEATURE;
144 148
145typedef struct _BURN_RELATED_MSI 149typedef struct _BURN_RELATED_MSI
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index 99c87163..29adfb42 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -21,6 +21,26 @@ static void ResetPlannedPackageState(
21static void ResetPlannedRollbackBoundaryState( 21static void ResetPlannedRollbackBoundaryState(
22 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary 22 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
23 ); 23 );
24static HRESULT PlanPackagesHelper(
25 __in BURN_PACKAGE* rgPackages,
26 __in DWORD cPackages,
27 __in BOOL fPlanCleanPackages,
28 __in BURN_USER_EXPERIENCE* pUX,
29 __in BURN_PLAN* pPlan,
30 __in BURN_LOGGING* pLog,
31 __in BURN_VARIABLES* pVariables,
32 __in BOOTSTRAPPER_DISPLAY display,
33 __in BOOTSTRAPPER_RELATION_TYPE relationType,
34 __in_z_opt LPCWSTR wzLayoutDirectory,
35 __inout HANDLE* phSyncpointEvent
36 );
37static HRESULT InitializePackage(
38 __in BURN_PLAN* pPlan,
39 __in BURN_USER_EXPERIENCE* pUX,
40 __in BURN_VARIABLES* pVariables,
41 __in BURN_PACKAGE* pPackage,
42 __in BOOTSTRAPPER_RELATION_TYPE relationType
43 );
24static HRESULT ProcessPackage( 44static HRESULT ProcessPackage(
25 __in BOOL fBundlePerMachine, 45 __in BOOL fBundlePerMachine,
26 __in BURN_USER_EXPERIENCE* pUX, 46 __in BURN_USER_EXPERIENCE* pUX,
@@ -29,7 +49,6 @@ static HRESULT ProcessPackage(
29 __in BURN_LOGGING* pLog, 49 __in BURN_LOGGING* pLog,
30 __in BURN_VARIABLES* pVariables, 50 __in BURN_VARIABLES* pVariables,
31 __in BOOTSTRAPPER_DISPLAY display, 51 __in BOOTSTRAPPER_DISPLAY display,
32 __in BOOTSTRAPPER_RELATION_TYPE relationType,
33 __in_z_opt LPCWSTR wzLayoutDirectory, 52 __in_z_opt LPCWSTR wzLayoutDirectory,
34 __inout HANDLE* phSyncpointEvent, 53 __inout HANDLE* phSyncpointEvent,
35 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 54 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
@@ -146,9 +165,7 @@ static HRESULT PlanDependencyActions(
146 __in BURN_PACKAGE* pPackage 165 __in BURN_PACKAGE* pPackage
147 ); 166 );
148static HRESULT CalculateExecuteActions( 167static HRESULT CalculateExecuteActions(
149 __in BURN_USER_EXPERIENCE* pUserExperience,
150 __in BURN_PACKAGE* pPackage, 168 __in BURN_PACKAGE* pPackage,
151 __in BURN_VARIABLES* pVariables,
152 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary, 169 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary,
153 __out_opt BOOL* pfBARequestedCache 170 __out_opt BOOL* pfBARequestedCache
154 ); 171 );
@@ -324,15 +341,13 @@ extern "C" HRESULT PlanDefaultPackageRequestState(
324 __in BOOL fPermanent, 341 __in BOOL fPermanent,
325 __in BURN_CACHE_TYPE cacheType, 342 __in BURN_CACHE_TYPE cacheType,
326 __in BOOTSTRAPPER_ACTION action, 343 __in BOOTSTRAPPER_ACTION action,
327 __in BURN_VARIABLES* pVariables, 344 __in BOOL fInstallCondition,
328 __in_z_opt LPCWSTR wzInstallCondition,
329 __in BOOTSTRAPPER_RELATION_TYPE relationType, 345 __in BOOTSTRAPPER_RELATION_TYPE relationType,
330 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState 346 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState
331 ) 347 )
332{ 348{
333 HRESULT hr = S_OK; 349 HRESULT hr = S_OK;
334 BOOTSTRAPPER_REQUEST_STATE defaultRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 350 BOOTSTRAPPER_REQUEST_STATE defaultRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
335 BOOL fCondition = FALSE;
336 BOOL fFallbackToCache = BURN_CACHE_TYPE_ALWAYS == cacheType && BOOTSTRAPPER_ACTION_UNINSTALL != action && BOOTSTRAPPER_PACKAGE_STATE_CACHED > currentState; 351 BOOL fFallbackToCache = BURN_CACHE_TYPE_ALWAYS == cacheType && BOOTSTRAPPER_ACTION_UNINSTALL != action && BOOTSTRAPPER_PACKAGE_STATE_CACHED > currentState;
337 352
338 // If doing layout, then always default to requesting the file be cached. 353 // If doing layout, then always default to requesting the file be cached.
@@ -373,14 +388,11 @@ extern "C" HRESULT PlanDefaultPackageRequestState(
373 hr = GetActionDefaultRequestState(action, fPermanent, currentState, &defaultRequestState); 388 hr = GetActionDefaultRequestState(action, fPermanent, currentState, &defaultRequestState);
374 ExitOnFailure(hr, "Failed to get default request state for action."); 389 ExitOnFailure(hr, "Failed to get default request state for action.");
375 390
376 // If there is an install condition (and we're doing an install) evaluate the condition 391 // If we're doing an install, use the install condition
377 // to determine whether to use the default request state or make the package absent. 392 // to determine whether to use the default request state or make the package absent.
378 if (BOOTSTRAPPER_ACTION_UNINSTALL != action && wzInstallCondition && *wzInstallCondition) 393 if (BOOTSTRAPPER_ACTION_UNINSTALL != action && !fInstallCondition)
379 { 394 {
380 hr = ConditionEvaluate(pVariables, wzInstallCondition, &fCondition); 395 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
381 ExitOnFailure(hr, "Failed to evaluate install condition.");
382
383 *pRequestState = fCondition ? defaultRequestState : BOOTSTRAPPER_REQUEST_STATE_ABSENT;
384 } 396 }
385 else // just set the package to the default request state. 397 else // just set the package to the default request state.
386 { 398 {
@@ -475,13 +487,11 @@ LExit:
475} 487}
476 488
477extern "C" HRESULT PlanPackages( 489extern "C" HRESULT PlanPackages(
478 __in BURN_REGISTRATION* /*pRegistration*/,
479 __in BURN_USER_EXPERIENCE* pUX, 490 __in BURN_USER_EXPERIENCE* pUX,
480 __in BURN_PACKAGES* pPackages, 491 __in BURN_PACKAGES* pPackages,
481 __in BURN_PLAN* pPlan, 492 __in BURN_PLAN* pPlan,
482 __in BURN_LOGGING* pLog, 493 __in BURN_LOGGING* pLog,
483 __in BURN_VARIABLES* pVariables, 494 __in BURN_VARIABLES* pVariables,
484 __in BOOL /*fBundleInstalled*/,
485 __in BOOTSTRAPPER_DISPLAY display, 495 __in BOOTSTRAPPER_DISPLAY display,
486 __in BOOTSTRAPPER_RELATION_TYPE relationType, 496 __in BOOTSTRAPPER_RELATION_TYPE relationType,
487 __in_z_opt LPCWSTR wzLayoutDirectory, 497 __in_z_opt LPCWSTR wzLayoutDirectory,
@@ -489,39 +499,9 @@ extern "C" HRESULT PlanPackages(
489 ) 499 )
490{ 500{
491 HRESULT hr = S_OK; 501 HRESULT hr = S_OK;
492 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. 502
493 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 503 hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent);
494
495 // Plan the packages.
496 for (DWORD i = 0; i < pPackages->cPackages; ++i)
497 {
498 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackages->cPackages - 1 - i : i;
499 BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage;
500
501 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary);
502 ExitOnFailure(hr, "Failed to process package.");
503 }
504 504
505 // If we still have an open rollback boundary, complete it.
506 if (pRollbackBoundary)
507 {
508 hr = PlanRollbackBoundaryComplete(pPlan);
509 ExitOnFailure(hr, "Failed to plan rollback boundary begin.");
510
511 pRollbackBoundary = NULL;
512 }
513
514 // Plan clean up of packages.
515 for (DWORD i = 0; i < pPackages->cPackages; ++i)
516 {
517 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackages->cPackages - 1 - i : i;
518 BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage;
519
520 hr = PlanCleanPackage(pPlan, pPackage);
521 ExitOnFailure(hr, "Failed to plan clean package.");
522 }
523
524LExit:
525 return hr; 505 return hr;
526} 506}
527 507
@@ -735,24 +715,13 @@ extern "C" HRESULT PlanPassThroughBundle(
735 ) 715 )
736{ 716{
737 HRESULT hr = S_OK; 717 HRESULT hr = S_OK;
738 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
739 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
740 718
741 // Plan passthrough package. 719 // Plan passthrough package.
742 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary); 720 // Passthrough packages are never cleaned up by the calling bundle (they delete themselves when appropriate)
721 // so we don't need to plan clean up.
722 hr = PlanPackagesHelper(pPackage, 1, FALSE, pUX, pPlan, pLog, pVariables, display, relationType, NULL, phSyncpointEvent);
743 ExitOnFailure(hr, "Failed to process passthrough package."); 723 ExitOnFailure(hr, "Failed to process passthrough package.");
744 724
745 // If we still have an open rollback boundary, complete it.
746 if (pRollbackBoundary)
747 {
748 hr = PlanRollbackBoundaryComplete(pPlan);
749 ExitOnFailure(hr, "Failed to plan rollback boundary for passthrough package.");
750 }
751
752 // Notice that the PlanCleanPackage() function is purposefully missing here. Passthrough packages
753 // are never cleaned up by the calling bundle (they delete themselves when appropriate) so we don't
754 // need to plan clean up.
755
756LExit: 725LExit:
757 return hr; 726 return hr;
758} 727}
@@ -769,28 +738,152 @@ extern "C" HRESULT PlanUpdateBundle(
769 ) 738 )
770{ 739{
771 HRESULT hr = S_OK; 740 HRESULT hr = S_OK;
772 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
773 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
774 741
775 // Plan update package. 742 // Plan update package.
776 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary); 743 hr = PlanPackagesHelper(pPackage, 1, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, NULL, phSyncpointEvent);
777 ExitOnFailure(hr, "Failed to process update package."); 744 ExitOnFailure(hr, "Failed to process update package.");
778 745
746LExit:
747 return hr;
748}
749
750static HRESULT PlanPackagesHelper(
751 __in BURN_PACKAGE* rgPackages,
752 __in DWORD cPackages,
753 __in BOOL fPlanCleanPackages,
754 __in BURN_USER_EXPERIENCE* pUX,
755 __in BURN_PLAN* pPlan,
756 __in BURN_LOGGING* pLog,
757 __in BURN_VARIABLES* pVariables,
758 __in BOOTSTRAPPER_DISPLAY display,
759 __in BOOTSTRAPPER_RELATION_TYPE relationType,
760 __in_z_opt LPCWSTR wzLayoutDirectory,
761 __inout HANDLE* phSyncpointEvent
762 )
763{
764 HRESULT hr = S_OK;
765 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
766 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
767
768 // Initialize the packages.
769 for (DWORD i = 0; i < cPackages; ++i)
770 {
771 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
772 BURN_PACKAGE* pPackage = rgPackages + iPackage;
773
774 hr = InitializePackage(pPlan, pUX, pVariables, pPackage, relationType);
775 ExitOnFailure(hr, "Failed to initialize package.");
776 }
777
778 // Initialize the patch targets after all packages, since they could rely on the requested state of packages that are after the patch's package in the chain.
779 for (DWORD i = 0; i < cPackages; ++i)
780 {
781 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
782 BURN_PACKAGE* pPackage = rgPackages + iPackage;
783
784 if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
785 {
786 hr = MspEnginePlanInitializePackage(pPackage, pUX);
787 ExitOnFailure(hr, "Failed to initialize plan package: %ls", pPackage->sczId);
788 }
789 }
790
791 // Plan the packages.
792 for (DWORD i = 0; i < cPackages; ++i)
793 {
794 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
795 BURN_PACKAGE* pPackage = rgPackages + iPackage;
796
797 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary);
798 ExitOnFailure(hr, "Failed to process package.");
799 }
800
779 // If we still have an open rollback boundary, complete it. 801 // If we still have an open rollback boundary, complete it.
780 if (pRollbackBoundary) 802 if (pRollbackBoundary)
781 { 803 {
782 hr = PlanRollbackBoundaryComplete(pPlan); 804 hr = PlanRollbackBoundaryComplete(pPlan);
783 ExitOnFailure(hr, "Failed to plan rollback boundary for update package."); 805 ExitOnFailure(hr, "Failed to plan final rollback boundary complete.");
806
807 pRollbackBoundary = NULL;
784 } 808 }
785 809
786 // Plan clean up of update package. 810 if (fPlanCleanPackages)
787 hr = PlanCleanPackage(pPlan, pPackage); 811 {
788 ExitOnFailure(hr, "Failed to plan clean of update package."); 812 // Plan clean up of packages.
813 for (DWORD i = 0; i < cPackages; ++i)
814 {
815 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
816 BURN_PACKAGE* pPackage = rgPackages + iPackage;
817
818 hr = PlanCleanPackage(pPlan, pPackage);
819 ExitOnFailure(hr, "Failed to plan clean package.");
820 }
821 }
822
823 // Remove unnecessary actions.
824 hr = PlanFinalizeActions(pPlan);
825 ExitOnFailure(hr, "Failed to remove unnecessary actions from plan.");
826
827 // Let the BA know the actions that were planned.
828 for (DWORD i = 0; i < cPackages; ++i)
829 {
830 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
831 BURN_PACKAGE* pPackage = rgPackages + iPackage;
832
833 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback);
834 }
789 835
790LExit: 836LExit:
791 return hr; 837 return hr;
792} 838}
793 839
840static HRESULT InitializePackage(
841 __in BURN_PLAN* pPlan,
842 __in BURN_USER_EXPERIENCE* pUX,
843 __in BURN_VARIABLES* pVariables,
844 __in BURN_PACKAGE* pPackage,
845 __in BOOTSTRAPPER_RELATION_TYPE relationType
846 )
847{
848 HRESULT hr = S_OK;
849 BOOL fInstallCondition = FALSE;
850 BOOL fBeginCalled = FALSE;
851
852 if (pPackage->sczInstallCondition && *pPackage->sczInstallCondition)
853 {
854 hr = ConditionEvaluate(pVariables, pPackage->sczInstallCondition, &fInstallCondition);
855 ExitOnFailure(hr, "Failed to evaluate install condition.");
856 }
857 else
858 {
859 fInstallCondition = TRUE;
860 }
861
862 // Remember the default requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it.
863 hr = PlanDefaultPackageRequestState(pPackage->type, pPackage->currentState, !pPackage->fUninstallable, pPackage->cacheType, pPlan->action, fInstallCondition, relationType, &pPackage->defaultRequested);
864 ExitOnFailure(hr, "Failed to set default package state.");
865
866 pPackage->requested = pPackage->defaultRequested;
867 fBeginCalled = TRUE;
868
869 hr = UserExperienceOnPlanPackageBegin(pUX, pPackage->sczId, pPackage->currentState, fInstallCondition, &pPackage->requested);
870 ExitOnRootFailure(hr, "BA aborted plan package begin.");
871
872 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
873 {
874 hr = MsiEnginePlanInitializePackage(pPackage, pVariables, pUX);
875 ExitOnFailure(hr, "Failed to initialize plan package: %ls", pPackage->sczId);
876 }
877
878LExit:
879 if (fBeginCalled)
880 {
881 UserExperienceOnPlanPackageComplete(pUX, pPackage->sczId, hr, pPackage->requested);
882 }
883
884 return hr;
885}
886
794static HRESULT ProcessPackage( 887static HRESULT ProcessPackage(
795 __in BOOL fBundlePerMachine, 888 __in BOOL fBundlePerMachine,
796 __in BURN_USER_EXPERIENCE* pUX, 889 __in BURN_USER_EXPERIENCE* pUX,
@@ -799,7 +892,6 @@ static HRESULT ProcessPackage(
799 __in BURN_LOGGING* pLog, 892 __in BURN_LOGGING* pLog,
800 __in BURN_VARIABLES* pVariables, 893 __in BURN_VARIABLES* pVariables,
801 __in BOOTSTRAPPER_DISPLAY display, 894 __in BOOTSTRAPPER_DISPLAY display,
802 __in BOOTSTRAPPER_RELATION_TYPE relationType,
803 __in_z_opt LPCWSTR wzLayoutDirectory, 895 __in_z_opt LPCWSTR wzLayoutDirectory,
804 __inout HANDLE* phSyncpointEvent, 896 __inout HANDLE* phSyncpointEvent,
805 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 897 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
@@ -807,17 +899,6 @@ static HRESULT ProcessPackage(
807{ 899{
808 HRESULT hr = S_OK; 900 HRESULT hr = S_OK;
809 BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL; 901 BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL;
810 BOOL fPlanPackageBegan = FALSE;
811
812 // Remember the default requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it.
813 hr = PlanDefaultPackageRequestState(pPackage->type, pPackage->currentState, !pPackage->fUninstallable, pPackage->cacheType, pPlan->action, pVariables, pPackage->sczInstallCondition, relationType, &pPackage->defaultRequested);
814 ExitOnFailure(hr, "Failed to set default package state.");
815
816 pPackage->requested = pPackage->defaultRequested;
817 fPlanPackageBegan = TRUE;
818
819 hr = UserExperienceOnPlanPackageBegin(pUX, pPackage->sczId, &pPackage->requested);
820 ExitOnRootFailure(hr, "BA aborted plan package begin.");
821 902
822 pEffectiveRollbackBoundary = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward; 903 pEffectiveRollbackBoundary = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward;
823 hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary); 904 hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary);
@@ -896,11 +977,6 @@ static HRESULT ProcessPackage(
896 } 977 }
897 978
898LExit: 979LExit:
899 if (fPlanPackageBegan)
900 {
901 UserExperienceOnPlanPackageComplete(pUX, pPackage->sczId, hr, pPackage->currentState, pPackage->requested, pPackage->execute, pPackage->rollback);
902 }
903
904 return hr; 980 return hr;
905} 981}
906 982
@@ -1007,7 +1083,7 @@ extern "C" HRESULT PlanExecutePackage(
1007 HRESULT hr = S_OK; 1083 HRESULT hr = S_OK;
1008 BOOL fBARequestedCache = FALSE; 1084 BOOL fBARequestedCache = FALSE;
1009 1085
1010 hr = CalculateExecuteActions(pUserExperience, pPackage, pVariables, pPlan->pActiveRollbackBoundary, &fBARequestedCache); 1086 hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary, &fBARequestedCache);
1011 ExitOnFailure(hr, "Failed to calculate plan actions for package: %ls", pPackage->sczId); 1087 ExitOnFailure(hr, "Failed to calculate plan actions for package: %ls", pPackage->sczId);
1012 1088
1013 // Calculate package states based on reference count and plan certain dependency actions prior to planning the package execute action. 1089 // Calculate package states based on reference count and plan certain dependency actions prior to planning the package execute action.
@@ -1801,6 +1877,9 @@ static void ResetPlannedPackageState(
1801 { 1877 {
1802 BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i]; 1878 BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i];
1803 1879
1880 pFeature->expectedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
1881 pFeature->defaultRequested = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
1882 pFeature->requested = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
1804 pFeature->execute = BOOTSTRAPPER_FEATURE_ACTION_NONE; 1883 pFeature->execute = BOOTSTRAPPER_FEATURE_ACTION_NONE;
1805 pFeature->rollback = BOOTSTRAPPER_FEATURE_ACTION_NONE; 1884 pFeature->rollback = BOOTSTRAPPER_FEATURE_ACTION_NONE;
1806 } 1885 }
@@ -1811,6 +1890,7 @@ static void ResetPlannedPackageState(
1811 { 1890 {
1812 BURN_MSPTARGETPRODUCT* pTargetProduct = &pPackage->Msp.rgTargetProducts[i]; 1891 BURN_MSPTARGETPRODUCT* pTargetProduct = &pPackage->Msp.rgTargetProducts[i];
1813 1892
1893 pTargetProduct->requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1814 pTargetProduct->execute = BOOTSTRAPPER_ACTION_STATE_NONE; 1894 pTargetProduct->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
1815 pTargetProduct->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 1895 pTargetProduct->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
1816 } 1896 }
@@ -2738,9 +2818,7 @@ LExit:
2738} 2818}
2739 2819
2740static HRESULT CalculateExecuteActions( 2820static HRESULT CalculateExecuteActions(
2741 __in BURN_USER_EXPERIENCE* pUserExperience,
2742 __in BURN_PACKAGE* pPackage, 2821 __in BURN_PACKAGE* pPackage,
2743 __in BURN_VARIABLES* pVariables,
2744 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary, 2822 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary,
2745 __out_opt BOOL* pfBARequestedCache 2823 __out_opt BOOL* pfBARequestedCache
2746 ) 2824 )
@@ -2756,11 +2834,11 @@ static HRESULT CalculateExecuteActions(
2756 break; 2834 break;
2757 2835
2758 case BURN_PACKAGE_TYPE_MSI: 2836 case BURN_PACKAGE_TYPE_MSI:
2759 hr = MsiEnginePlanCalculatePackage(pPackage, pVariables, pUserExperience, fInsideMsiTransaction, pfBARequestedCache); 2837 hr = MsiEnginePlanCalculatePackage(pPackage, fInsideMsiTransaction, pfBARequestedCache);
2760 break; 2838 break;
2761 2839
2762 case BURN_PACKAGE_TYPE_MSP: 2840 case BURN_PACKAGE_TYPE_MSP:
2763 hr = MspEnginePlanCalculatePackage(pPackage, pUserExperience, fInsideMsiTransaction, pfBARequestedCache); 2841 hr = MspEnginePlanCalculatePackage(pPackage, fInsideMsiTransaction, pfBARequestedCache);
2764 break; 2842 break;
2765 2843
2766 case BURN_PACKAGE_TYPE_MSU: 2844 case BURN_PACKAGE_TYPE_MSU:
diff --git a/src/engine/plan.h b/src/engine/plan.h
index 2f6c9dd3..23e4e312 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -382,8 +382,7 @@ HRESULT PlanDefaultPackageRequestState(
382 __in BOOL fPermanent, 382 __in BOOL fPermanent,
383 __in BURN_CACHE_TYPE cacheType, 383 __in BURN_CACHE_TYPE cacheType,
384 __in BOOTSTRAPPER_ACTION action, 384 __in BOOTSTRAPPER_ACTION action,
385 __in BURN_VARIABLES* pVariables, 385 __in BOOL fInstallCondition,
386 __in_z_opt LPCWSTR wzInstallCondition,
387 __in BOOTSTRAPPER_RELATION_TYPE relationType, 386 __in BOOTSTRAPPER_RELATION_TYPE relationType,
388 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState 387 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState
389 ); 388 );
@@ -396,13 +395,11 @@ HRESULT PlanLayoutBundle(
396 __out_z LPWSTR* psczLayoutDirectory 395 __out_z LPWSTR* psczLayoutDirectory
397 ); 396 );
398HRESULT PlanPackages( 397HRESULT PlanPackages(
399 __in BURN_REGISTRATION* pRegistration,
400 __in BURN_USER_EXPERIENCE* pUX, 398 __in BURN_USER_EXPERIENCE* pUX,
401 __in BURN_PACKAGES* pPackages, 399 __in BURN_PACKAGES* pPackages,
402 __in BURN_PLAN* pPlan, 400 __in BURN_PLAN* pPlan,
403 __in BURN_LOGGING* pLog, 401 __in BURN_LOGGING* pLog,
404 __in BURN_VARIABLES* pVariables, 402 __in BURN_VARIABLES* pVariables,
405 __in BOOL fBundleInstalled,
406 __in BOOTSTRAPPER_DISPLAY display, 403 __in BOOTSTRAPPER_DISPLAY display,
407 __in BOOTSTRAPPER_RELATION_TYPE relationType, 404 __in BOOTSTRAPPER_RELATION_TYPE relationType,
408 __in_z_opt LPCWSTR wzLayoutDirectory, 405 __in_z_opt LPCWSTR wzLayoutDirectory,
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp
index 12c3f6df..88b07d68 100644
--- a/src/engine/userexperience.cpp
+++ b/src/engine/userexperience.cpp
@@ -111,7 +111,7 @@ extern "C" HRESULT UserExperienceLoad(
111 args.pCommand = pCommand; 111 args.pCommand = pCommand;
112 args.pfnBootstrapperEngineProc = EngineForApplicationProc; 112 args.pfnBootstrapperEngineProc = EngineForApplicationProc;
113 args.pvBootstrapperEngineProcContext = pEngineContext; 113 args.pvBootstrapperEngineProcContext = pEngineContext;
114 args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 1, 30, 0); 114 args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 2, 18, 0);
115 115
116 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); 116 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS);
117 117
@@ -1606,9 +1606,36 @@ LExit:
1606 return hr; 1606 return hr;
1607} 1607}
1608 1608
1609EXTERN_C BAAPI UserExperienceOnPlannedPackage(
1610 __in BURN_USER_EXPERIENCE* pUserExperience,
1611 __in_z LPCWSTR wzPackageId,
1612 __in BOOTSTRAPPER_ACTION_STATE execute,
1613 __in BOOTSTRAPPER_ACTION_STATE rollback
1614 )
1615{
1616 HRESULT hr = S_OK;
1617 BA_ONPLANNEDPACKAGE_ARGS args = { };
1618 BA_ONPLANNEDPACKAGE_RESULTS results = { };
1619
1620 args.cbSize = sizeof(args);
1621 args.wzPackageId = wzPackageId;
1622 args.execute = execute;
1623 args.rollback = rollback;
1624
1625 results.cbSize = sizeof(results);
1626
1627 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDPACKAGE, &args, &results);
1628 ExitOnFailure(hr, "BA OnPlannedPackage failed.");
1629
1630LExit:
1631 return hr;
1632}
1633
1609EXTERN_C BAAPI UserExperienceOnPlanPackageBegin( 1634EXTERN_C BAAPI UserExperienceOnPlanPackageBegin(
1610 __in BURN_USER_EXPERIENCE* pUserExperience, 1635 __in BURN_USER_EXPERIENCE* pUserExperience,
1611 __in_z LPCWSTR wzPackageId, 1636 __in_z LPCWSTR wzPackageId,
1637 __in BOOTSTRAPPER_PACKAGE_STATE state,
1638 __in BOOL fInstallCondition,
1612 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState 1639 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState
1613 ) 1640 )
1614{ 1641{
@@ -1618,6 +1645,8 @@ EXTERN_C BAAPI UserExperienceOnPlanPackageBegin(
1618 1645
1619 args.cbSize = sizeof(args); 1646 args.cbSize = sizeof(args);
1620 args.wzPackageId = wzPackageId; 1647 args.wzPackageId = wzPackageId;
1648 args.state = state;
1649 args.fInstallCondition = fInstallCondition;
1621 args.recommendedState = *pRequestedState; 1650 args.recommendedState = *pRequestedState;
1622 1651
1623 results.cbSize = sizeof(results); 1652 results.cbSize = sizeof(results);
@@ -1640,10 +1669,7 @@ EXTERN_C BAAPI UserExperienceOnPlanPackageComplete(
1640 __in BURN_USER_EXPERIENCE* pUserExperience, 1669 __in BURN_USER_EXPERIENCE* pUserExperience,
1641 __in_z LPCWSTR wzPackageId, 1670 __in_z LPCWSTR wzPackageId,
1642 __in HRESULT hrStatus, 1671 __in HRESULT hrStatus,
1643 __in BOOTSTRAPPER_PACKAGE_STATE state, 1672 __in BOOTSTRAPPER_REQUEST_STATE requested
1644 __in BOOTSTRAPPER_REQUEST_STATE requested,
1645 __in BOOTSTRAPPER_ACTION_STATE execute,
1646 __in BOOTSTRAPPER_ACTION_STATE rollback
1647 ) 1673 )
1648{ 1674{
1649 HRESULT hr = S_OK; 1675 HRESULT hr = S_OK;
@@ -1653,10 +1679,7 @@ EXTERN_C BAAPI UserExperienceOnPlanPackageComplete(
1653 args.cbSize = sizeof(args); 1679 args.cbSize = sizeof(args);
1654 args.wzPackageId = wzPackageId; 1680 args.wzPackageId = wzPackageId;
1655 args.hrStatus = hrStatus; 1681 args.hrStatus = hrStatus;
1656 args.state = state;
1657 args.requested = requested; 1682 args.requested = requested;
1658 args.execute = execute;
1659 args.rollback = rollback;
1660 1683
1661 results.cbSize = sizeof(results); 1684 results.cbSize = sizeof(results);
1662 1685
diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h
index 930e7268..f02e6279 100644
--- a/src/engine/userexperience.h
+++ b/src/engine/userexperience.h
@@ -372,19 +372,24 @@ BAAPI UserExperienceOnPlanMsiPackage(
372 __inout INSTALLUILEVEL* pUiLevel, 372 __inout INSTALLUILEVEL* pUiLevel,
373 __inout BOOL* pfDisableExternalUiHandler 373 __inout BOOL* pfDisableExternalUiHandler
374 ); 374 );
375BAAPI UserExperienceOnPlannedPackage(
376 __in BURN_USER_EXPERIENCE* pUserExperience,
377 __in_z LPCWSTR wzPackageId,
378 __in BOOTSTRAPPER_ACTION_STATE execute,
379 __in BOOTSTRAPPER_ACTION_STATE rollback
380 );
375BAAPI UserExperienceOnPlanPackageBegin( 381BAAPI UserExperienceOnPlanPackageBegin(
376 __in BURN_USER_EXPERIENCE* pUserExperience, 382 __in BURN_USER_EXPERIENCE* pUserExperience,
377 __in_z LPCWSTR wzPackageId, 383 __in_z LPCWSTR wzPackageId,
384 __in BOOTSTRAPPER_PACKAGE_STATE state,
385 __in BOOL fInstallCondition,
378 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState 386 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState
379 ); 387 );
380BAAPI UserExperienceOnPlanPackageComplete( 388BAAPI UserExperienceOnPlanPackageComplete(
381 __in BURN_USER_EXPERIENCE* pUserExperience, 389 __in BURN_USER_EXPERIENCE* pUserExperience,
382 __in_z LPCWSTR wzPackageId, 390 __in_z LPCWSTR wzPackageId,
383 __in HRESULT hrStatus, 391 __in HRESULT hrStatus,
384 __in BOOTSTRAPPER_PACKAGE_STATE state, 392 __in BOOTSTRAPPER_REQUEST_STATE requested
385 __in BOOTSTRAPPER_REQUEST_STATE requested,
386 __in BOOTSTRAPPER_ACTION_STATE execute,
387 __in BOOTSTRAPPER_ACTION_STATE rollback
388 ); 393 );
389BAAPI UserExperienceOnPlanRelatedBundle( 394BAAPI UserExperienceOnPlanRelatedBundle(
390 __in BURN_USER_EXPERIENCE* pUserExperience, 395 __in BURN_USER_EXPERIENCE* pUserExperience,