diff options
Diffstat (limited to 'src/engine/plan.cpp')
| -rw-r--r-- | src/engine/plan.cpp | 287 |
1 files changed, 164 insertions, 123 deletions
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 86a07dfb..b3cb0ee3 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp | |||
| @@ -154,11 +154,15 @@ static void RemoveUnnecessaryActions( | |||
| 154 | __in BURN_EXECUTE_ACTION* rgActions, | 154 | __in BURN_EXECUTE_ACTION* rgActions, |
| 155 | __in DWORD cActions | 155 | __in DWORD cActions |
| 156 | ); | 156 | ); |
| 157 | static HRESULT FinalizeSlipstreamPatchActions( | 157 | static void FinalizePatchActions( |
| 158 | __in BOOL fExecute, | 158 | __in BOOL fExecute, |
| 159 | __in BURN_EXECUTE_ACTION* rgActions, | 159 | __in BURN_EXECUTE_ACTION* rgActions, |
| 160 | __in DWORD cActions | 160 | __in DWORD cActions |
| 161 | ); | 161 | ); |
| 162 | static void CalculateExpectedRegistrationStates( | ||
| 163 | __in BURN_PACKAGE* rgPackages, | ||
| 164 | __in DWORD cPackages | ||
| 165 | ); | ||
| 162 | static HRESULT PlanDependencyActions( | 166 | static HRESULT PlanDependencyActions( |
| 163 | __in BOOL fBundlePerMachine, | 167 | __in BOOL fBundlePerMachine, |
| 164 | __in BURN_PLAN* pPlan, | 168 | __in BURN_PLAN* pPlan, |
| @@ -301,7 +305,6 @@ extern "C" void PlanUninitializeExecuteAction( | |||
| 301 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: | 305 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: |
| 302 | ReleaseStr(pExecuteAction->msiPackage.sczLogPath); | 306 | ReleaseStr(pExecuteAction->msiPackage.sczLogPath); |
| 303 | ReleaseMem(pExecuteAction->msiPackage.rgFeatures); | 307 | ReleaseMem(pExecuteAction->msiPackage.rgFeatures); |
| 304 | ReleaseMem(pExecuteAction->msiPackage.rgSlipstreamPatches); | ||
| 305 | break; | 308 | break; |
| 306 | 309 | ||
| 307 | case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: | 310 | case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: |
| @@ -823,6 +826,8 @@ static HRESULT PlanPackagesHelper( | |||
| 823 | hr = PlanFinalizeActions(pPlan); | 826 | hr = PlanFinalizeActions(pPlan); |
| 824 | ExitOnFailure(hr, "Failed to remove unnecessary actions from plan."); | 827 | ExitOnFailure(hr, "Failed to remove unnecessary actions from plan."); |
| 825 | 828 | ||
| 829 | CalculateExpectedRegistrationStates(rgPackages, cPackages); | ||
| 830 | |||
| 826 | // Let the BA know the actions that were planned. | 831 | // Let the BA know the actions that were planned. |
| 827 | for (DWORD i = 0; i < cPackages; ++i) | 832 | for (DWORD i = 0; i < cPackages; ++i) |
| 828 | { | 833 | { |
| @@ -848,6 +853,12 @@ static HRESULT InitializePackage( | |||
| 848 | BOOL fInstallCondition = FALSE; | 853 | BOOL fInstallCondition = FALSE; |
| 849 | BOOL fBeginCalled = FALSE; | 854 | BOOL fBeginCalled = FALSE; |
| 850 | 855 | ||
| 856 | if (pPackage->fCanAffectRegistration) | ||
| 857 | { | ||
| 858 | pPackage->expectedCacheRegistrationState = pPackage->cacheRegistrationState; | ||
| 859 | pPackage->expectedInstallRegistrationState = pPackage->installRegistrationState; | ||
| 860 | } | ||
| 861 | |||
| 851 | if (pPackage->sczInstallCondition && *pPackage->sczInstallCondition) | 862 | if (pPackage->sczInstallCondition && *pPackage->sczInstallCondition) |
| 852 | { | 863 | { |
| 853 | hr = ConditionEvaluate(pVariables, pPackage->sczInstallCondition, &fInstallCondition); | 864 | hr = ConditionEvaluate(pVariables, pPackage->sczInstallCondition, &fInstallCondition); |
| @@ -903,68 +914,24 @@ static HRESULT ProcessPackage( | |||
| 903 | hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary); | 914 | hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary); |
| 904 | ExitOnFailure(hr, "Failed to process package rollback boundary."); | 915 | ExitOnFailure(hr, "Failed to process package rollback boundary."); |
| 905 | 916 | ||
| 906 | if (pPackage->fCanAffectRegistration) | 917 | if (BOOTSTRAPPER_ACTION_LAYOUT == pPlan->action) |
| 907 | { | 918 | { |
| 908 | pPackage->expectedCacheRegistrationState = pPackage->cacheRegistrationState; | 919 | hr = PlanLayoutPackage(pPlan, pPackage, wzLayoutDirectory); |
| 909 | pPackage->expectedInstallRegistrationState = pPackage->installRegistrationState; | 920 | ExitOnFailure(hr, "Failed to plan layout package."); |
| 910 | } | 921 | } |
| 911 | 922 | else | |
| 912 | // If the package is in a requested state, plan it. | ||
| 913 | if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) | ||
| 914 | { | 923 | { |
| 915 | if (BOOTSTRAPPER_ACTION_LAYOUT == pPlan->action) | 924 | if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) |
| 916 | { | ||
| 917 | hr = PlanLayoutPackage(pPlan, pPackage, wzLayoutDirectory); | ||
| 918 | ExitOnFailure(hr, "Failed to plan layout package."); | ||
| 919 | } | ||
| 920 | else | ||
| 921 | { | 925 | { |
| 926 | // If the package is in a requested state, plan it. | ||
| 922 | hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent); | 927 | hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent); |
| 923 | ExitOnFailure(hr, "Failed to plan execute package."); | 928 | ExitOnFailure(hr, "Failed to plan execute package."); |
| 924 | |||
| 925 | if (pPackage->fCanAffectRegistration) | ||
| 926 | { | ||
| 927 | if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < pPackage->execute) | ||
| 928 | { | ||
| 929 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | ||
| 930 | } | ||
| 931 | else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) | ||
| 932 | { | ||
| 933 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; | ||
| 934 | } | ||
| 935 | } | ||
| 936 | } | ||
| 937 | } | ||
| 938 | else if (BOOTSTRAPPER_ACTION_LAYOUT != pPlan->action) | ||
| 939 | { | ||
| 940 | // Make sure the package is properly ref-counted even if no plan is requested. | ||
| 941 | hr = PlanDependencyActions(fBundlePerMachine, pPlan, pPackage); | ||
| 942 | ExitOnFailure(hr, "Failed to plan dependency actions for package: %ls", pPackage->sczId); | ||
| 943 | } | ||
| 944 | |||
| 945 | if (pPackage->fCanAffectRegistration) | ||
| 946 | { | ||
| 947 | if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute) | ||
| 948 | { | ||
| 949 | if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedCacheRegistrationState) | ||
| 950 | { | ||
| 951 | pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | ||
| 952 | } | ||
| 953 | if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedInstallRegistrationState) | ||
| 954 | { | ||
| 955 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | ||
| 956 | } | ||
| 957 | } | 929 | } |
| 958 | else if (BURN_DEPENDENCY_ACTION_UNREGISTER == pPackage->dependencyExecute) | 930 | else |
| 959 | { | 931 | { |
| 960 | if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedCacheRegistrationState) | 932 | // Make sure the package is properly ref-counted even if no plan is requested. |
| 961 | { | 933 | hr = PlanDependencyActions(fBundlePerMachine, pPlan, pPackage); |
| 962 | pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; | 934 | ExitOnFailure(hr, "Failed to plan dependency actions for package: %ls", pPackage->sczId); |
| 963 | } | ||
| 964 | if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedInstallRegistrationState) | ||
| 965 | { | ||
| 966 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; | ||
| 967 | } | ||
| 968 | } | 935 | } |
| 969 | } | 936 | } |
| 970 | 937 | ||
| @@ -1498,17 +1465,14 @@ extern "C" HRESULT PlanFinalizeActions( | |||
| 1498 | { | 1465 | { |
| 1499 | HRESULT hr = S_OK; | 1466 | HRESULT hr = S_OK; |
| 1500 | 1467 | ||
| 1501 | RemoveUnnecessaryActions(TRUE, pPlan->rgExecuteActions, pPlan->cExecuteActions); | 1468 | FinalizePatchActions(TRUE, pPlan->rgExecuteActions, pPlan->cExecuteActions); |
| 1502 | 1469 | ||
| 1503 | RemoveUnnecessaryActions(FALSE, pPlan->rgRollbackActions, pPlan->cRollbackActions); | 1470 | FinalizePatchActions(FALSE, pPlan->rgRollbackActions, pPlan->cRollbackActions); |
| 1504 | 1471 | ||
| 1505 | hr = FinalizeSlipstreamPatchActions(TRUE, pPlan->rgExecuteActions, pPlan->cExecuteActions); | 1472 | RemoveUnnecessaryActions(TRUE, pPlan->rgExecuteActions, pPlan->cExecuteActions); |
| 1506 | ExitOnFailure(hr, "Failed to finalize slipstream execute actions."); | ||
| 1507 | 1473 | ||
| 1508 | hr = FinalizeSlipstreamPatchActions(FALSE, pPlan->rgRollbackActions, pPlan->cRollbackActions); | 1474 | RemoveUnnecessaryActions(FALSE, pPlan->rgRollbackActions, pPlan->cRollbackActions); |
| 1509 | ExitOnFailure(hr, "Failed to finalize slipstream rollback actions."); | ||
| 1510 | 1475 | ||
| 1511 | LExit: | ||
| 1512 | return hr; | 1476 | return hr; |
| 1513 | } | 1477 | } |
| 1514 | 1478 | ||
| @@ -1868,7 +1832,7 @@ static void ResetPlannedPackageState( | |||
| 1868 | pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; | 1832 | pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; |
| 1869 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; | 1833 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; |
| 1870 | 1834 | ||
| 1871 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.rgFeatures) | 1835 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type) |
| 1872 | { | 1836 | { |
| 1873 | for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i) | 1837 | for (DWORD i = 0; i < pPackage->Msi.cFeatures; ++i) |
| 1874 | { | 1838 | { |
| @@ -1880,6 +1844,14 @@ static void ResetPlannedPackageState( | |||
| 1880 | pFeature->execute = BOOTSTRAPPER_FEATURE_ACTION_NONE; | 1844 | pFeature->execute = BOOTSTRAPPER_FEATURE_ACTION_NONE; |
| 1881 | pFeature->rollback = BOOTSTRAPPER_FEATURE_ACTION_NONE; | 1845 | pFeature->rollback = BOOTSTRAPPER_FEATURE_ACTION_NONE; |
| 1882 | } | 1846 | } |
| 1847 | |||
| 1848 | for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i) | ||
| 1849 | { | ||
| 1850 | BURN_SLIPSTREAM_MSP* pSlipstreamMsp = &pPackage->Msi.rgSlipstreamMsps[i]; | ||
| 1851 | |||
| 1852 | pSlipstreamMsp->execute = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
| 1853 | pSlipstreamMsp->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
| 1854 | } | ||
| 1883 | } | 1855 | } |
| 1884 | else if (BURN_PACKAGE_TYPE_MSP == pPackage->type && pPackage->Msp.rgTargetProducts) | 1856 | else if (BURN_PACKAGE_TYPE_MSP == pPackage->type && pPackage->Msp.rgTargetProducts) |
| 1885 | { | 1857 | { |
| @@ -2716,101 +2688,165 @@ static void RemoveUnnecessaryActions( | |||
| 2716 | { | 2688 | { |
| 2717 | BURN_EXECUTE_ACTION* pAction = rgActions + i; | 2689 | BURN_EXECUTE_ACTION* pAction = rgActions + i; |
| 2718 | 2690 | ||
| 2719 | // If this MSP targets a package in the chain, check the target's execute state | ||
| 2720 | // to see if this patch should be skipped. | ||
| 2721 | if (BURN_EXECUTE_ACTION_TYPE_MSP_TARGET == pAction->type && pAction->mspTarget.pChainedTargetPackage) | 2691 | if (BURN_EXECUTE_ACTION_TYPE_MSP_TARGET == pAction->type && pAction->mspTarget.pChainedTargetPackage) |
| 2722 | { | 2692 | { |
| 2693 | BURN_MSPTARGETPRODUCT* pFirstTargetProduct = pAction->mspTarget.rgOrderedPatches->pTargetProduct; | ||
| 2694 | BURN_PATCH_SKIP_STATE skipState = fExecute ? pFirstTargetProduct->executeSkip : pFirstTargetProduct->rollbackSkip; | ||
| 2723 | BOOTSTRAPPER_ACTION_STATE chainedTargetPackageAction = fExecute ? pAction->mspTarget.pChainedTargetPackage->execute : pAction->mspTarget.pChainedTargetPackage->rollback; | 2695 | BOOTSTRAPPER_ACTION_STATE chainedTargetPackageAction = fExecute ? pAction->mspTarget.pChainedTargetPackage->execute : pAction->mspTarget.pChainedTargetPackage->rollback; |
| 2724 | BURN_PATCH_SKIP_STATE skipState = BURN_PATCH_SKIP_STATE_NONE; | ||
| 2725 | if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == chainedTargetPackageAction) | ||
| 2726 | { | ||
| 2727 | skipState = BURN_PATCH_SKIP_STATE_TARGET_UNINSTALL; | ||
| 2728 | LogId(REPORT_STANDARD, MSG_PLAN_SKIP_PATCH_ACTION, pAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pAction->mspTarget.action), pAction->mspTarget.pChainedTargetPackage->sczId, LoggingActionStateToString(chainedTargetPackageAction), szExecuteOrRollback); | ||
| 2729 | } | ||
| 2730 | else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < chainedTargetPackageAction && pAction->mspTarget.fSlipstream && BOOTSTRAPPER_ACTION_STATE_UNINSTALL < pAction->mspTarget.action) | ||
| 2731 | { | ||
| 2732 | // If the slipstream target is being installed or upgraded (not uninstalled or repaired) then we will slipstream so skip | ||
| 2733 | // this action to install the patch standalone. Also, if the slipstream target is being repaired and the patch is being | ||
| 2734 | // repaired, skip this operation since it will be redundant. | ||
| 2735 | // | ||
| 2736 | // The primary goal here is to ensure that a slipstream patch that is yet not installed is installed even if the MSI | ||
| 2737 | // is already on the machine. The slipstream must be installed standalone if the MSI is being repaired. | ||
| 2738 | if (BOOTSTRAPPER_ACTION_STATE_REPAIR != chainedTargetPackageAction || BOOTSTRAPPER_ACTION_STATE_REPAIR == pAction->mspTarget.action) | ||
| 2739 | { | ||
| 2740 | skipState = BURN_PATCH_SKIP_STATE_SLIPSTREAM; | ||
| 2741 | LogId(REPORT_STANDARD, MSG_PLAN_SKIP_SLIPSTREAM_ACTION, pAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pAction->mspTarget.action), pAction->mspTarget.pChainedTargetPackage->sczId, LoggingActionStateToString(chainedTargetPackageAction), szExecuteOrRollback); | ||
| 2742 | } | ||
| 2743 | } | ||
| 2744 | 2696 | ||
| 2745 | if (BURN_PATCH_SKIP_STATE_NONE != skipState) | 2697 | switch (skipState) |
| 2746 | { | 2698 | { |
| 2699 | case BURN_PATCH_SKIP_STATE_TARGET_UNINSTALL: | ||
| 2747 | pAction->fDeleted = TRUE; | 2700 | pAction->fDeleted = TRUE; |
| 2748 | 2701 | LogId(REPORT_STANDARD, MSG_PLAN_SKIP_PATCH_ACTION, pAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pAction->mspTarget.action), pAction->mspTarget.pChainedTargetPackage->sczId, LoggingActionStateToString(chainedTargetPackageAction), szExecuteOrRollback); | |
| 2749 | for (DWORD j = 0; j < pAction->mspTarget.cOrderedPatches; ++j) | 2702 | break; |
| 2750 | { | 2703 | case BURN_PATCH_SKIP_STATE_SLIPSTREAM: |
| 2751 | BURN_MSPTARGETPRODUCT* pTargetProduct = pAction->mspTarget.rgOrderedPatches[j].pTargetProduct; | 2704 | pAction->fDeleted = TRUE; |
| 2752 | 2705 | LogId(REPORT_STANDARD, MSG_PLAN_SKIP_SLIPSTREAM_ACTION, pAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pAction->mspTarget.action), pAction->mspTarget.pChainedTargetPackage->sczId, LoggingActionStateToString(chainedTargetPackageAction), szExecuteOrRollback); | |
| 2753 | if (fExecute) | 2706 | break; |
| 2754 | { | ||
| 2755 | pTargetProduct->executeSkip = skipState; | ||
| 2756 | } | ||
| 2757 | else | ||
| 2758 | { | ||
| 2759 | pTargetProduct->rollbackSkip = skipState; | ||
| 2760 | } | ||
| 2761 | } | ||
| 2762 | } | 2707 | } |
| 2763 | } | 2708 | } |
| 2764 | } | 2709 | } |
| 2765 | } | 2710 | } |
| 2766 | 2711 | ||
| 2767 | static HRESULT FinalizeSlipstreamPatchActions( | 2712 | static void FinalizePatchActions( |
| 2768 | __in BOOL fExecute, | 2713 | __in BOOL fExecute, |
| 2769 | __in BURN_EXECUTE_ACTION* rgActions, | 2714 | __in BURN_EXECUTE_ACTION* rgActions, |
| 2770 | __in DWORD cActions | 2715 | __in DWORD cActions |
| 2771 | ) | 2716 | ) |
| 2772 | { | 2717 | { |
| 2773 | HRESULT hr = S_OK; | ||
| 2774 | |||
| 2775 | for (DWORD i = 0; i < cActions; ++i) | 2718 | for (DWORD i = 0; i < cActions; ++i) |
| 2776 | { | 2719 | { |
| 2777 | BURN_EXECUTE_ACTION* pAction = rgActions + i; | 2720 | BURN_EXECUTE_ACTION* pAction = rgActions + i; |
| 2778 | 2721 | ||
| 2779 | // If this MSI package contains slipstream patches store the slipstream actions. | 2722 | if (BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE == pAction->type) |
| 2780 | if (BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE == pAction->type && pAction->msiPackage.pPackage->Msi.cSlipstreamMspPackages) | ||
| 2781 | { | 2723 | { |
| 2782 | BURN_PACKAGE* pPackage = pAction->msiPackage.pPackage; | 2724 | BURN_PACKAGE* pPackage = pAction->msiPackage.pPackage; |
| 2725 | AssertSz(BOOTSTRAPPER_ACTION_STATE_NONE < pAction->msiPackage.action, "Planned execute MSI action to do nothing"); | ||
| 2783 | 2726 | ||
| 2784 | // By default all slipstream actions will be initialized to "no action" (aka: 0). | 2727 | if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->msiPackage.action) |
| 2785 | pAction->msiPackage.rgSlipstreamPatches = (BOOTSTRAPPER_ACTION_STATE*)MemAlloc(sizeof(BOOTSTRAPPER_ACTION_STATE) * pPackage->Msi.cSlipstreamMspPackages, TRUE); | 2728 | { |
| 2786 | ExitOnNull(pAction->msiPackage.rgSlipstreamPatches, hr, E_OUTOFMEMORY, "Failed to allocate memory for patch actions."); | 2729 | // If we are uninstalling the MSI, we must skip all the patches. |
| 2730 | for (DWORD j = 0; j < pPackage->Msi.cChainedPatches; ++j) | ||
| 2731 | { | ||
| 2732 | BURN_CHAINED_PATCH* pChainedPatch = pPackage->Msi.rgChainedPatches + j; | ||
| 2733 | BURN_MSPTARGETPRODUCT* pTargetProduct = pChainedPatch->pMspPackage->Msp.rgTargetProducts + pChainedPatch->dwMspTargetProductIndex; | ||
| 2787 | 2734 | ||
| 2788 | // If we are uninstalling or repairing the MSI, we must ignore all the slipstream patches because they cannot | 2735 | if (fExecute) |
| 2789 | // be applied right now. | 2736 | { |
| 2790 | if (BOOTSTRAPPER_ACTION_STATE_REPAIR != pAction->msiPackage.action && BOOTSTRAPPER_ACTION_STATE_UNINSTALL != pAction->msiPackage.action) | 2737 | pTargetProduct->execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; |
| 2738 | pTargetProduct->executeSkip = BURN_PATCH_SKIP_STATE_TARGET_UNINSTALL; | ||
| 2739 | } | ||
| 2740 | else | ||
| 2741 | { | ||
| 2742 | pTargetProduct->rollback = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; | ||
| 2743 | pTargetProduct->rollbackSkip = BURN_PATCH_SKIP_STATE_TARGET_UNINSTALL; | ||
| 2744 | } | ||
| 2745 | } | ||
| 2746 | } | ||
| 2747 | else | ||
| 2791 | { | 2748 | { |
| 2749 | // If the slipstream target is being installed or upgraded (not uninstalled or repaired) then we will slipstream so skip | ||
| 2750 | // the patch's standalone action. Also, if the slipstream target is being repaired and the patch is being | ||
| 2751 | // repaired, skip this operation since it will be redundant. | ||
| 2752 | // | ||
| 2753 | // The primary goal here is to ensure that a slipstream patch that is yet not installed is installed even if the MSI | ||
| 2754 | // is already on the machine. The slipstream must be installed standalone if the MSI is being repaired. | ||
| 2792 | for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j) | 2755 | for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j) |
| 2793 | { | 2756 | { |
| 2794 | BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[j].pMspPackage; | 2757 | BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + j; |
| 2795 | AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); | 2758 | BURN_CHAINED_PATCH* pChainedPatch = pPackage->Msi.rgChainedPatches + pSlipstreamMsp->dwMsiChainedPatchIndex; |
| 2796 | 2759 | BURN_MSPTARGETPRODUCT* pTargetProduct = pSlipstreamMsp->pMspPackage->Msp.rgTargetProducts + pChainedPatch->dwMspTargetProductIndex; | |
| 2797 | pAction->msiPackage.rgSlipstreamPatches[j] = fExecute ? pMspPackage->execute : pMspPackage->rollback; | 2760 | BOOTSTRAPPER_ACTION_STATE action = fExecute ? pTargetProduct->execute : pTargetProduct->rollback; |
| 2798 | for (DWORD k = 0; k < pMspPackage->Msp.cTargetProductCodes; ++k) | 2761 | BOOL fSlipstream = BOOTSTRAPPER_ACTION_STATE_UNINSTALL < action && |
| 2762 | (BOOTSTRAPPER_ACTION_STATE_REPAIR != pAction->msiPackage.action || BOOTSTRAPPER_ACTION_STATE_REPAIR == action); | ||
| 2763 | |||
| 2764 | if (fSlipstream) | ||
| 2799 | { | 2765 | { |
| 2800 | BURN_MSPTARGETPRODUCT* pTargetProduct = pMspPackage->Msp.rgTargetProducts + k; | 2766 | if (fExecute) |
| 2801 | if (pPackage == pTargetProduct->pChainedTargetPackage) | 2767 | { |
| 2768 | pSlipstreamMsp->execute = action; | ||
| 2769 | pTargetProduct->executeSkip = BURN_PATCH_SKIP_STATE_SLIPSTREAM; | ||
| 2770 | } | ||
| 2771 | else | ||
| 2802 | { | 2772 | { |
| 2803 | pAction->msiPackage.rgSlipstreamPatches[j] = fExecute ? pTargetProduct->execute : pTargetProduct->rollback; | 2773 | pSlipstreamMsp->rollback = action; |
| 2804 | break; | 2774 | pTargetProduct->rollbackSkip = BURN_PATCH_SKIP_STATE_SLIPSTREAM; |
| 2805 | } | 2775 | } |
| 2806 | } | 2776 | } |
| 2807 | } | 2777 | } |
| 2808 | } | 2778 | } |
| 2809 | } | 2779 | } |
| 2810 | } | 2780 | } |
| 2781 | } | ||
| 2811 | 2782 | ||
| 2812 | LExit: | 2783 | static void CalculateExpectedRegistrationStates( |
| 2813 | return hr; | 2784 | __in BURN_PACKAGE* rgPackages, |
| 2785 | __in DWORD cPackages | ||
| 2786 | ) | ||
| 2787 | { | ||
| 2788 | for (DWORD i = 0; i < cPackages; ++i) | ||
| 2789 | { | ||
| 2790 | BURN_PACKAGE* pPackage = rgPackages + i; | ||
| 2791 | |||
| 2792 | // MspPackages can have actions throughout the plan, so the plan needed to be finalized before anything could be calculated. | ||
| 2793 | if (BURN_PACKAGE_TYPE_MSP == pPackage->type && !pPackage->fDependencyManagerWasHere) | ||
| 2794 | { | ||
| 2795 | pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
| 2796 | pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
| 2797 | |||
| 2798 | for (DWORD j = 0; j < pPackage->Msp.cTargetProductCodes; ++j) | ||
| 2799 | { | ||
| 2800 | BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + j; | ||
| 2801 | |||
| 2802 | // The highest aggregate action state found will be used. | ||
| 2803 | if (pPackage->execute < pTargetProduct->execute) | ||
| 2804 | { | ||
| 2805 | pPackage->execute = pTargetProduct->execute; | ||
| 2806 | } | ||
| 2807 | |||
| 2808 | if (pPackage->rollback < pTargetProduct->rollback) | ||
| 2809 | { | ||
| 2810 | pPackage->rollback = pTargetProduct->rollback; | ||
| 2811 | } | ||
| 2812 | } | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | if (pPackage->fCanAffectRegistration) | ||
| 2816 | { | ||
| 2817 | if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < pPackage->execute) | ||
| 2818 | { | ||
| 2819 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | ||
| 2820 | } | ||
| 2821 | else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) | ||
| 2822 | { | ||
| 2823 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; | ||
| 2824 | } | ||
| 2825 | |||
| 2826 | if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute) | ||
| 2827 | { | ||
| 2828 | if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedCacheRegistrationState) | ||
| 2829 | { | ||
| 2830 | pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | ||
| 2831 | } | ||
| 2832 | if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedInstallRegistrationState) | ||
| 2833 | { | ||
| 2834 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | ||
| 2835 | } | ||
| 2836 | } | ||
| 2837 | else if (BURN_DEPENDENCY_ACTION_UNREGISTER == pPackage->dependencyExecute) | ||
| 2838 | { | ||
| 2839 | if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedCacheRegistrationState) | ||
| 2840 | { | ||
| 2841 | pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; | ||
| 2842 | } | ||
| 2843 | if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedInstallRegistrationState) | ||
| 2844 | { | ||
| 2845 | pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; | ||
| 2846 | } | ||
| 2847 | } | ||
| 2848 | } | ||
| 2849 | } | ||
| 2814 | } | 2850 | } |
| 2815 | 2851 | ||
| 2816 | static HRESULT PlanDependencyActions( | 2852 | static HRESULT PlanDependencyActions( |
| @@ -3064,6 +3100,11 @@ static void ExecuteActionLog( | |||
| 3064 | 3100 | ||
| 3065 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: | 3101 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: |
| 3066 | LogStringLine(PlanDumpLevel, "%ls action[%u]: MSI_PACKAGE package id: %ls, action: %hs, action msi property: %ls, ui level: %u, disable externaluihandler: %ls, log path: %ls, logging attrib: %u", wzBase, iAction, pAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pAction->msiPackage.action), LoggingBurnMsiPropertyToString(pAction->msiPackage.actionMsiProperty), pAction->msiPackage.uiLevel, pAction->msiPackage.fDisableExternalUiHandler ? L"yes" : L"no", pAction->msiPackage.sczLogPath, pAction->msiPackage.dwLoggingAttributes); | 3102 | LogStringLine(PlanDumpLevel, "%ls action[%u]: MSI_PACKAGE package id: %ls, action: %hs, action msi property: %ls, ui level: %u, disable externaluihandler: %ls, log path: %ls, logging attrib: %u", wzBase, iAction, pAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pAction->msiPackage.action), LoggingBurnMsiPropertyToString(pAction->msiPackage.actionMsiProperty), pAction->msiPackage.uiLevel, pAction->msiPackage.fDisableExternalUiHandler ? L"yes" : L"no", pAction->msiPackage.sczLogPath, pAction->msiPackage.dwLoggingAttributes); |
| 3103 | for (DWORD j = 0; j < pAction->msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++j) | ||
| 3104 | { | ||
| 3105 | const BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pAction->msiPackage.pPackage->Msi.rgSlipstreamMsps + j; | ||
| 3106 | LogStringLine(PlanDumpLevel, " Patch[%u]: msp package id: %ls, action: %hs", j, pSlipstreamMsp->pMspPackage->sczId, LoggingActionStateToString(fRollback ? pSlipstreamMsp->rollback : pSlipstreamMsp->execute)); | ||
| 3107 | } | ||
| 3067 | break; | 3108 | break; |
| 3068 | 3109 | ||
| 3069 | case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: | 3110 | case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: |
