From b29af5d005c2cc802aa60a123d435042038ba8ef Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Thu, 18 Feb 2021 10:44:49 -0600 Subject: Get all request states up front before building the plan. --- .../inc/BootstrapperApplication.h | 19 +- src/engine/core.cpp | 20 +- src/engine/engine.mc | 2 +- src/engine/msiengine.cpp | 62 +++-- src/engine/msiengine.h | 7 +- src/engine/mspengine.cpp | 36 ++- src/engine/mspengine.h | 5 +- src/engine/package.h | 10 +- src/engine/plan.cpp | 256 ++++++++++++++------- src/engine/plan.h | 5 +- src/engine/userexperience.cpp | 39 +++- src/engine/userexperience.h | 13 +- 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 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPAUSEAUTOMATICUPDATESCOMPLETE, BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTBEGIN, BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTCOMPLETE, + BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDPACKAGE, }; enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION @@ -885,10 +886,25 @@ struct BA_ONPLANMSIPACKAGE_RESULTS BOOL fDisableExternalUiHandler; }; +struct BA_ONPLANNEDPACKAGE_ARGS +{ + DWORD cbSize; + LPCWSTR wzPackageId; + BOOTSTRAPPER_ACTION_STATE execute; + BOOTSTRAPPER_ACTION_STATE rollback; +}; + +struct BA_ONPLANNEDPACKAGE_RESULTS +{ + DWORD cbSize; +}; + struct BA_ONPLANPACKAGEBEGIN_ARGS { DWORD cbSize; LPCWSTR wzPackageId; + BOOTSTRAPPER_PACKAGE_STATE state; + BOOL fInstallCondition; BOOTSTRAPPER_REQUEST_STATE recommendedState; }; @@ -904,10 +920,7 @@ struct BA_ONPLANPACKAGECOMPLETE_ARGS DWORD cbSize; LPCWSTR wzPackageId; HRESULT hrStatus; - BOOTSTRAPPER_PACKAGE_STATE state; BOOTSTRAPPER_REQUEST_STATE requested; - BOOTSTRAPPER_ACTION_STATE execute; - BOOTSTRAPPER_ACTION_STATE rollback; }; struct 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( ExitOnFailure(hr, "Failed to plan the layout of the bundle."); // Plan the packages' layout. - hr = PlanPackages(&pEngineState->registration, &pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, FALSE, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory, &hSyncpointEvent); + hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory, &hSyncpointEvent); ExitOnFailure(hr, "Failed to plan packages."); } else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) @@ -529,7 +529,7 @@ extern "C" HRESULT CorePlan( hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); ExitOnFailure(hr, "Failed to plan related bundles."); - 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); + hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent); ExitOnFailure(hr, "Failed to plan packages."); // Schedule the update of related bundles last. @@ -538,10 +538,6 @@ extern "C" HRESULT CorePlan( } } - // Remove unnecessary actions. - hr = PlanFinalizeActions(&pEngineState->plan); - ExitOnFailure(hr, "Failed to remove unnecessary actions from plan."); - if (fContinuePlanning) { // Finally, display all packages and related bundles in the log. @@ -1814,6 +1810,18 @@ static void LogPackages( const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; 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)); + + if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.cFeatures) + { + LogId(REPORT_STANDARD, MSG_PLANNED_MSI_FEATURES, pPackage->Msi.cFeatures, pPackage->sczId); + + for (DWORD j = 0; j < pPackage->Msi.cFeatures; ++j) + { + const BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[j]; + + LogId(REPORT_STANDARD, MSG_PLANNED_MSI_FEATURE, pFeature->sczId, LoggingMsiFeatureStateToString(pFeature->currentState), LoggingMsiFeatureStateToString(pFeature->defaultRequested), LoggingMsiFeatureStateToString(pFeature->requested), LoggingMsiFeatureActionToString(pFeature->execute), LoggingMsiFeatureActionToString(pFeature->rollback)); + } + } } // 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: MessageId=204 Severity=Success -SymbolicName=MSG_PLAN_MSI_FEATURES +SymbolicName=MSG_PLANNED_MSI_FEATURES Language=English Plan %1!u! msi features for package: %2!ls! . 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: return hr; } +extern "C" HRESULT MsiEnginePlanInitializePackage( + __in BURN_PACKAGE* pPackage, + __in BURN_VARIABLES* pVariables, + __in BURN_USER_EXPERIENCE* pUserExperience + ) +{ + HRESULT hr = S_OK; + + if (pPackage->Msi.cFeatures) + { + // get feature request states + for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i) + { + BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i]; + + // Evaluate feature conditions. + hr = EvaluateActionStateConditions(pVariables, pFeature->sczAddLocalCondition, pFeature->sczAddSourceCondition, pFeature->sczAdvertiseCondition, &pFeature->defaultRequested); + ExitOnFailure(hr, "Failed to evaluate requested state conditions."); + + hr = EvaluateActionStateConditions(pVariables, pFeature->sczRollbackAddLocalCondition, pFeature->sczRollbackAddSourceCondition, pFeature->sczRollbackAdvertiseCondition, &pFeature->expectedState); + ExitOnFailure(hr, "Failed to evaluate expected state conditions."); + + // Remember the default feature requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it. + pFeature->requested = pFeature->defaultRequested; + + // Send plan MSI feature message to BA. + hr = UserExperienceOnPlanMsiFeature(pUserExperience, pPackage->sczId, pFeature->sczId, &pFeature->requested); + ExitOnRootFailure(hr, "BA aborted plan MSI feature."); + } + } + +LExit: + return hr; +} + // // PlanCalculate - calculates the execute and rollback state for the requested package state. // extern "C" HRESULT MsiEnginePlanCalculatePackage( __in BURN_PACKAGE* pPackage, - __in BURN_VARIABLES* pVariables, - __in BURN_USER_EXPERIENCE* pUserExperience, __in BOOL fInsideMsiTransaction, __out_opt BOOL* pfBARequestedCache ) @@ -702,38 +735,17 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( // If the package is present and we're repairing it. BOOL fRepairingPackage = (BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested); - LogId(REPORT_STANDARD, MSG_PLAN_MSI_FEATURES, pPackage->Msi.cFeatures, pPackage->sczId); - // plan features for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i) { BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i]; - BOOTSTRAPPER_FEATURE_STATE defaultFeatureRequestedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; - BOOTSTRAPPER_FEATURE_STATE featureRequestedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; - BOOTSTRAPPER_FEATURE_STATE featureExpectedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; - - // Evaluate feature conditions. - hr = EvaluateActionStateConditions(pVariables, pFeature->sczAddLocalCondition, pFeature->sczAddSourceCondition, pFeature->sczAdvertiseCondition, &defaultFeatureRequestedState); - ExitOnFailure(hr, "Failed to evaluate requested state conditions."); - - hr = EvaluateActionStateConditions(pVariables, pFeature->sczRollbackAddLocalCondition, pFeature->sczRollbackAddSourceCondition, pFeature->sczRollbackAdvertiseCondition, &featureExpectedState); - ExitOnFailure(hr, "Failed to evaluate expected state conditions."); - - // Remember the default feature requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it. - featureRequestedState = defaultFeatureRequestedState; - - // Send plan MSI feature message to BA. - hr = UserExperienceOnPlanMsiFeature(pUserExperience, pPackage->sczId, pFeature->sczId, &featureRequestedState); - ExitOnRootFailure(hr, "BA aborted plan MSI feature."); // Calculate feature actions. - hr = CalculateFeatureAction(pFeature->currentState, featureRequestedState, fRepairingPackage, &pFeature->execute, &fFeatureActionDelta); + hr = CalculateFeatureAction(pFeature->currentState, pFeature->requested, fRepairingPackage, &pFeature->execute, &fFeatureActionDelta); ExitOnFailure(hr, "Failed to calculate execute feature state."); - hr = CalculateFeatureAction(featureRequestedState, BOOTSTRAPPER_FEATURE_ACTION_NONE == pFeature->execute ? featureExpectedState : pFeature->currentState, FALSE, &pFeature->rollback, &fRollbackFeatureActionDelta); + hr = CalculateFeatureAction(pFeature->requested, BOOTSTRAPPER_FEATURE_ACTION_NONE == pFeature->execute ? pFeature->expectedState : pFeature->currentState, FALSE, &pFeature->rollback, &fRollbackFeatureActionDelta); ExitOnFailure(hr, "Failed to calculate rollback feature state."); - - LogId(REPORT_STANDARD, MSG_PLANNED_MSI_FEATURE, pFeature->sczId, LoggingMsiFeatureStateToString(pFeature->currentState), LoggingMsiFeatureStateToString(defaultFeatureRequestedState), LoggingMsiFeatureStateToString(featureRequestedState), LoggingMsiFeatureActionToString(pFeature->execute), LoggingMsiFeatureActionToString(pFeature->rollback)); } } 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( __in BURN_PACKAGE* pPackage, __in BURN_USER_EXPERIENCE* pUserExperience ); -HRESULT MsiEnginePlanCalculatePackage( +HRESULT MsiEnginePlanInitializePackage( __in BURN_PACKAGE* pPackage, __in BURN_VARIABLES* pVariables, - __in BURN_USER_EXPERIENCE* pUserExperience, + __in BURN_USER_EXPERIENCE* pUserExperience + ); +HRESULT MsiEnginePlanCalculatePackage( + __in BURN_PACKAGE* pPackage, __in BOOL fInsideMsiTransaction, __out_opt BOOL* pfBARequestedCache ); 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: return hr; } +extern "C" HRESULT MspEnginePlanInitializePackage( + __in BURN_PACKAGE* pPackage, + __in BURN_USER_EXPERIENCE* pUserExperience + ) +{ + HRESULT hr = S_OK; + + for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) + { + BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; + + pTargetProduct->requested = pPackage->requested; + + hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &pTargetProduct->requested); + ExitOnRootFailure(hr, "BA aborted plan patch target."); + } + +LExit: + return hr; +} + // // PlanCalculate - calculates the execute and rollback state for the requested package state. // extern "C" HRESULT MspEnginePlanCalculatePackage( __in BURN_PACKAGE* pPackage, - __in BURN_USER_EXPERIENCE* pUserExperience, __in BOOL fInsideMsiTransaction, __out BOOL* pfBARequestedCache ) @@ -296,18 +316,14 @@ extern "C" HRESULT MspEnginePlanCalculatePackage( { BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; - BOOTSTRAPPER_REQUEST_STATE requested = pPackage->requested; BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE; BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE; - hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &requested); - ExitOnRootFailure(hr, "BA aborted plan patch target."); - // Calculate the execute action. switch (pTargetProduct->patchPackageState) { case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: - switch (requested) + switch (pTargetProduct->requested) { case BOOTSTRAPPER_REQUEST_STATE_REPAIR: execute = BOOTSTRAPPER_ACTION_STATE_REPAIR; @@ -329,7 +345,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage( break; case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: - switch (requested) + switch (pTargetProduct->requested) { case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; case BOOTSTRAPPER_REQUEST_STATE_REPAIR: @@ -354,7 +370,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage( switch (pPackage->currentState) { case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: - switch (requested) + switch (pTargetProduct->requested) { case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough; case BOOTSTRAPPER_REQUEST_STATE_ABSENT: @@ -369,7 +385,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage( case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: __fallthrough; case BOOTSTRAPPER_PACKAGE_STATE_CACHED: - switch (requested) + switch (pTargetProduct->requested) { case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; case BOOTSTRAPPER_REQUEST_STATE_REPAIR: @@ -408,8 +424,6 @@ extern "C" HRESULT MspEnginePlanCalculatePackage( *pfBARequestedCache = fBARequestedCache; } -LExit: - return hr; } 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( __in BURN_PACKAGE* pPackage, __in BURN_USER_EXPERIENCE* pUserExperience ); +HRESULT MspEnginePlanInitializePackage( + __in BURN_PACKAGE* pPackage, + __in BURN_USER_EXPERIENCE* pUserExperience + ); HRESULT MspEnginePlanCalculatePackage( __in BURN_PACKAGE* pPackage, - __in BURN_USER_EXPERIENCE* pUserExperience, __in BOOL fInsideMsiTransaction, __out_opt BOOL* pfBARequestedCache ); 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 BOOL fSlipstream; BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect. + BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan. BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. @@ -137,9 +138,12 @@ typedef struct _BURN_MSIFEATURE LPWSTR sczRollbackAddSourceCondition; LPWSTR sczRollbackAdvertiseCondition; - BOOTSTRAPPER_FEATURE_STATE currentState; // only valid after Detect. - BOOTSTRAPPER_FEATURE_ACTION execute; // only valid during Plan. - BOOTSTRAPPER_FEATURE_ACTION rollback; // only valid during Plan. + BOOTSTRAPPER_FEATURE_STATE currentState; // only valid after Detect. + BOOTSTRAPPER_FEATURE_STATE expectedState; // only valid during Plan. + BOOTSTRAPPER_FEATURE_STATE defaultRequested; // only valid during Plan. + BOOTSTRAPPER_FEATURE_STATE requested; // only valid during Plan. + BOOTSTRAPPER_FEATURE_ACTION execute; // only valid during Plan. + BOOTSTRAPPER_FEATURE_ACTION rollback; // only valid during Plan. } BURN_MSIFEATURE; typedef 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( static void ResetPlannedRollbackBoundaryState( __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary ); +static HRESULT PlanPackagesHelper( + __in BURN_PACKAGE* rgPackages, + __in DWORD cPackages, + __in BOOL fPlanCleanPackages, + __in BURN_USER_EXPERIENCE* pUX, + __in BURN_PLAN* pPlan, + __in BURN_LOGGING* pLog, + __in BURN_VARIABLES* pVariables, + __in BOOTSTRAPPER_DISPLAY display, + __in BOOTSTRAPPER_RELATION_TYPE relationType, + __in_z_opt LPCWSTR wzLayoutDirectory, + __inout HANDLE* phSyncpointEvent + ); +static HRESULT InitializePackage( + __in BURN_PLAN* pPlan, + __in BURN_USER_EXPERIENCE* pUX, + __in BURN_VARIABLES* pVariables, + __in BURN_PACKAGE* pPackage, + __in BOOTSTRAPPER_RELATION_TYPE relationType + ); static HRESULT ProcessPackage( __in BOOL fBundlePerMachine, __in BURN_USER_EXPERIENCE* pUX, @@ -29,7 +49,6 @@ static HRESULT ProcessPackage( __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z_opt LPCWSTR wzLayoutDirectory, __inout HANDLE* phSyncpointEvent, __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary @@ -146,9 +165,7 @@ static HRESULT PlanDependencyActions( __in BURN_PACKAGE* pPackage ); static HRESULT CalculateExecuteActions( - __in BURN_USER_EXPERIENCE* pUserExperience, __in BURN_PACKAGE* pPackage, - __in BURN_VARIABLES* pVariables, __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary, __out_opt BOOL* pfBARequestedCache ); @@ -324,15 +341,13 @@ extern "C" HRESULT PlanDefaultPackageRequestState( __in BOOL fPermanent, __in BURN_CACHE_TYPE cacheType, __in BOOTSTRAPPER_ACTION action, - __in BURN_VARIABLES* pVariables, - __in_z_opt LPCWSTR wzInstallCondition, + __in BOOL fInstallCondition, __in BOOTSTRAPPER_RELATION_TYPE relationType, __out BOOTSTRAPPER_REQUEST_STATE* pRequestState ) { HRESULT hr = S_OK; BOOTSTRAPPER_REQUEST_STATE defaultRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; - BOOL fCondition = FALSE; BOOL fFallbackToCache = BURN_CACHE_TYPE_ALWAYS == cacheType && BOOTSTRAPPER_ACTION_UNINSTALL != action && BOOTSTRAPPER_PACKAGE_STATE_CACHED > currentState; // If doing layout, then always default to requesting the file be cached. @@ -373,14 +388,11 @@ extern "C" HRESULT PlanDefaultPackageRequestState( hr = GetActionDefaultRequestState(action, fPermanent, currentState, &defaultRequestState); ExitOnFailure(hr, "Failed to get default request state for action."); - // If there is an install condition (and we're doing an install) evaluate the condition + // If we're doing an install, use the install condition // to determine whether to use the default request state or make the package absent. - if (BOOTSTRAPPER_ACTION_UNINSTALL != action && wzInstallCondition && *wzInstallCondition) + if (BOOTSTRAPPER_ACTION_UNINSTALL != action && !fInstallCondition) { - hr = ConditionEvaluate(pVariables, wzInstallCondition, &fCondition); - ExitOnFailure(hr, "Failed to evaluate install condition."); - - *pRequestState = fCondition ? defaultRequestState : BOOTSTRAPPER_REQUEST_STATE_ABSENT; + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; } else // just set the package to the default request state. { @@ -475,13 +487,11 @@ LExit: } extern "C" HRESULT PlanPackages( - __in BURN_REGISTRATION* /*pRegistration*/, __in BURN_USER_EXPERIENCE* pUX, __in BURN_PACKAGES* pPackages, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, - __in BOOL /*fBundleInstalled*/, __in BOOTSTRAPPER_DISPLAY display, __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z_opt LPCWSTR wzLayoutDirectory, @@ -489,39 +499,9 @@ extern "C" HRESULT PlanPackages( ) { HRESULT hr = S_OK; - BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. - BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; - - // Plan the packages. - for (DWORD i = 0; i < pPackages->cPackages; ++i) - { - DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackages->cPackages - 1 - i : i; - BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage; - - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary); - ExitOnFailure(hr, "Failed to process package."); - } + + hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent); - // If we still have an open rollback boundary, complete it. - if (pRollbackBoundary) - { - hr = PlanRollbackBoundaryComplete(pPlan); - ExitOnFailure(hr, "Failed to plan rollback boundary begin."); - - pRollbackBoundary = NULL; - } - - // Plan clean up of packages. - for (DWORD i = 0; i < pPackages->cPackages; ++i) - { - DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackages->cPackages - 1 - i : i; - BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage; - - hr = PlanCleanPackage(pPlan, pPackage); - ExitOnFailure(hr, "Failed to plan clean package."); - } - -LExit: return hr; } @@ -735,24 +715,13 @@ extern "C" HRESULT PlanPassThroughBundle( ) { HRESULT hr = S_OK; - BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. - BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Plan passthrough package. - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary); + // Passthrough packages are never cleaned up by the calling bundle (they delete themselves when appropriate) + // so we don't need to plan clean up. + hr = PlanPackagesHelper(pPackage, 1, FALSE, pUX, pPlan, pLog, pVariables, display, relationType, NULL, phSyncpointEvent); ExitOnFailure(hr, "Failed to process passthrough package."); - // If we still have an open rollback boundary, complete it. - if (pRollbackBoundary) - { - hr = PlanRollbackBoundaryComplete(pPlan); - ExitOnFailure(hr, "Failed to plan rollback boundary for passthrough package."); - } - - // Notice that the PlanCleanPackage() function is purposefully missing here. Passthrough packages - // are never cleaned up by the calling bundle (they delete themselves when appropriate) so we don't - // need to plan clean up. - LExit: return hr; } @@ -769,28 +738,152 @@ extern "C" HRESULT PlanUpdateBundle( ) { HRESULT hr = S_OK; - BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. - BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Plan update package. - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary); + hr = PlanPackagesHelper(pPackage, 1, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, NULL, phSyncpointEvent); ExitOnFailure(hr, "Failed to process update package."); +LExit: + return hr; +} + +static HRESULT PlanPackagesHelper( + __in BURN_PACKAGE* rgPackages, + __in DWORD cPackages, + __in BOOL fPlanCleanPackages, + __in BURN_USER_EXPERIENCE* pUX, + __in BURN_PLAN* pPlan, + __in BURN_LOGGING* pLog, + __in BURN_VARIABLES* pVariables, + __in BOOTSTRAPPER_DISPLAY display, + __in BOOTSTRAPPER_RELATION_TYPE relationType, + __in_z_opt LPCWSTR wzLayoutDirectory, + __inout HANDLE* phSyncpointEvent + ) +{ + HRESULT hr = S_OK; + BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. + BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; + + // Initialize the packages. + for (DWORD i = 0; i < cPackages; ++i) + { + DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; + BURN_PACKAGE* pPackage = rgPackages + iPackage; + + hr = InitializePackage(pPlan, pUX, pVariables, pPackage, relationType); + ExitOnFailure(hr, "Failed to initialize package."); + } + + // 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. + for (DWORD i = 0; i < cPackages; ++i) + { + DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; + BURN_PACKAGE* pPackage = rgPackages + iPackage; + + if (BURN_PACKAGE_TYPE_MSP == pPackage->type) + { + hr = MspEnginePlanInitializePackage(pPackage, pUX); + ExitOnFailure(hr, "Failed to initialize plan package: %ls", pPackage->sczId); + } + } + + // Plan the packages. + for (DWORD i = 0; i < cPackages; ++i) + { + DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; + BURN_PACKAGE* pPackage = rgPackages + iPackage; + + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary); + ExitOnFailure(hr, "Failed to process package."); + } + // If we still have an open rollback boundary, complete it. if (pRollbackBoundary) { hr = PlanRollbackBoundaryComplete(pPlan); - ExitOnFailure(hr, "Failed to plan rollback boundary for update package."); + ExitOnFailure(hr, "Failed to plan final rollback boundary complete."); + + pRollbackBoundary = NULL; } - // Plan clean up of update package. - hr = PlanCleanPackage(pPlan, pPackage); - ExitOnFailure(hr, "Failed to plan clean of update package."); + if (fPlanCleanPackages) + { + // Plan clean up of packages. + for (DWORD i = 0; i < cPackages; ++i) + { + DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; + BURN_PACKAGE* pPackage = rgPackages + iPackage; + + hr = PlanCleanPackage(pPlan, pPackage); + ExitOnFailure(hr, "Failed to plan clean package."); + } + } + + // Remove unnecessary actions. + hr = PlanFinalizeActions(pPlan); + ExitOnFailure(hr, "Failed to remove unnecessary actions from plan."); + + // Let the BA know the actions that were planned. + for (DWORD i = 0; i < cPackages; ++i) + { + DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; + BURN_PACKAGE* pPackage = rgPackages + iPackage; + + UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback); + } LExit: return hr; } +static HRESULT InitializePackage( + __in BURN_PLAN* pPlan, + __in BURN_USER_EXPERIENCE* pUX, + __in BURN_VARIABLES* pVariables, + __in BURN_PACKAGE* pPackage, + __in BOOTSTRAPPER_RELATION_TYPE relationType + ) +{ + HRESULT hr = S_OK; + BOOL fInstallCondition = FALSE; + BOOL fBeginCalled = FALSE; + + if (pPackage->sczInstallCondition && *pPackage->sczInstallCondition) + { + hr = ConditionEvaluate(pVariables, pPackage->sczInstallCondition, &fInstallCondition); + ExitOnFailure(hr, "Failed to evaluate install condition."); + } + else + { + fInstallCondition = TRUE; + } + + // Remember the default requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it. + hr = PlanDefaultPackageRequestState(pPackage->type, pPackage->currentState, !pPackage->fUninstallable, pPackage->cacheType, pPlan->action, fInstallCondition, relationType, &pPackage->defaultRequested); + ExitOnFailure(hr, "Failed to set default package state."); + + pPackage->requested = pPackage->defaultRequested; + fBeginCalled = TRUE; + + hr = UserExperienceOnPlanPackageBegin(pUX, pPackage->sczId, pPackage->currentState, fInstallCondition, &pPackage->requested); + ExitOnRootFailure(hr, "BA aborted plan package begin."); + + if (BURN_PACKAGE_TYPE_MSI == pPackage->type) + { + hr = MsiEnginePlanInitializePackage(pPackage, pVariables, pUX); + ExitOnFailure(hr, "Failed to initialize plan package: %ls", pPackage->sczId); + } + +LExit: + if (fBeginCalled) + { + UserExperienceOnPlanPackageComplete(pUX, pPackage->sczId, hr, pPackage->requested); + } + + return hr; +} + static HRESULT ProcessPackage( __in BOOL fBundlePerMachine, __in BURN_USER_EXPERIENCE* pUX, @@ -799,7 +892,6 @@ static HRESULT ProcessPackage( __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z_opt LPCWSTR wzLayoutDirectory, __inout HANDLE* phSyncpointEvent, __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary @@ -807,17 +899,6 @@ static HRESULT ProcessPackage( { HRESULT hr = S_OK; BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL; - BOOL fPlanPackageBegan = FALSE; - - // Remember the default requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it. - hr = PlanDefaultPackageRequestState(pPackage->type, pPackage->currentState, !pPackage->fUninstallable, pPackage->cacheType, pPlan->action, pVariables, pPackage->sczInstallCondition, relationType, &pPackage->defaultRequested); - ExitOnFailure(hr, "Failed to set default package state."); - - pPackage->requested = pPackage->defaultRequested; - fPlanPackageBegan = TRUE; - - hr = UserExperienceOnPlanPackageBegin(pUX, pPackage->sczId, &pPackage->requested); - ExitOnRootFailure(hr, "BA aborted plan package begin."); pEffectiveRollbackBoundary = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward; hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary); @@ -896,11 +977,6 @@ static HRESULT ProcessPackage( } LExit: - if (fPlanPackageBegan) - { - UserExperienceOnPlanPackageComplete(pUX, pPackage->sczId, hr, pPackage->currentState, pPackage->requested, pPackage->execute, pPackage->rollback); - } - return hr; } @@ -1007,7 +1083,7 @@ extern "C" HRESULT PlanExecutePackage( HRESULT hr = S_OK; BOOL fBARequestedCache = FALSE; - hr = CalculateExecuteActions(pUserExperience, pPackage, pVariables, pPlan->pActiveRollbackBoundary, &fBARequestedCache); + hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary, &fBARequestedCache); ExitOnFailure(hr, "Failed to calculate plan actions for package: %ls", pPackage->sczId); // 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( { BURN_MSIFEATURE* pFeature = &pPackage->Msi.rgFeatures[i]; + pFeature->expectedState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; + pFeature->defaultRequested = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; + pFeature->requested = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; pFeature->execute = BOOTSTRAPPER_FEATURE_ACTION_NONE; pFeature->rollback = BOOTSTRAPPER_FEATURE_ACTION_NONE; } @@ -1811,6 +1890,7 @@ static void ResetPlannedPackageState( { BURN_MSPTARGETPRODUCT* pTargetProduct = &pPackage->Msp.rgTargetProducts[i]; + pTargetProduct->requested = BOOTSTRAPPER_REQUEST_STATE_NONE; pTargetProduct->execute = BOOTSTRAPPER_ACTION_STATE_NONE; pTargetProduct->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; } @@ -2738,9 +2818,7 @@ LExit: } static HRESULT CalculateExecuteActions( - __in BURN_USER_EXPERIENCE* pUserExperience, __in BURN_PACKAGE* pPackage, - __in BURN_VARIABLES* pVariables, __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary, __out_opt BOOL* pfBARequestedCache ) @@ -2756,11 +2834,11 @@ static HRESULT CalculateExecuteActions( break; case BURN_PACKAGE_TYPE_MSI: - hr = MsiEnginePlanCalculatePackage(pPackage, pVariables, pUserExperience, fInsideMsiTransaction, pfBARequestedCache); + hr = MsiEnginePlanCalculatePackage(pPackage, fInsideMsiTransaction, pfBARequestedCache); break; case BURN_PACKAGE_TYPE_MSP: - hr = MspEnginePlanCalculatePackage(pPackage, pUserExperience, fInsideMsiTransaction, pfBARequestedCache); + hr = MspEnginePlanCalculatePackage(pPackage, fInsideMsiTransaction, pfBARequestedCache); break; 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( __in BOOL fPermanent, __in BURN_CACHE_TYPE cacheType, __in BOOTSTRAPPER_ACTION action, - __in BURN_VARIABLES* pVariables, - __in_z_opt LPCWSTR wzInstallCondition, + __in BOOL fInstallCondition, __in BOOTSTRAPPER_RELATION_TYPE relationType, __out BOOTSTRAPPER_REQUEST_STATE* pRequestState ); @@ -396,13 +395,11 @@ HRESULT PlanLayoutBundle( __out_z LPWSTR* psczLayoutDirectory ); HRESULT PlanPackages( - __in BURN_REGISTRATION* pRegistration, __in BURN_USER_EXPERIENCE* pUX, __in BURN_PACKAGES* pPackages, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, - __in BOOL fBundleInstalled, __in BOOTSTRAPPER_DISPLAY display, __in BOOTSTRAPPER_RELATION_TYPE relationType, __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( args.pCommand = pCommand; args.pfnBootstrapperEngineProc = EngineForApplicationProc; args.pvBootstrapperEngineProcContext = pEngineContext; - args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 1, 30, 0); + args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 2, 18, 0); results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); @@ -1606,9 +1606,36 @@ LExit: return hr; } +EXTERN_C BAAPI UserExperienceOnPlannedPackage( + __in BURN_USER_EXPERIENCE* pUserExperience, + __in_z LPCWSTR wzPackageId, + __in BOOTSTRAPPER_ACTION_STATE execute, + __in BOOTSTRAPPER_ACTION_STATE rollback + ) +{ + HRESULT hr = S_OK; + BA_ONPLANNEDPACKAGE_ARGS args = { }; + BA_ONPLANNEDPACKAGE_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.wzPackageId = wzPackageId; + args.execute = execute; + args.rollback = rollback; + + results.cbSize = sizeof(results); + + hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDPACKAGE, &args, &results); + ExitOnFailure(hr, "BA OnPlannedPackage failed."); + +LExit: + return hr; +} + EXTERN_C BAAPI UserExperienceOnPlanPackageBegin( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, + __in BOOTSTRAPPER_PACKAGE_STATE state, + __in BOOL fInstallCondition, __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState ) { @@ -1618,6 +1645,8 @@ EXTERN_C BAAPI UserExperienceOnPlanPackageBegin( args.cbSize = sizeof(args); args.wzPackageId = wzPackageId; + args.state = state; + args.fInstallCondition = fInstallCondition; args.recommendedState = *pRequestedState; results.cbSize = sizeof(results); @@ -1640,10 +1669,7 @@ EXTERN_C BAAPI UserExperienceOnPlanPackageComplete( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, __in HRESULT hrStatus, - __in BOOTSTRAPPER_PACKAGE_STATE state, - __in BOOTSTRAPPER_REQUEST_STATE requested, - __in BOOTSTRAPPER_ACTION_STATE execute, - __in BOOTSTRAPPER_ACTION_STATE rollback + __in BOOTSTRAPPER_REQUEST_STATE requested ) { HRESULT hr = S_OK; @@ -1653,10 +1679,7 @@ EXTERN_C BAAPI UserExperienceOnPlanPackageComplete( args.cbSize = sizeof(args); args.wzPackageId = wzPackageId; args.hrStatus = hrStatus; - args.state = state; args.requested = requested; - args.execute = execute; - args.rollback = rollback; results.cbSize = sizeof(results); 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( __inout INSTALLUILEVEL* pUiLevel, __inout BOOL* pfDisableExternalUiHandler ); +BAAPI UserExperienceOnPlannedPackage( + __in BURN_USER_EXPERIENCE* pUserExperience, + __in_z LPCWSTR wzPackageId, + __in BOOTSTRAPPER_ACTION_STATE execute, + __in BOOTSTRAPPER_ACTION_STATE rollback + ); BAAPI UserExperienceOnPlanPackageBegin( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, + __in BOOTSTRAPPER_PACKAGE_STATE state, + __in BOOL fInstallCondition, __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState ); BAAPI UserExperienceOnPlanPackageComplete( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, __in HRESULT hrStatus, - __in BOOTSTRAPPER_PACKAGE_STATE state, - __in BOOTSTRAPPER_REQUEST_STATE requested, - __in BOOTSTRAPPER_ACTION_STATE execute, - __in BOOTSTRAPPER_ACTION_STATE rollback + __in BOOTSTRAPPER_REQUEST_STATE requested ); BAAPI UserExperienceOnPlanRelatedBundle( __in BURN_USER_EXPERIENCE* pUserExperience, -- cgit v1.2.3-55-g6feb