aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine')
-rw-r--r--src/burn/engine/apply.cpp51
-rw-r--r--src/burn/engine/core.cpp2
-rw-r--r--src/burn/engine/engine.mc4
-rw-r--r--src/burn/engine/logging.cpp29
-rw-r--r--src/burn/engine/logging.h8
-rw-r--r--src/burn/engine/package.h12
-rw-r--r--src/burn/engine/plan.cpp111
-rw-r--r--src/burn/engine/plan.h5
-rw-r--r--src/burn/engine/userexperience.cpp40
-rw-r--r--src/burn/engine/userexperience.h9
10 files changed, 207 insertions, 64 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index 048cd98b..d215cfe5 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -110,7 +110,8 @@ static HRESULT ApplyLayoutContainer(
110static HRESULT ApplyProcessPayload( 110static HRESULT ApplyProcessPayload(
111 __in BURN_CACHE_CONTEXT* pContext, 111 __in BURN_CACHE_CONTEXT* pContext,
112 __in_opt BURN_PACKAGE* pPackage, 112 __in_opt BURN_PACKAGE* pPackage,
113 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem 113 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
114 __in BOOL fVital
114 ); 115 );
115static HRESULT ApplyCacheVerifyContainerOrPayload( 116static HRESULT ApplyCacheVerifyContainerOrPayload(
116 __in BURN_CACHE_CONTEXT* pContext, 117 __in BURN_CACHE_CONTEXT* pContext,
@@ -203,6 +204,10 @@ static HRESULT DoRollbackActions(
203 __in DWORD dwCheckpoint, 204 __in DWORD dwCheckpoint,
204 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 205 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
205 ); 206 );
207static BOOL ShouldSkipPackage(
208 __in BURN_PACKAGE* pPackage,
209 __in BOOL fRollback
210 );
206static HRESULT ExecuteRelatedBundle( 211static HRESULT ExecuteRelatedBundle(
207 __in BURN_ENGINE_STATE* pEngineState, 212 __in BURN_ENGINE_STATE* pEngineState,
208 __in BURN_EXECUTE_ACTION* pExecuteAction, 213 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -379,6 +384,7 @@ extern "C" void ApplyReset(
379 { 384 {
380 BURN_PACKAGE* pPackage = pPackages->rgPackages + i; 385 BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
381 pPackage->hrCacheResult = S_OK; 386 pPackage->hrCacheResult = S_OK;
387 pPackage->fAcquireOptionalSource = FALSE;
382 pPackage->fReachedExecution = FALSE; 388 pPackage->fReachedExecution = FALSE;
383 pPackage->fAbandonedProcess = FALSE; 389 pPackage->fAbandonedProcess = FALSE;
384 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 390 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
@@ -633,7 +639,7 @@ extern "C" HRESULT ApplyCache(
633 break; 639 break;
634 640
635 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 641 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
636 if (!::SetEvent(pCacheAction->syncpoint.hEvent)) 642 if (!::SetEvent(pCacheAction->syncpoint.pPackage->hCacheEvent))
637 { 643 {
638 ExitWithLastError(hr, "Failed to set syncpoint event."); 644 ExitWithLastError(hr, "Failed to set syncpoint event.");
639 } 645 }
@@ -959,12 +965,13 @@ static HRESULT ApplyCachePackage(
959 HRESULT hr = S_OK; 965 HRESULT hr = S_OK;
960 BOOL fCanceledBegin = FALSE; 966 BOOL fCanceledBegin = FALSE;
961 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE; 967 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE;
968 BOOL fVital = pPackage->fCacheVital;
962 969
963 for (;;) 970 for (;;)
964 { 971 {
965 fCanceledBegin = FALSE; 972 fCanceledBegin = FALSE;
966 973
967 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cItems, pPackage->payloads.qwTotalSize); 974 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cItems, pPackage->payloads.qwTotalSize, fVital);
968 if (FAILED(hr)) 975 if (FAILED(hr))
969 { 976 {
970 fCanceledBegin = TRUE; 977 fCanceledBegin = TRUE;
@@ -975,7 +982,7 @@ static HRESULT ApplyCachePackage(
975 { 982 {
976 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i; 983 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i;
977 984
978 hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem); 985 hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem, fVital);
979 if (FAILED(hr)) 986 if (FAILED(hr))
980 { 987 {
981 break; 988 break;
@@ -984,7 +991,7 @@ static HRESULT ApplyCachePackage(
984 } 991 }
985 992
986 pPackage->hrCacheResult = hr; 993 pPackage->hrCacheResult = hr;
987 cachePackageCompleteAction = SUCCEEDED(hr) || pPackage->fVital || fCanceledBegin ? BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE : BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE; 994 cachePackageCompleteAction = SUCCEEDED(hr) || (pPackage->fVital && fVital) || fCanceledBegin ? BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE : BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE;
988 UserExperienceOnCachePackageComplete(pContext->pUX, pPackage->sczId, hr, &cachePackageCompleteAction); 995 UserExperienceOnCachePackageComplete(pContext->pUX, pPackage->sczId, hr, &cachePackageCompleteAction);
989 996
990 if (SUCCEEDED(hr)) 997 if (SUCCEEDED(hr))
@@ -1014,7 +1021,7 @@ static HRESULT ApplyCachePackage(
1014 1021
1015 continue; 1022 continue;
1016 } 1023 }
1017 else if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE == cachePackageCompleteAction && !pPackage->fVital) // ignore non-vital download failures. 1024 else if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE == cachePackageCompleteAction && (!pPackage->fVital || !fVital)) // ignore non-vital download failures.
1018 { 1025 {
1019 LogId(REPORT_STANDARD, MSG_CACHE_CONTINUING_NONVITAL_PACKAGE, pPackage->sczId, hr); 1026 LogId(REPORT_STANDARD, MSG_CACHE_CONTINUING_NONVITAL_PACKAGE, pPackage->sczId, hr);
1020 hr = S_OK; 1027 hr = S_OK;
@@ -1101,7 +1108,7 @@ static HRESULT ApplyLayoutBundle(
1101 { 1108 {
1102 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i; 1109 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i;
1103 1110
1104 hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem); 1111 hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem, TRUE);
1105 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey); 1112 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey);
1106 } 1113 }
1107 1114
@@ -1164,12 +1171,14 @@ LExit:
1164static HRESULT ApplyProcessPayload( 1171static HRESULT ApplyProcessPayload(
1165 __in BURN_CACHE_CONTEXT* pContext, 1172 __in BURN_CACHE_CONTEXT* pContext,
1166 __in_opt BURN_PACKAGE* pPackage, 1173 __in_opt BURN_PACKAGE* pPackage,
1167 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem 1174 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
1175 __in BOOL fVital
1168 ) 1176 )
1169{ 1177{
1170 HRESULT hr = S_OK; 1178 HRESULT hr = S_OK;
1171 DWORD cTryAgainAttempts = 0; 1179 DWORD cTryAgainAttempts = 0;
1172 BOOL fRetry = FALSE; 1180 BOOL fRetry = FALSE;
1181 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action = BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_NONE;
1173 BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload; 1182 BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload;
1174 1183
1175 Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory); 1184 Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory);
@@ -1184,6 +1193,18 @@ static HRESULT ApplyProcessPayload(
1184 { 1193 {
1185 ExitFunction(); 1194 ExitFunction();
1186 } 1195 }
1196 else if (pPackage && !pPackage->fAcquireOptionalSource && !fVital)
1197 {
1198 HRESULT hrResponse = UserExperienceOnCachePackageNonVitalValidationFailure(pContext->pUX, pPackage->sczId, hr, &action);
1199 ExitOnRootFailure(hrResponse, "BA aborted cache package non-vital failure.");
1200
1201 if (BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_ACQUIRE != action)
1202 {
1203 ExitFunction();
1204 }
1205
1206 pPackage->fAcquireOptionalSource = TRUE;
1207 }
1187 1208
1188 for (;;) 1209 for (;;)
1189 { 1210 {
@@ -2567,10 +2588,20 @@ static BOOL ShouldSkipPackage(
2567 ) 2588 )
2568{ 2589{
2569 BOOL fSkip = FALSE; 2590 BOOL fSkip = FALSE;
2591 BURN_CACHE_PACKAGE_TYPE cachePackageType = fRollback ? pPackage->rollbackCacheType : pPackage->executeCacheType;
2592 BOOL fCacheVital = BURN_CACHE_PACKAGE_TYPE_REQUIRED == cachePackageType;
2570 2593
2571 if (FAILED(pPackage->hrCacheResult)) 2594 if (fCacheVital && FAILED(pPackage->hrCacheResult))
2572 { 2595 {
2573 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); 2596 if (fRollback)
2597 {
2598 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_ROLLBACK_NO_CACHE, pPackage->sczId, pPackage->hrCacheResult, LoggingActionStateToString(pPackage->rollback));
2599 }
2600 else
2601 {
2602 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2603 }
2604
2574 ExitFunction1(fSkip = TRUE); 2605 ExitFunction1(fSkip = TRUE);
2575 } 2606 }
2576 else if (fRollback && pPackage->fAbandonedProcess) 2607 else if (fRollback && pPackage->fAbandonedProcess)
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 8dfa0010..c1e3a12c 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -2329,7 +2329,7 @@ static void LogPackages(
2329 LogRollbackBoundary(pPackage->pRollbackBoundaryBackward); 2329 LogRollbackBoundary(pPackage->pRollbackBoundaryBackward);
2330 } 2330 }
2331 2331
2332 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingCacheTypeToString(pPackage->authoredCacheType), LoggingCacheTypeToString(pPackage->cacheType), LoggingBoolToString(pPackage->fPlannedCache), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); 2332 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingCacheTypeToString(pPackage->authoredCacheType), LoggingCacheTypeToString(pPackage->cacheType), LoggingPlannedCacheToString(pPackage), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState));
2333 2333
2334 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 2334 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
2335 { 2335 {
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 52524edb..f5e3ca27 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -417,9 +417,9 @@ Planned related bundle: %1!ls!, detect type: %2!hs!, default plan type: %3!hs!,
417 417
418MessageId=208 418MessageId=208
419Severity=Warning 419Severity=Warning
420SymbolicName=MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE 420SymbolicName=MSG_APPLY_SKIPPED_ROLLBACK_NO_CACHE
421Language=English 421Language=English
422Plan disabled rollback due to incomplete cache for package: %1!ls!, original rollback action: %2!hs! 422Skipping apply rollback of package: %1!ls! due to cache error: 0x%2!x!, original rollback action: %3!hs!. Continuing...
423. 423.
424 424
425MessageId=209 425MessageId=209
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 77f5079c..1020d01f 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -445,6 +445,23 @@ extern "C" LPCSTR LoggingCacheTypeToString(
445 } 445 }
446} 446}
447 447
448extern "C" LPCSTR LoggingCachePackageTypeToString(
449 BURN_CACHE_PACKAGE_TYPE cachePackageType
450 )
451{
452 switch (cachePackageType)
453 {
454 case BURN_CACHE_PACKAGE_TYPE_NONE:
455 return "None";
456 case BURN_CACHE_PACKAGE_TYPE_OPTIONAL:
457 return "Optional";
458 case BURN_CACHE_PACKAGE_TYPE_REQUIRED:
459 return "Required";
460 default:
461 return "Invalid";
462 }
463}
464
448extern "C" LPCSTR LoggingDependencyActionToString( 465extern "C" LPCSTR LoggingDependencyActionToString(
449 BURN_DEPENDENCY_ACTION action 466 BURN_DEPENDENCY_ACTION action
450 ) 467 )
@@ -669,6 +686,18 @@ extern "C" LPCSTR LoggingPerMachineToString(
669 return "PerUser"; 686 return "PerUser";
670} 687}
671 688
689extern "C" LPCSTR LoggingPlannedCacheToString(
690 __in const BURN_PACKAGE* pPackage
691 )
692{
693 if (!pPackage->hCacheEvent)
694 {
695 return "No";
696 }
697
698 return pPackage->fCacheVital ? "Vital" : "NonVital";
699}
700
672extern "C" LPCSTR LoggingRegistrationTypeToString( 701extern "C" LPCSTR LoggingRegistrationTypeToString(
673 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType 702 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
674 ) 703 )
diff --git a/src/burn/engine/logging.h b/src/burn/engine/logging.h
index 857394b9..000b04f8 100644
--- a/src/burn/engine/logging.h
+++ b/src/burn/engine/logging.h
@@ -92,6 +92,10 @@ LPCSTR LoggingCacheTypeToString(
92 BOOTSTRAPPER_CACHE_TYPE cacheType 92 BOOTSTRAPPER_CACHE_TYPE cacheType
93 ); 93 );
94 94
95LPCSTR LoggingCachePackageTypeToString(
96 BURN_CACHE_PACKAGE_TYPE cachePackageType
97 );
98
95LPCSTR LoggingDependencyActionToString( 99LPCSTR LoggingDependencyActionToString(
96 BURN_DEPENDENCY_ACTION action 100 BURN_DEPENDENCY_ACTION action
97 ); 101 );
@@ -142,6 +146,10 @@ LPCSTR LoggingPerMachineToString(
142 __in BOOL fPerMachine 146 __in BOOL fPerMachine
143 ); 147 );
144 148
149LPCSTR LoggingPlannedCacheToString(
150 __in const BURN_PACKAGE* pPackage
151 );
152
145LPCSTR LoggingRegistrationTypeToString( 153LPCSTR LoggingRegistrationTypeToString(
146 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType 154 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
147 ); 155 );
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index 85f34de5..5fccf50a 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -16,6 +16,13 @@ typedef _BURN_PACKAGE BURN_PACKAGE;
16 16
17const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000; 17const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000;
18 18
19enum BURN_CACHE_PACKAGE_TYPE
20{
21 BURN_CACHE_PACKAGE_TYPE_NONE,
22 BURN_CACHE_PACKAGE_TYPE_OPTIONAL,
23 BURN_CACHE_PACKAGE_TYPE_REQUIRED,
24};
25
19enum BURN_EXE_DETECTION_TYPE 26enum BURN_EXE_DETECTION_TYPE
20{ 27{
21 BURN_EXE_DETECTION_TYPE_NONE, 28 BURN_EXE_DETECTION_TYPE_NONE,
@@ -277,7 +284,7 @@ typedef struct _BURN_PACKAGE
277 BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan. 284 BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan.
278 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan. 285 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan.
279 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan. 286 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan.
280 BOOL fPlannedCache; // only valid during Plan. 287 BOOL fCacheVital; // only valid during Plan.
281 BOOL fPlannedUncache; // only valid during Plan. 288 BOOL fPlannedUncache; // only valid during Plan.
282 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. 289 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
283 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. 290 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
@@ -286,9 +293,12 @@ typedef struct _BURN_PACKAGE
286 BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan. 293 BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan.
287 BURN_DEPENDENCY_ACTION dependencyRollback; // only valid during Plan. 294 BURN_DEPENDENCY_ACTION dependencyRollback; // only valid during Plan.
288 BOOL fDependencyManagerWasHere; // only valid during Plan. 295 BOOL fDependencyManagerWasHere; // only valid during Plan.
296 BURN_CACHE_PACKAGE_TYPE executeCacheType; // only valid during Plan.
297 BURN_CACHE_PACKAGE_TYPE rollbackCacheType; // only valid during Plan.
289 HANDLE hCacheEvent; // only valid during Plan. 298 HANDLE hCacheEvent; // only valid during Plan.
290 LPWSTR sczCacheFolder; // only valid during Apply. 299 LPWSTR sczCacheFolder; // only valid during Apply.
291 HRESULT hrCacheResult; // only valid during Apply. 300 HRESULT hrCacheResult; // only valid during Apply.
301 BOOL fAcquireOptionalSource; // only valid during Apply.
292 BOOL fReachedExecution; // only valid during Apply. 302 BOOL fReachedExecution; // only valid during Apply.
293 BOOL fAbandonedProcess; // only valid during Apply. 303 BOOL fAbandonedProcess; // only valid during Apply.
294 304
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:
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 46a9a363..386de2c6 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -117,7 +117,7 @@ typedef struct _BURN_CACHE_ACTION
117 } rollbackPackage; 117 } rollbackPackage;
118 struct 118 struct
119 { 119 {
120 HANDLE hEvent; 120 BURN_PACKAGE* pPackage;
121 } syncpoint; 121 } syncpoint;
122 struct 122 struct
123 { 123 {
@@ -392,7 +392,8 @@ HRESULT PlanLayoutContainer(
392 ); 392 );
393HRESULT PlanLayoutPackage( 393HRESULT PlanLayoutPackage(
394 __in BURN_PLAN* pPlan, 394 __in BURN_PLAN* pPlan,
395 __in BURN_PACKAGE* pPackage 395 __in BURN_PACKAGE* pPackage,
396 __in BOOL fVital
396 ); 397 );
397HRESULT PlanExecutePackage( 398HRESULT PlanExecutePackage(
398 __in BOOL fPerMachine, 399 __in BOOL fPerMachine,
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index 87ef4de1..a97234ef 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad(
104 args.pCommand = pCommand; 104 args.pCommand = pCommand;
105 args.pfnBootstrapperEngineProc = EngineForApplicationProc; 105 args.pfnBootstrapperEngineProc = EngineForApplicationProc;
106 args.pvBootstrapperEngineProcContext = pEngineContext; 106 args.pvBootstrapperEngineProcContext = pEngineContext;
107 args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 31, 0); 107 args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 6, 10, 0);
108 108
109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); 109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS);
110 110
@@ -726,7 +726,8 @@ EXTERN_C BAAPI UserExperienceOnCachePackageBegin(
726 __in BURN_USER_EXPERIENCE* pUserExperience, 726 __in BURN_USER_EXPERIENCE* pUserExperience,
727 __in_z LPCWSTR wzPackageId, 727 __in_z LPCWSTR wzPackageId,
728 __in DWORD cCachePayloads, 728 __in DWORD cCachePayloads,
729 __in DWORD64 dw64PackageCacheSize 729 __in DWORD64 dw64PackageCacheSize,
730 __in BOOL fVital
730 ) 731 )
731{ 732{
732 HRESULT hr = S_OK; 733 HRESULT hr = S_OK;
@@ -737,6 +738,7 @@ EXTERN_C BAAPI UserExperienceOnCachePackageBegin(
737 args.wzPackageId = wzPackageId; 738 args.wzPackageId = wzPackageId;
738 args.cCachePayloads = cCachePayloads; 739 args.cCachePayloads = cCachePayloads;
739 args.dw64PackageCacheSize = dw64PackageCacheSize; 740 args.dw64PackageCacheSize = dw64PackageCacheSize;
741 args.fVital = fVital;
740 742
741 results.cbSize = sizeof(results); 743 results.cbSize = sizeof(results);
742 744
@@ -783,6 +785,40 @@ LExit:
783 return hr; 785 return hr;
784} 786}
785 787
788EXTERN_C BAAPI UserExperienceOnCachePackageNonVitalValidationFailure(
789 __in BURN_USER_EXPERIENCE* pUserExperience,
790 __in_z LPCWSTR wzPackageId,
791 __in HRESULT hrStatus,
792 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* pAction
793 )
794{
795 HRESULT hr = S_OK;
796 BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS args = { };
797 BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS results = { };
798
799 args.cbSize = sizeof(args);
800 args.wzPackageId = wzPackageId;
801 args.hrStatus = hrStatus;
802 args.recommendation = *pAction;
803
804 results.cbSize = sizeof(results);
805 results.action = *pAction;
806
807 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE, &args, &results);
808 ExitOnFailure(hr, "BA OnCachePackageNonVitalValidationFailure failed.");
809
810 switch (results.action)
811 {
812 case BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_NONE: __fallthrough;
813 case BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_ACQUIRE:
814 *pAction = results.action;
815 break;
816 }
817
818LExit:
819 return hr;
820}
821
786EXTERN_C BAAPI UserExperienceOnCachePayloadExtractBegin( 822EXTERN_C BAAPI UserExperienceOnCachePayloadExtractBegin(
787 __in BURN_USER_EXPERIENCE* pUserExperience, 823 __in BURN_USER_EXPERIENCE* pUserExperience,
788 __in_z_opt LPCWSTR wzContainerId, 824 __in_z_opt LPCWSTR wzContainerId,
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index 94b73f7d..9f183208 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -189,7 +189,14 @@ BAAPI UserExperienceOnCachePackageBegin(
189 __in BURN_USER_EXPERIENCE* pUserExperience, 189 __in BURN_USER_EXPERIENCE* pUserExperience,
190 __in_z LPCWSTR wzPackageId, 190 __in_z LPCWSTR wzPackageId,
191 __in DWORD cCachePayloads, 191 __in DWORD cCachePayloads,
192 __in DWORD64 dw64PackageCacheSize 192 __in DWORD64 dw64PackageCacheSize,
193 __in BOOL fVital
194 );
195BAAPI UserExperienceOnCachePackageNonVitalValidationFailure(
196 __in BURN_USER_EXPERIENCE* pUserExperience,
197 __in_z LPCWSTR wzPackageId,
198 __in HRESULT hrStatus,
199 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* pAction
193 ); 200 );
194BAAPI UserExperienceOnCachePackageComplete( 201BAAPI UserExperienceOnCachePackageComplete(
195 __in BURN_USER_EXPERIENCE* pUserExperience, 202 __in BURN_USER_EXPERIENCE* pUserExperience,