summaryrefslogtreecommitdiff
path: root/src/burn/engine/plan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/plan.cpp')
-rw-r--r--src/burn/engine/plan.cpp111
1 files changed, 66 insertions, 45 deletions
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 419d3272..18f9b274 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -78,11 +78,13 @@ static HRESULT AddRegistrationAction(
78 ); 78 );
79static HRESULT AddCachePackage( 79static HRESULT AddCachePackage(
80 __in BURN_PLAN* pPlan, 80 __in BURN_PLAN* pPlan,
81 __in BURN_PACKAGE* pPackage 81 __in BURN_PACKAGE* pPackage,
82 __in BOOL fVital
82 ); 83 );
83static HRESULT AddCachePackageHelper( 84static HRESULT AddCachePackageHelper(
84 __in BURN_PLAN* pPlan, 85 __in BURN_PLAN* pPlan,
85 __in BURN_PACKAGE* pPackage 86 __in BURN_PACKAGE* pPackage,
87 __in BOOL fVital
86 ); 88 );
87static HRESULT AddCacheSlipstreamMsps( 89static HRESULT AddCacheSlipstreamMsps(
88 __in BURN_PLAN* pPlan, 90 __in BURN_PLAN* pPlan,
@@ -134,7 +136,7 @@ static HRESULT CalculateExecuteActions(
134 __in BURN_PACKAGE* pPackage, 136 __in BURN_PACKAGE* pPackage,
135 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary 137 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary
136 ); 138 );
137static BOOL NeedsCache( 139static BURN_CACHE_PACKAGE_TYPE GetCachePackageType(
138 __in BURN_PACKAGE* pPackage, 140 __in BURN_PACKAGE* pPackage,
139 __in BOOL fExecute 141 __in BOOL fExecute
140 ); 142 );
@@ -894,7 +896,7 @@ static HRESULT PlanPackagesHelper(
894 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; 896 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
895 BURN_PACKAGE* pPackage = rgPackages + iPackage; 897 BURN_PACKAGE* pPackage = rgPackages + iPackage;
896 898
897 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, pPackage->fPlannedCache, pPackage->fPlannedUncache); 899 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, NULL != pPackage->hCacheEvent, pPackage->fPlannedUncache);
898 900
899 if (pPackage->compatiblePackage.fPlannable) 901 if (pPackage->compatiblePackage.fPlannable)
900 { 902 {
@@ -999,7 +1001,7 @@ static HRESULT ProcessPackage(
999 { 1001 {
1000 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) 1002 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
1001 { 1003 {
1002 hr = PlanLayoutPackage(pPlan, pPackage); 1004 hr = PlanLayoutPackage(pPlan, pPackage, TRUE);
1003 ExitOnFailure(hr, "Failed to plan layout package."); 1005 ExitOnFailure(hr, "Failed to plan layout package.");
1004 } 1006 }
1005 } 1007 }
@@ -1015,7 +1017,7 @@ static HRESULT ProcessPackage(
1015 { 1017 {
1016 if (ForceCache(pPlan, pPackage)) 1018 if (ForceCache(pPlan, pPackage))
1017 { 1019 {
1018 hr = AddCachePackage(pPlan, pPackage); 1020 hr = AddCachePackage(pPlan, pPackage, TRUE);
1019 ExitOnFailure(hr, "Failed to plan cache package."); 1021 ExitOnFailure(hr, "Failed to plan cache package.");
1020 1022
1021 if (pPackage->fPerMachine) 1023 if (pPackage->fPerMachine)
@@ -1127,7 +1129,8 @@ LExit:
1127 1129
1128extern "C" HRESULT PlanLayoutPackage( 1130extern "C" HRESULT PlanLayoutPackage(
1129 __in BURN_PLAN* pPlan, 1131 __in BURN_PLAN* pPlan,
1130 __in BURN_PACKAGE* pPackage 1132 __in BURN_PACKAGE* pPackage,
1133 __in BOOL fVital
1131 ) 1134 )
1132{ 1135{
1133 HRESULT hr = S_OK; 1136 HRESULT hr = S_OK;
@@ -1143,6 +1146,7 @@ extern "C" HRESULT PlanLayoutPackage(
1143 1146
1144 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE; 1147 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE;
1145 pCacheAction->package.pPackage = pPackage; 1148 pCacheAction->package.pPackage = pPackage;
1149 pPackage->fCacheVital = fVital;
1146 1150
1147 ++pPlan->cOverallProgressTicksTotal; 1151 ++pPlan->cOverallProgressTicksTotal;
1148 1152
@@ -1170,18 +1174,14 @@ extern "C" HRESULT PlanExecutePackage(
1170 hr = DependencyPlanPackageBegin(fPerMachine, pPackage, pPlan); 1174 hr = DependencyPlanPackageBegin(fPerMachine, pPackage, pPlan);
1171 ExitOnFailure(hr, "Failed to begin plan dependency actions for package: %ls", pPackage->sczId); 1175 ExitOnFailure(hr, "Failed to begin plan dependency actions for package: %ls", pPackage->sczId);
1172 1176
1173 if (fRequestedCache || NeedsCache(pPackage, TRUE)) 1177 pPackage->executeCacheType = fRequestedCache ? BURN_CACHE_PACKAGE_TYPE_REQUIRED : GetCachePackageType(pPackage, TRUE);
1178 pPackage->rollbackCacheType = GetCachePackageType(pPackage, FALSE);
1179
1180 if (BURN_CACHE_PACKAGE_TYPE_NONE != pPackage->executeCacheType || BURN_CACHE_PACKAGE_TYPE_NONE != pPackage->rollbackCacheType)
1174 { 1181 {
1175 hr = AddCachePackage(pPlan, pPackage); 1182 hr = AddCachePackage(pPlan, pPackage, BURN_CACHE_PACKAGE_TYPE_REQUIRED == pPackage->executeCacheType);
1176 ExitOnFailure(hr, "Failed to plan cache package."); 1183 ExitOnFailure(hr, "Failed to plan cache package.");
1177 } 1184 }
1178 else if (!pPackage->fCached && NeedsCache(pPackage, FALSE))
1179 {
1180 // TODO: this decision should be made during apply instead of plan based on whether the package is actually cached.
1181 // If the package is not in the cache, disable any rollback that would require the package from the cache.
1182 LogId(REPORT_STANDARD, MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE, pPackage->sczId, LoggingActionStateToString(pPackage->rollback));
1183 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
1184 }
1185 1185
1186 // Add execute actions. 1186 // Add execute actions.
1187 switch (pPackage->type) 1187 switch (pPackage->type)
@@ -1364,6 +1364,8 @@ extern "C" HRESULT PlanRelatedBundlesInitialize(
1364 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1364 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1365 pRelatedBundle->defaultPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE; 1365 pRelatedBundle->defaultPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
1366 pRelatedBundle->planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE; 1366 pRelatedBundle->planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
1367 pRelatedBundle->package.executeCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
1368 pRelatedBundle->package.rollbackCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
1367 1369
1368 // Determine the plan relation type even if later it is ignored due to the planned action, the command relation type, or the related bundle not being plannable. 1370 // Determine the plan relation type even if later it is ignored due to the planned action, the command relation type, or the related bundle not being plannable.
1369 // This gives more information to the BA in case it wants to override default behavior. 1371 // This gives more information to the BA in case it wants to override default behavior.
@@ -2088,10 +2090,6 @@ static void UninitializeCacheAction(
2088{ 2090{
2089 switch (pCacheAction->type) 2091 switch (pCacheAction->type)
2090 { 2092 {
2091 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
2092 ReleaseHandle(pCacheAction->syncpoint.hEvent);
2093 break;
2094
2095 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE: 2093 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
2096 ReleaseStr(pCacheAction->bundleLayout.sczExecutableName); 2094 ReleaseStr(pCacheAction->bundleLayout.sczExecutableName);
2097 ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath); 2095 ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath);
@@ -2145,7 +2143,7 @@ static void ResetPlannedPackageState(
2145 pPackage->cacheType = pPackage->authoredCacheType; 2143 pPackage->cacheType = pPackage->authoredCacheType;
2146 pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; 2144 pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
2147 pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 2145 pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
2148 pPackage->fPlannedCache = FALSE; 2146 pPackage->fCacheVital = FALSE;
2149 pPackage->fPlannedUncache = FALSE; 2147 pPackage->fPlannedUncache = FALSE;
2150 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; 2148 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
2151 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 2149 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -2156,7 +2154,9 @@ static void ResetPlannedPackageState(
2156 pPackage->fDependencyManagerWasHere = FALSE; 2154 pPackage->fDependencyManagerWasHere = FALSE;
2157 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 2155 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
2158 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 2156 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
2159 pPackage->hCacheEvent = NULL; 2157 pPackage->executeCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
2158 pPackage->rollbackCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
2159 ReleaseHandle(pPackage->hCacheEvent);
2160 2160
2161 ReleaseNullStr(pPackage->sczCacheFolder); 2161 ReleaseNullStr(pPackage->sczCacheFolder);
2162 2162
@@ -2314,19 +2314,21 @@ LExit:
2314 2314
2315static HRESULT AddCachePackage( 2315static HRESULT AddCachePackage(
2316 __in BURN_PLAN* pPlan, 2316 __in BURN_PLAN* pPlan,
2317 __in BURN_PACKAGE* pPackage 2317 __in BURN_PACKAGE* pPackage,
2318 __in BOOL fVital
2318 ) 2319 )
2319{ 2320{
2320 HRESULT hr = S_OK; 2321 HRESULT hr = S_OK;
2321 2322
2322 // If this is an MSI package with slipstream MSPs, ensure the MSPs are cached first. 2323 // If this is an MSI package with slipstream MSPs, ensure the MSPs are cached first.
2323 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && 0 < pPackage->Msi.cSlipstreamMspPackages) 2324 // TODO: Slipstream packages are not accounted for when caching the MSI package is optional.
2325 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && 0 < pPackage->Msi.cSlipstreamMspPackages && fVital)
2324 { 2326 {
2325 hr = AddCacheSlipstreamMsps(pPlan, pPackage); 2327 hr = AddCacheSlipstreamMsps(pPlan, pPackage);
2326 ExitOnFailure(hr, "Failed to plan slipstream patches for package."); 2328 ExitOnFailure(hr, "Failed to plan slipstream patches for package.");
2327 } 2329 }
2328 2330
2329 hr = AddCachePackageHelper(pPlan, pPackage); 2331 hr = AddCachePackageHelper(pPlan, pPackage, fVital);
2330 ExitOnFailure(hr, "Failed to plan cache package."); 2332 ExitOnFailure(hr, "Failed to plan cache package.");
2331 2333
2332LExit: 2334LExit:
@@ -2335,7 +2337,8 @@ LExit:
2335 2337
2336static HRESULT AddCachePackageHelper( 2338static HRESULT AddCachePackageHelper(
2337 __in BURN_PLAN* pPlan, 2339 __in BURN_PLAN* pPlan,
2338 __in BURN_PACKAGE* pPackage 2340 __in BURN_PACKAGE* pPackage,
2341 __in BOOL fVital
2339 ) 2342 )
2340{ 2343{
2341 AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id."); 2344 AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id.");
@@ -2354,6 +2357,9 @@ static HRESULT AddCachePackageHelper(
2354 ExitFunction(); 2357 ExitFunction();
2355 } 2358 }
2356 2359
2360 pPackage->hCacheEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
2361 ExitOnNullWithLastError(pPackage->hCacheEvent, hr, "Failed to create syncpoint event.");
2362
2357 // Cache checkpoints happen before the package is cached because downloading packages' 2363 // Cache checkpoints happen before the package is cached because downloading packages'
2358 // payloads will not roll themselves back the way installation packages rollback on 2364 // payloads will not roll themselves back the way installation packages rollback on
2359 // failure automatically. 2365 // failure automatically.
@@ -2381,7 +2387,7 @@ static HRESULT AddCachePackageHelper(
2381 pCacheAction->checkpoint.dwId = dwCheckpoint; 2387 pCacheAction->checkpoint.dwId = dwCheckpoint;
2382 } 2388 }
2383 2389
2384 hr = PlanLayoutPackage(pPlan, pPackage); 2390 hr = PlanLayoutPackage(pPlan, pPackage, fVital);
2385 ExitOnFailure(hr, "Failed to plan cache for package."); 2391 ExitOnFailure(hr, "Failed to plan cache for package.");
2386 2392
2387 // Create syncpoint action. 2393 // Create syncpoint action.
@@ -2389,15 +2395,11 @@ static HRESULT AddCachePackageHelper(
2389 ExitOnFailure(hr, "Failed to append cache action."); 2395 ExitOnFailure(hr, "Failed to append cache action.");
2390 2396
2391 pCacheAction->type = BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT; 2397 pCacheAction->type = BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT;
2392 pCacheAction->syncpoint.hEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL); 2398 pCacheAction->syncpoint.pPackage = pPackage;
2393 ExitOnNullWithLastError(pCacheAction->syncpoint.hEvent, hr, "Failed to create syncpoint event.");
2394
2395 pPackage->hCacheEvent = pCacheAction->syncpoint.hEvent;
2396 2399
2397 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage); 2400 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage);
2398 ExitOnFailure(hr, "Failed to plan package cache syncpoint"); 2401 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
2399 2402
2400 pPackage->fPlannedCache = TRUE;
2401 if (pPackage->fCanAffectRegistration) 2403 if (pPackage->fCanAffectRegistration)
2402 { 2404 {
2403 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 2405 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
@@ -2421,7 +2423,7 @@ static HRESULT AddCacheSlipstreamMsps(
2421 BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage; 2423 BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage;
2422 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); 2424 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
2423 2425
2424 hr = AddCachePackageHelper(pPlan, pMspPackage); 2426 hr = AddCachePackageHelper(pPlan, pMspPackage, TRUE);
2425 ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId); 2427 ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId);
2426 } 2428 }
2427 2429
@@ -2791,22 +2793,41 @@ LExit:
2791 return hr; 2793 return hr;
2792} 2794}
2793 2795
2794static BOOL NeedsCache( 2796static BURN_CACHE_PACKAGE_TYPE GetCachePackageType(
2795 __in BURN_PACKAGE* pPackage, 2797 __in BURN_PACKAGE* pPackage,
2796 __in BOOL fExecute 2798 __in BOOL fExecute
2797 ) 2799 )
2798{ 2800{
2799 BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback; 2801 BURN_CACHE_PACKAGE_TYPE cachePackageType = BURN_CACHE_PACKAGE_TYPE_NONE;
2800 // TODO: bundles could theoretically use package cache 2802
2801 if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type || // Bundle and Exe packages require the package for all operations (even uninstall). 2803 switch (fExecute ? pPackage->execute : pPackage->rollback)
2802 BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_DETECTION_TYPE_ARP != pPackage->Exe.detectionType)
2803 {
2804 return BOOTSTRAPPER_ACTION_STATE_NONE != action;
2805 }
2806 else // The other package types can uninstall without the original package.
2807 { 2804 {
2808 return BOOTSTRAPPER_ACTION_STATE_UNINSTALL < action; 2805 case BOOTSTRAPPER_ACTION_STATE_NONE:
2806 break;
2807 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
2808 if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type ||
2809 BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_DETECTION_TYPE_ARP != pPackage->Exe.detectionType)
2810 {
2811 // Bundle and non-ArpEntry Exe packages require the package for all operations (even uninstall).
2812 // TODO: bundles could theoretically use package cache.
2813 cachePackageType = BURN_CACHE_PACKAGE_TYPE_REQUIRED;
2814 }
2815 else
2816 {
2817 // The other package types can uninstall without the original package.
2818 cachePackageType = BURN_CACHE_PACKAGE_TYPE_NONE;
2819 }
2820 break;
2821 case BOOTSTRAPPER_ACTION_STATE_INSTALL: __fallthrough;
2822 case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough;
2823 case BOOTSTRAPPER_ACTION_STATE_REPAIR: __fallthrough;
2824 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE: __fallthrough;
2825 default:
2826 cachePackageType = BURN_CACHE_PACKAGE_TYPE_REQUIRED;
2827 break;
2809 } 2828 }
2829
2830 return cachePackageType;
2810} 2831}
2811 2832
2812static BOOL ForceCache( 2833static BOOL ForceCache(
@@ -2881,7 +2902,7 @@ static void CacheActionLog(
2881 break; 2902 break;
2882 2903
2883 case BURN_CACHE_ACTION_TYPE_PACKAGE: 2904 case BURN_CACHE_ACTION_TYPE_PACKAGE:
2884 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE id: %ls", wzBase, iAction, pAction->package.pPackage->sczId); 2905 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE id: %ls, vital: %hs, execute cache type: %hs, rollback cache type: %hs", wzBase, iAction, pAction->package.pPackage->sczId, LoggingBoolToString(pAction->package.pPackage->fCacheVital), LoggingCachePackageTypeToString(pAction->package.pPackage->executeCacheType), LoggingCachePackageTypeToString(pAction->package.pPackage->rollbackCacheType));
2885 break; 2906 break;
2886 2907
2887 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE: 2908 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE:
@@ -2889,7 +2910,7 @@ static void CacheActionLog(
2889 break; 2910 break;
2890 2911
2891 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 2912 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
2892 LogStringLine(PlanDumpLevel, "%ls action[%u]: SIGNAL_SYNCPOINT event handle: 0x%p", wzBase, iAction, pAction->syncpoint.hEvent); 2913 LogStringLine(PlanDumpLevel, "%ls action[%u]: SIGNAL_SYNCPOINT package id: %ls, event handle: 0x%p", wzBase, iAction, pAction->syncpoint.pPackage->sczId, pAction->syncpoint.pPackage->hCacheEvent);
2893 break; 2914 break;
2894 2915
2895 default: 2916 default: