aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/burn/engine/apply.cpp99
-rw-r--r--src/burn/engine/apply.h8
-rw-r--r--src/burn/engine/core.cpp29
-rw-r--r--src/burn/engine/core.h2
-rw-r--r--src/burn/engine/exeengine.cpp10
-rw-r--r--src/burn/engine/exeengine.h3
-rw-r--r--src/burn/engine/msiengine.cpp10
-rw-r--r--src/burn/engine/msiengine.h3
-rw-r--r--src/burn/engine/mspengine.cpp31
-rw-r--r--src/burn/engine/mspengine.h3
-rw-r--r--src/burn/engine/msuengine.cpp10
-rw-r--r--src/burn/engine/msuengine.h3
-rw-r--r--src/burn/engine/package.h2
-rw-r--r--src/burn/engine/plan.cpp128
-rw-r--r--src/burn/engine/plan.h13
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp51
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs2
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs2
18 files changed, 189 insertions, 220 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index 4d527409..aad9e6eb 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -335,6 +335,7 @@ extern "C" void ApplyReset(
335 { 335 {
336 BURN_PACKAGE* pPackage = pPackages->rgPackages + i; 336 BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
337 pPackage->hrCacheResult = S_OK; 337 pPackage->hrCacheResult = S_OK;
338 pPackage->fReachedExecution = FALSE;
338 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 339 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
339 } 340 }
340} 341}
@@ -433,7 +434,7 @@ LExit:
433 434
434extern "C" HRESULT ApplyUnregister( 435extern "C" HRESULT ApplyUnregister(
435 __in BURN_ENGINE_STATE* pEngineState, 436 __in BURN_ENGINE_STATE* pEngineState,
436 __in BOOL fFailedOrRollback, 437 __in BOOL fFailed,
437 __in BOOL fSuspend, 438 __in BOOL fSuspend,
438 __in BOOTSTRAPPER_APPLY_RESTART restart 439 __in BOOTSTRAPPER_APPLY_RESTART restart
439 ) 440 )
@@ -466,7 +467,7 @@ extern "C" HRESULT ApplyUnregister(
466 467
467 // If apply failed in any way and we're going to be keeping the bundle registered then 468 // If apply failed in any way and we're going to be keeping the bundle registered then
468 // execute any rollback dependency registration actions. 469 // execute any rollback dependency registration actions.
469 if (fFailedOrRollback && fKeepRegistration) 470 if (fFailed && fKeepRegistration)
470 { 471 {
471 // Execute any rollback registration actions. 472 // Execute any rollback registration actions.
472 HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions); 473 HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions);
@@ -587,11 +588,7 @@ extern "C" HRESULT ApplyCache(
587 } 588 }
588 589
589LExit: 590LExit:
590 if (FAILED(hr)) 591 pContext->dwCacheCheckpoint = dwCheckpoint;
591 {
592 DoRollbackCache(pUX, pPlan, hPipe, dwCheckpoint);
593 pContext->fRollback = TRUE;
594 }
595 592
596 // Clean up any remanents in the cache. 593 // Clean up any remanents in the cache.
597 if (INVALID_HANDLE_VALUE != hPipe) 594 if (INVALID_HANDLE_VALUE != hPipe)
@@ -612,6 +609,16 @@ LExit:
612 return hr; 609 return hr;
613} 610}
614 611
612extern "C" void ApplyCacheRollback(
613 __in BURN_USER_EXPERIENCE* pUX,
614 __in BURN_PLAN* pPlan,
615 __in HANDLE hPipe,
616 __in BURN_APPLY_CONTEXT* pContext
617 )
618{
619 DoRollbackCache(pUX, pPlan, hPipe, pContext->dwCacheCheckpoint);
620}
621
615extern "C" HRESULT ApplyExecute( 622extern "C" HRESULT ApplyExecute(
616 __in BURN_ENGINE_STATE* pEngineState, 623 __in BURN_ENGINE_STATE* pEngineState,
617 __in BURN_APPLY_CONTEXT* pApplyContext, 624 __in BURN_APPLY_CONTEXT* pApplyContext,
@@ -687,7 +694,6 @@ extern "C" HRESULT ApplyExecute(
687 IgnoreRollbackError(hrRollback, "Failed commit transaction from disable rollback"); 694 IgnoreRollbackError(hrRollback, "Failed commit transaction from disable rollback");
688 } 695 }
689 696
690 pApplyContext->fRollback = TRUE;
691 break; 697 break;
692 } 698 }
693 699
@@ -708,7 +714,6 @@ extern "C" HRESULT ApplyExecute(
708 // If the rollback boundary is vital, end execution here. 714 // If the rollback boundary is vital, end execution here.
709 if (pRollbackBoundary && pRollbackBoundary->fVital) 715 if (pRollbackBoundary && pRollbackBoundary->fVital)
710 { 716 {
711 pApplyContext->fRollback = TRUE;
712 break; 717 break;
713 } 718 }
714 719
@@ -2110,41 +2115,44 @@ static void DoRollbackCache(
2110 ) 2115 )
2111{ 2116{
2112 HRESULT hr = S_OK; 2117 HRESULT hr = S_OK;
2113 DWORD iCheckpoint = 0; 2118 BURN_PACKAGE* pPackage = NULL;
2119 DWORD dwLastCheckpoint = 0;
2114 2120
2115 // Scan to last checkpoint. 2121 // Rollback cache actions.
2116 for (DWORD i = 0; i < pPlan->cRollbackCacheActions; ++i) 2122 for (DWORD i = pPlan->cRollbackCacheActions; i > 0; --i)
2117 { 2123 {
2118 BURN_CACHE_ACTION* pRollbackCacheAction = &pPlan->rgRollbackCacheActions[i]; 2124 BURN_CACHE_ACTION* pRollbackCacheAction = &pPlan->rgRollbackCacheActions[i - 1];
2119 2125
2120 if (BURN_CACHE_ACTION_TYPE_CHECKPOINT == pRollbackCacheAction->type && pRollbackCacheAction->checkpoint.dwId == dwCheckpoint) 2126 switch (pRollbackCacheAction->type)
2121 { 2127 {
2122 iCheckpoint = i; 2128 case BURN_CACHE_ACTION_TYPE_CHECKPOINT:
2129 dwLastCheckpoint = pRollbackCacheAction->checkpoint.dwId;
2123 break; 2130 break;
2124 }
2125 }
2126 2131
2127 // Rollback cache actions. 2132 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE:
2128 if (iCheckpoint) 2133 pPackage = pRollbackCacheAction->rollbackPackage.pPackage;
2129 {
2130 // i has to be a signed integer so it doesn't get decremented to 0xFFFFFFFF.
2131 for (int i = iCheckpoint - 1; i >= 0; --i)
2132 {
2133 BURN_CACHE_ACTION* pRollbackCacheAction = &pPlan->rgRollbackCacheActions[i];
2134 2134
2135 switch (pRollbackCacheAction->type) 2135 // If the package was executed then it's up to ApplyExecute to rollback its cache.
2136 if (!pPackage->fReachedExecution)
2136 { 2137 {
2137 case BURN_CACHE_ACTION_TYPE_CHECKPOINT: 2138 if (!pPackage->fCached) // only rollback when it wasn't already cached.
2138 break; 2139 {
2139 2140 if (dwLastCheckpoint <= dwCheckpoint) // only rollback when it was attempted to be cached.
2140 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE: 2141 {
2141 hr = CleanPackage(hPipe, pRollbackCacheAction->rollbackPackage.pPackage); 2142 hr = CleanPackage(hPipe, pPackage);
2142 break; 2143 }
2143 2144 }
2144 default: 2145 else if (pPackage->fCanAffectRegistration)
2145 AssertSz(FALSE, "Invalid rollback cache action."); 2146 {
2146 break; 2147 // Don't let this already cached package cause the registration to be kept if the bundle failed and wasn't already registered.
2148 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
2149 }
2147 } 2150 }
2151 break;
2152
2153 default:
2154 AssertSz(FALSE, "Invalid rollback cache action.");
2155 break;
2148 } 2156 }
2149 } 2157 }
2150} 2158}
@@ -2180,9 +2188,11 @@ static HRESULT DoExecuteAction(
2180 *ppCheckpoint = &pExecuteAction->checkpoint; 2188 *ppCheckpoint = &pExecuteAction->checkpoint;
2181 break; 2189 break;
2182 2190
2183 case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT: 2191 case BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE:
2192 pExecuteAction->waitCachePackage.pPackage->fReachedExecution = TRUE;
2193
2184 // wait for cache sync-point 2194 // wait for cache sync-point
2185 rghWait[0] = pExecuteAction->syncpoint.hEvent; 2195 rghWait[0] = pExecuteAction->waitCachePackage.pPackage->hCacheEvent;
2186 rghWait[1] = pContext->pApplyContext->hCacheThread; 2196 rghWait[1] = pContext->pApplyContext->hCacheThread;
2187 switch (::WaitForMultipleObjects(rghWait[1] ? 2 : 1, rghWait, FALSE, INFINITE)) 2197 switch (::WaitForMultipleObjects(rghWait[1] ? 2 : 1, rghWait, FALSE, INFINITE))
2188 { 2198 {
@@ -2354,10 +2364,17 @@ static HRESULT DoRollbackActions(
2354 ExitFunction1(hr = S_OK); 2364 ExitFunction1(hr = S_OK);
2355 2365
2356 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: 2366 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE:
2357 // TODO: This used to be skipped if the package was already cached. 2367 if (!pRollbackAction->uncachePackage.pPackage->fCached) // only rollback when it wasn't already cached.
2358 // Need to figure out new logic for when (if?) to skip it. 2368 {
2359 hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage); 2369 hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage);
2360 IgnoreRollbackError(hr, "Failed to uncache package for rollback."); 2370 IgnoreRollbackError(hr, "Failed to uncache package for rollback.");
2371 }
2372 else if (pRollbackAction->uncachePackage.pPackage->fCanAffectRegistration)
2373 {
2374 // Don't let this already cached package cause the registration to be kept if the bundle failed and wasn't already registered.
2375 pRollbackAction->uncachePackage.pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
2376 }
2377
2361 break; 2378 break;
2362 2379
2363 default: 2380 default:
diff --git a/src/burn/engine/apply.h b/src/burn/engine/apply.h
index 39580297..45270f92 100644
--- a/src/burn/engine/apply.h
+++ b/src/burn/engine/apply.h
@@ -71,7 +71,7 @@ HRESULT ApplyRegister(
71 ); 71 );
72HRESULT ApplyUnregister( 72HRESULT ApplyUnregister(
73 __in BURN_ENGINE_STATE* pEngineState, 73 __in BURN_ENGINE_STATE* pEngineState,
74 __in BOOL fFailedOrRollback, 74 __in BOOL fFailed,
75 __in BOOL fSuspend, 75 __in BOOL fSuspend,
76 __in BOOTSTRAPPER_APPLY_RESTART restart 76 __in BOOTSTRAPPER_APPLY_RESTART restart
77 ); 77 );
@@ -83,6 +83,12 @@ HRESULT ApplyCache(
83 __in HANDLE hPipe, 83 __in HANDLE hPipe,
84 __in BURN_APPLY_CONTEXT* pContext 84 __in BURN_APPLY_CONTEXT* pContext
85 ); 85 );
86void ApplyCacheRollback(
87 __in BURN_USER_EXPERIENCE* pUX,
88 __in BURN_PLAN* pPlan,
89 __in HANDLE hPipe,
90 __in BURN_APPLY_CONTEXT* pContext
91 );
86HRESULT ApplyExecute( 92HRESULT ApplyExecute(
87 __in BURN_ENGINE_STATE* pEngineState, 93 __in BURN_ENGINE_STATE* pEngineState,
88 __in BURN_APPLY_CONTEXT* pApplyContext, 94 __in BURN_APPLY_CONTEXT* pApplyContext,
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 601f29a0..aab49cb7 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -467,6 +467,7 @@ extern "C" HRESULT CorePlan(
467 pEngineState->plan.wzBundleId = pEngineState->registration.sczId; 467 pEngineState->plan.wzBundleId = pEngineState->registration.sczId;
468 pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId; 468 pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId;
469 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback; 469 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback;
470 pEngineState->plan.fBundleAlreadyRegistered = pEngineState->registration.fInstalled;
470 471
471 hr = PlanSetVariables(action, &pEngineState->variables); 472 hr = PlanSetVariables(action, &pEngineState->variables);
472 ExitOnFailure(hr, "Failed to update action."); 473 ExitOnFailure(hr, "Failed to update action.");
@@ -613,6 +614,7 @@ extern "C" HRESULT CoreApply(
613 BURN_APPLY_CONTEXT applyContext = { }; 614 BURN_APPLY_CONTEXT applyContext = { };
614 BOOL fDeleteApplyCs = FALSE; 615 BOOL fDeleteApplyCs = FALSE;
615 BURN_CACHE_THREAD_CONTEXT cacheThreadContext = { }; 616 BURN_CACHE_THREAD_CONTEXT cacheThreadContext = { };
617 BOOL fRollbackCache = FALSE;
616 DWORD dwPhaseCount = 0; 618 DWORD dwPhaseCount = 0;
617 BOOTSTRAPPER_APPLYCOMPLETE_ACTION applyCompleteAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE; 619 BOOTSTRAPPER_APPLYCOMPLETE_ACTION applyCompleteAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE;
618 620
@@ -713,6 +715,8 @@ extern "C" HRESULT CoreApply(
713 applyContext.hCacheThread = ::CreateThread(NULL, 0, CacheThreadProc, &cacheThreadContext, 0, NULL); 715 applyContext.hCacheThread = ::CreateThread(NULL, 0, CacheThreadProc, &cacheThreadContext, 0, NULL);
714 ExitOnNullWithLastError(applyContext.hCacheThread, hr, "Failed to create cache thread."); 716 ExitOnNullWithLastError(applyContext.hCacheThread, hr, "Failed to create cache thread.");
715 717
718 fRollbackCache = TRUE;
719
716 // If we're not caching in parallel, wait for the cache thread to terminate. 720 // If we're not caching in parallel, wait for the cache thread to terminate.
717 if (!pEngineState->fParallelCacheAndExecute) 721 if (!pEngineState->fParallelCacheAndExecute)
718 { 722 {
@@ -740,23 +744,32 @@ extern "C" HRESULT CoreApply(
740 } 744 }
741 } 745 }
742 746
743 // If something went wrong or force restarted, skip cleaning. 747 if (fSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart)
744 if (FAILED(hr) || applyContext.fRollback || fSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart)
745 { 748 {
746 ExitFunction(); 749 // Leave cache alone.
750 fRollbackCache = FALSE;
747 } 751 }
748 752 else if (SUCCEEDED(hr))
749 // Clean.
750 if (pEngineState->plan.cCleanActions)
751 { 753 {
752 ApplyClean(&pEngineState->userExperience, &pEngineState->plan, pEngineState->companionConnection.hPipe); 754 // Clean.
755 fRollbackCache = FALSE;
756
757 if (pEngineState->plan.cCleanActions)
758 {
759 ApplyClean(&pEngineState->userExperience, &pEngineState->plan, pEngineState->companionConnection.hPipe);
760 }
753 } 761 }
754 762
755LExit: 763LExit:
764 if (fRollbackCache)
765 {
766 ApplyCacheRollback(&pEngineState->userExperience, &pEngineState->plan, pEngineState->companionConnection.hCachePipe, &applyContext);
767 }
768
756 // Unregister. 769 // Unregister.
757 if (fRegistered) 770 if (fRegistered)
758 { 771 {
759 ApplyUnregister(pEngineState, FAILED(hr) || applyContext.fRollback, fSuspend, restart); 772 ApplyUnregister(pEngineState, FAILED(hr), fSuspend, restart);
760 } 773 }
761 774
762 if (fElevated) 775 if (fElevated)
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 9f779366..27cb2e25 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -138,8 +138,8 @@ typedef struct _BURN_APPLY_CONTEXT
138{ 138{
139 CRITICAL_SECTION csApply; 139 CRITICAL_SECTION csApply;
140 DWORD cOverallProgressTicks; 140 DWORD cOverallProgressTicks;
141 BOOL fRollback;
142 HANDLE hCacheThread; 141 HANDLE hCacheThread;
142 DWORD dwCacheCheckpoint;
143} BURN_APPLY_CONTEXT; 143} BURN_APPLY_CONTEXT;
144 144
145 145
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index c0ba93e0..13d4f6c6 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -268,20 +268,12 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
268 __in BURN_PACKAGE* pPackage, 268 __in BURN_PACKAGE* pPackage,
269 __in BURN_PLAN* pPlan, 269 __in BURN_PLAN* pPlan,
270 __in BURN_LOGGING* pLog, 270 __in BURN_LOGGING* pLog,
271 __in BURN_VARIABLES* pVariables, 271 __in BURN_VARIABLES* pVariables
272 __in_opt HANDLE hCacheEvent
273 ) 272 )
274{ 273{
275 HRESULT hr = S_OK; 274 HRESULT hr = S_OK;
276 BURN_EXECUTE_ACTION* pAction = NULL; 275 BURN_EXECUTE_ACTION* pAction = NULL;
277 276
278 // add wait for cache
279 if (hCacheEvent)
280 {
281 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
282 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
283 }
284
285 hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan); 277 hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
286 ExitOnFailure(hr, "Failed to plan package dependency actions."); 278 ExitOnFailure(hr, "Failed to plan package dependency actions.");
287 279
diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h
index e032ea01..4fec2dd9 100644
--- a/src/burn/engine/exeengine.h
+++ b/src/burn/engine/exeengine.h
@@ -28,8 +28,7 @@ HRESULT ExeEnginePlanAddPackage(
28 __in BURN_PACKAGE* pPackage, 28 __in BURN_PACKAGE* pPackage,
29 __in BURN_PLAN* pPlan, 29 __in BURN_PLAN* pPlan,
30 __in BURN_LOGGING* pLog, 30 __in BURN_LOGGING* pLog,
31 __in BURN_VARIABLES* pVariables, 31 __in BURN_VARIABLES* pVariables
32 __in_opt HANDLE hCacheEvent
33 ); 32 );
34HRESULT ExeEngineExecutePackage( 33HRESULT ExeEngineExecutePackage(
35 __in BURN_EXECUTE_ACTION* pExecuteAction, 34 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index 3e96e5f9..a579fa17 100644
--- a/src/burn/engine/msiengine.cpp
+++ b/src/burn/engine/msiengine.cpp
@@ -915,8 +915,7 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
915 __in BURN_PACKAGE* pPackage, 915 __in BURN_PACKAGE* pPackage,
916 __in BURN_PLAN* pPlan, 916 __in BURN_PLAN* pPlan,
917 __in BURN_LOGGING* pLog, 917 __in BURN_LOGGING* pLog,
918 __in BURN_VARIABLES* pVariables, 918 __in BURN_VARIABLES* pVariables
919 __in_opt HANDLE hCacheEvent
920 ) 919 )
921{ 920{
922 HRESULT hr = S_OK; 921 HRESULT hr = S_OK;
@@ -943,13 +942,6 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
943 } 942 }
944 } 943 }
945 944
946 // add wait for cache
947 if (hCacheEvent)
948 {
949 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
950 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
951 }
952
953 hr = DependencyPlanPackage(NULL, pPackage, pPlan); 945 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
954 ExitOnFailure(hr, "Failed to plan package dependency actions."); 946 ExitOnFailure(hr, "Failed to plan package dependency actions.");
955 947
diff --git a/src/burn/engine/msiengine.h b/src/burn/engine/msiengine.h
index 8b5bcdd0..e4155a62 100644
--- a/src/burn/engine/msiengine.h
+++ b/src/burn/engine/msiengine.h
@@ -49,8 +49,7 @@ HRESULT MsiEnginePlanAddPackage(
49 __in BURN_PACKAGE* pPackage, 49 __in BURN_PACKAGE* pPackage,
50 __in BURN_PLAN* pPlan, 50 __in BURN_PLAN* pPlan,
51 __in BURN_LOGGING* pLog, 51 __in BURN_LOGGING* pLog,
52 __in BURN_VARIABLES* pVariables, 52 __in BURN_VARIABLES* pVariables
53 __in_opt HANDLE hCacheEvent
54 ); 53 );
55HRESULT MsiEngineBeginTransaction( 54HRESULT MsiEngineBeginTransaction(
56 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary 55 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
diff --git a/src/burn/engine/mspengine.cpp b/src/burn/engine/mspengine.cpp
index 6d58d324..4a82598f 100644
--- a/src/burn/engine/mspengine.cpp
+++ b/src/burn/engine/mspengine.cpp
@@ -57,8 +57,7 @@ static HRESULT PlanTargetProduct(
57 __in BURN_VARIABLES* pVariables, 57 __in BURN_VARIABLES* pVariables,
58 __in BOOTSTRAPPER_ACTION_STATE actionState, 58 __in BOOTSTRAPPER_ACTION_STATE actionState,
59 __in BURN_PACKAGE* pPackage, 59 __in BURN_PACKAGE* pPackage,
60 __in BURN_MSPTARGETPRODUCT* pTargetProduct, 60 __in BURN_MSPTARGETPRODUCT* pTargetProduct
61 __in_opt HANDLE hCacheEvent
62 ); 61 );
63 62
64 63
@@ -504,21 +503,11 @@ extern "C" HRESULT MspEnginePlanAddPackage(
504 __in BURN_PACKAGE* pPackage, 503 __in BURN_PACKAGE* pPackage,
505 __in BURN_PLAN* pPlan, 504 __in BURN_PLAN* pPlan,
506 __in BURN_LOGGING* pLog, 505 __in BURN_LOGGING* pLog,
507 __in BURN_VARIABLES* pVariables, 506 __in BURN_VARIABLES* pVariables
508 __in_opt HANDLE hCacheEvent
509 ) 507 )
510{ 508{
511 HRESULT hr = S_OK; 509 HRESULT hr = S_OK;
512 510
513 // TODO: need to handle the case where this patch adds itself to an earlier patch's list of target products. That would
514 // essentially bump this patch earlier in the plan and we need to make sure this patch is downloaded.
515 // add wait for cache
516 if (hCacheEvent)
517 {
518 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
519 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
520 }
521
522 hr = DependencyPlanPackage(NULL, pPackage, pPlan); 511 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
523 ExitOnFailure(hr, "Failed to plan package dependency actions."); 512 ExitOnFailure(hr, "Failed to plan package dependency actions.");
524 513
@@ -536,13 +525,13 @@ extern "C" HRESULT MspEnginePlanAddPackage(
536 525
537 if (BOOTSTRAPPER_ACTION_STATE_NONE != pTargetProduct->execute) 526 if (BOOTSTRAPPER_ACTION_STATE_NONE != pTargetProduct->execute)
538 { 527 {
539 hr = PlanTargetProduct(display, pUserExperience, FALSE, pPlan, pLog, pVariables, pTargetProduct->execute, pPackage, pTargetProduct, hCacheEvent); 528 hr = PlanTargetProduct(display, pUserExperience, FALSE, pPlan, pLog, pVariables, pTargetProduct->execute, pPackage, pTargetProduct);
540 ExitOnFailure(hr, "Failed to plan target product."); 529 ExitOnFailure(hr, "Failed to plan target product.");
541 } 530 }
542 531
543 if (BOOTSTRAPPER_ACTION_STATE_NONE != pTargetProduct->rollback) 532 if (BOOTSTRAPPER_ACTION_STATE_NONE != pTargetProduct->rollback)
544 { 533 {
545 hr = PlanTargetProduct(display, pUserExperience, TRUE, pPlan, pLog, pVariables, pTargetProduct->rollback, pPackage, pTargetProduct, hCacheEvent); 534 hr = PlanTargetProduct(display, pUserExperience, TRUE, pPlan, pLog, pVariables, pTargetProduct->rollback, pPackage, pTargetProduct);
546 ExitOnFailure(hr, "Failed to plan rollback target product."); 535 ExitOnFailure(hr, "Failed to plan rollback target product.");
547 } 536 }
548 } 537 }
@@ -1089,8 +1078,7 @@ static HRESULT PlanTargetProduct(
1089 __in BURN_VARIABLES* pVariables, 1078 __in BURN_VARIABLES* pVariables,
1090 __in BOOTSTRAPPER_ACTION_STATE actionState, 1079 __in BOOTSTRAPPER_ACTION_STATE actionState,
1091 __in BURN_PACKAGE* pPackage, 1080 __in BURN_PACKAGE* pPackage,
1092 __in BURN_MSPTARGETPRODUCT* pTargetProduct, 1081 __in BURN_MSPTARGETPRODUCT* pTargetProduct
1093 __in_opt HANDLE hCacheEvent
1094 ) 1082 )
1095{ 1083{
1096 HRESULT hr = S_OK; 1084 HRESULT hr = S_OK;
@@ -1153,16 +1141,17 @@ static HRESULT PlanTargetProduct(
1153 } 1141 }
1154 else 1142 else
1155 { 1143 {
1156 if (!fRollback && hCacheEvent) 1144 if (!fRollback && pPackage->hCacheEvent)
1157 { 1145 {
1158 // Since a previouse MSP target action is being updated with the new MSP, 1146 // TODO: need to properly handle rolling back the caching of the package since this causes cache and execute plans to get out of sync.
1147 // Since a previous MSP target action is being updated with the new MSP,
1159 // insert a wait syncpoint to before this action since we need to cache the current MSI before using it. 1148 // insert a wait syncpoint to before this action since we need to cache the current MSI before using it.
1160 BURN_EXECUTE_ACTION* pWaitSyncPointAction = NULL; 1149 BURN_EXECUTE_ACTION* pWaitSyncPointAction = NULL;
1161 hr = PlanInsertExecuteAction(dwInsertSequence, pPlan, &pWaitSyncPointAction); 1150 hr = PlanInsertExecuteAction(dwInsertSequence, pPlan, &pWaitSyncPointAction);
1162 ExitOnFailure(hr, "Failed to insert execute action."); 1151 ExitOnFailure(hr, "Failed to insert execute action.");
1163 1152
1164 pWaitSyncPointAction->type = BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT; 1153 pWaitSyncPointAction->type = BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE;
1165 pWaitSyncPointAction->syncpoint.hEvent = hCacheEvent; 1154 pWaitSyncPointAction->waitCachePackage.pPackage = pPackage;
1166 1155
1167 // Since we inserted an action before the MSP target action that we will be updating, need to update the pointer. 1156 // Since we inserted an action before the MSP target action that we will be updating, need to update the pointer.
1168 pAction = pPlan->rgExecuteActions + (dwInsertSequence + 1); 1157 pAction = pPlan->rgExecuteActions + (dwInsertSequence + 1);
diff --git a/src/burn/engine/mspengine.h b/src/burn/engine/mspengine.h
index 79998030..a8835d7b 100644
--- a/src/burn/engine/mspengine.h
+++ b/src/burn/engine/mspengine.h
@@ -57,8 +57,7 @@ HRESULT MspEnginePlanAddPackage(
57 __in BURN_PACKAGE* pPackage, 57 __in BURN_PACKAGE* pPackage,
58 __in BURN_PLAN* pPlan, 58 __in BURN_PLAN* pPlan,
59 __in BURN_LOGGING* pLog, 59 __in BURN_LOGGING* pLog,
60 __in BURN_VARIABLES* pVariables, 60 __in BURN_VARIABLES* pVariables
61 __in_opt HANDLE hCacheEvent
62 ); 61 );
63HRESULT MspEngineExecutePackage( 62HRESULT MspEngineExecutePackage(
64 __in_opt HWND hwndParent, 63 __in_opt HWND hwndParent,
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp
index 6003123b..d6722bbf 100644
--- a/src/burn/engine/msuengine.cpp
+++ b/src/burn/engine/msuengine.cpp
@@ -192,20 +192,12 @@ extern "C" HRESULT MsuEnginePlanAddPackage(
192 __in BURN_PACKAGE* pPackage, 192 __in BURN_PACKAGE* pPackage,
193 __in BURN_PLAN* pPlan, 193 __in BURN_PLAN* pPlan,
194 __in BURN_LOGGING* pLog, 194 __in BURN_LOGGING* pLog,
195 __in BURN_VARIABLES* pVariables, 195 __in BURN_VARIABLES* pVariables
196 __in HANDLE hCacheEvent
197 ) 196 )
198{ 197{
199 HRESULT hr = S_OK; 198 HRESULT hr = S_OK;
200 BURN_EXECUTE_ACTION* pAction = NULL; 199 BURN_EXECUTE_ACTION* pAction = NULL;
201 200
202 // add wait for cache
203 if (hCacheEvent)
204 {
205 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
206 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
207 }
208
209 hr = DependencyPlanPackage(NULL, pPackage, pPlan); 201 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
210 ExitOnFailure(hr, "Failed to plan package dependency actions."); 202 ExitOnFailure(hr, "Failed to plan package dependency actions.");
211 203
diff --git a/src/burn/engine/msuengine.h b/src/burn/engine/msuengine.h
index fda7a5ab..23dd5301 100644
--- a/src/burn/engine/msuengine.h
+++ b/src/burn/engine/msuengine.h
@@ -27,8 +27,7 @@ HRESULT MsuEnginePlanAddPackage(
27 __in BURN_PACKAGE* pPackage, 27 __in BURN_PACKAGE* pPackage,
28 __in BURN_PLAN* pPlan, 28 __in BURN_PLAN* pPlan,
29 __in BURN_LOGGING* pLog, 29 __in BURN_LOGGING* pLog,
30 __in BURN_VARIABLES* pVariables, 30 __in BURN_VARIABLES* pVariables
31 __in HANDLE hCacheEvent
32 ); 31 );
33HRESULT MsuEngineExecutePackage( 32HRESULT MsuEngineExecutePackage(
34 __in BURN_EXECUTE_ACTION* pExecuteAction, 33 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index 89a3d6e9..94f27c23 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -240,8 +240,10 @@ typedef struct _BURN_PACKAGE
240 BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan. 240 BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan.
241 BURN_DEPENDENCY_ACTION dependencyRollback; // only valid during Plan. 241 BURN_DEPENDENCY_ACTION dependencyRollback; // only valid during Plan.
242 BOOL fDependencyManagerWasHere; // only valid during Plan. 242 BOOL fDependencyManagerWasHere; // only valid during Plan.
243 HANDLE hCacheEvent; // only valid during Plan.
243 LPWSTR sczCacheFolder; // only valid during Apply. 244 LPWSTR sczCacheFolder; // only valid during Apply.
244 HRESULT hrCacheResult; // only valid during Apply. 245 HRESULT hrCacheResult; // only valid during Apply.
246 BOOL fReachedExecution; // only valid during Apply.
245 247
246 BURN_PACKAGE_REGISTRATION_STATE cacheRegistrationState; // initialized during Detect, updated during Apply. 248 BURN_PACKAGE_REGISTRATION_STATE cacheRegistrationState; // initialized during Detect, updated during Apply.
247 BURN_PACKAGE_REGISTRATION_STATE installRegistrationState; // initialized during Detect, updated during Apply. 249 BURN_PACKAGE_REGISTRATION_STATE installRegistrationState; // initialized during Detect, updated during Apply.
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index f0ae2a44..d1f07508 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -55,7 +55,6 @@ static HRESULT ProcessPackage(
55 __in BURN_LOGGING* pLog, 55 __in BURN_LOGGING* pLog,
56 __in BURN_VARIABLES* pVariables, 56 __in BURN_VARIABLES* pVariables,
57 __in BOOTSTRAPPER_DISPLAY display, 57 __in BOOTSTRAPPER_DISPLAY display,
58 __inout HANDLE* phSyncpointEvent,
59 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 58 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
60 ); 59 );
61static HRESULT ProcessPackageRollbackBoundary( 60static HRESULT ProcessPackageRollbackBoundary(
@@ -77,23 +76,16 @@ static HRESULT AddRegistrationAction(
77 ); 76 );
78static HRESULT AddCachePackage( 77static HRESULT AddCachePackage(
79 __in BURN_PLAN* pPlan, 78 __in BURN_PLAN* pPlan,
80 __in BURN_PACKAGE* pPackage, 79 __in BURN_PACKAGE* pPackage
81 __out HANDLE* phSyncpointEvent
82 ); 80 );
83static HRESULT AddCachePackageHelper( 81static HRESULT AddCachePackageHelper(
84 __in BURN_PLAN* pPlan, 82 __in BURN_PLAN* pPlan,
85 __in BURN_PACKAGE* pPackage, 83 __in BURN_PACKAGE* pPackage
86 __out HANDLE* phSyncpointEvent
87 ); 84 );
88static HRESULT AddCacheSlipstreamMsps( 85static HRESULT AddCacheSlipstreamMsps(
89 __in BURN_PLAN* pPlan, 86 __in BURN_PLAN* pPlan,
90 __in BURN_PACKAGE* pPackage 87 __in BURN_PACKAGE* pPackage
91 ); 88 );
92static BOOL AlreadyPlannedCachePackage(
93 __in BURN_PLAN* pPlan,
94 __in_z LPCWSTR wzPackageId,
95 __out HANDLE* phSyncpointEvent
96 );
97static DWORD GetNextCheckpointId( 89static DWORD GetNextCheckpointId(
98 __in BURN_PLAN* pPlan 90 __in BURN_PLAN* pPlan
99 ); 91 );
@@ -765,7 +757,6 @@ static HRESULT PlanPackagesHelper(
765 HRESULT hr = S_OK; 757 HRESULT hr = S_OK;
766 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. 758 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
767 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 759 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
768 HANDLE hSyncpointEvent = NULL;
769 760
770 // Initialize the packages. 761 // Initialize the packages.
771 for (DWORD i = 0; i < cPackages; ++i) 762 for (DWORD i = 0; i < cPackages; ++i)
@@ -796,7 +787,7 @@ static HRESULT PlanPackagesHelper(
796 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 787 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
797 BURN_PACKAGE* pPackage = rgPackages + iPackage; 788 BURN_PACKAGE* pPackage = rgPackages + iPackage;
798 789
799 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &hSyncpointEvent, &pRollbackBoundary); 790 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &pRollbackBoundary);
800 ExitOnFailure(hr, "Failed to process package."); 791 ExitOnFailure(hr, "Failed to process package.");
801 } 792 }
802 793
@@ -902,7 +893,6 @@ static HRESULT ProcessPackage(
902 __in BURN_LOGGING* pLog, 893 __in BURN_LOGGING* pLog,
903 __in BURN_VARIABLES* pVariables, 894 __in BURN_VARIABLES* pVariables,
904 __in BOOTSTRAPPER_DISPLAY display, 895 __in BOOTSTRAPPER_DISPLAY display,
905 __inout HANDLE* phSyncpointEvent,
906 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 896 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
907 ) 897 )
908{ 898{
@@ -926,14 +916,14 @@ static HRESULT ProcessPackage(
926 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) 916 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
927 { 917 {
928 // If the package is in a requested state, plan it. 918 // If the package is in a requested state, plan it.
929 hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent); 919 hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables);
930 ExitOnFailure(hr, "Failed to plan execute package."); 920 ExitOnFailure(hr, "Failed to plan execute package.");
931 } 921 }
932 else 922 else
933 { 923 {
934 if (ForceCache(pPlan, pPackage)) 924 if (ForceCache(pPlan, pPackage))
935 { 925 {
936 hr = AddCachePackage(pPlan, pPackage, phSyncpointEvent); 926 hr = AddCachePackage(pPlan, pPackage);
937 ExitOnFailure(hr, "Failed to plan cache package."); 927 ExitOnFailure(hr, "Failed to plan cache package.");
938 928
939 if (pPackage->fPerMachine) 929 if (pPackage->fPerMachine)
@@ -1072,8 +1062,7 @@ extern "C" HRESULT PlanExecutePackage(
1072 __in BURN_PLAN* pPlan, 1062 __in BURN_PLAN* pPlan,
1073 __in BURN_PACKAGE* pPackage, 1063 __in BURN_PACKAGE* pPackage,
1074 __in BURN_LOGGING* pLog, 1064 __in BURN_LOGGING* pLog,
1075 __in BURN_VARIABLES* pVariables, 1065 __in BURN_VARIABLES* pVariables
1076 __inout HANDLE* phSyncpointEvent
1077 ) 1066 )
1078{ 1067{
1079 HRESULT hr = S_OK; 1068 HRESULT hr = S_OK;
@@ -1088,7 +1077,7 @@ extern "C" HRESULT PlanExecutePackage(
1088 1077
1089 if (fRequestedCache || NeedsCache(pPackage, TRUE)) 1078 if (fRequestedCache || NeedsCache(pPackage, TRUE))
1090 { 1079 {
1091 hr = AddCachePackage(pPlan, pPackage, phSyncpointEvent); 1080 hr = AddCachePackage(pPlan, pPackage);
1092 ExitOnFailure(hr, "Failed to plan cache package."); 1081 ExitOnFailure(hr, "Failed to plan cache package.");
1093 } 1082 }
1094 else if (!pPackage->fCached && NeedsCache(pPackage, FALSE)) 1083 else if (!pPackage->fCached && NeedsCache(pPackage, FALSE))
@@ -1128,19 +1117,19 @@ extern "C" HRESULT PlanExecutePackage(
1128 switch (pPackage->type) 1117 switch (pPackage->type)
1129 { 1118 {
1130 case BURN_PACKAGE_TYPE_EXE: 1119 case BURN_PACKAGE_TYPE_EXE:
1131 hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent); 1120 hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables);
1132 break; 1121 break;
1133 1122
1134 case BURN_PACKAGE_TYPE_MSI: 1123 case BURN_PACKAGE_TYPE_MSI:
1135 hr = MsiEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent); 1124 hr = MsiEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables);
1136 break; 1125 break;
1137 1126
1138 case BURN_PACKAGE_TYPE_MSP: 1127 case BURN_PACKAGE_TYPE_MSP:
1139 hr = MspEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent); 1128 hr = MspEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables);
1140 break; 1129 break;
1141 1130
1142 case BURN_PACKAGE_TYPE_MSU: 1131 case BURN_PACKAGE_TYPE_MSU:
1143 hr = MsuEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables, *phSyncpointEvent); 1132 hr = MsuEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables);
1144 break; 1133 break;
1145 1134
1146 default: 1135 default:
@@ -1453,7 +1442,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1453 } 1442 }
1454 } 1443 }
1455 1444
1456 hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables, NULL); 1445 hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables);
1457 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId); 1446 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1458 1447
1459 // Calculate package states based on reference count for addon and patch related bundles. 1448 // Calculate package states based on reference count for addon and patch related bundles.
@@ -1583,28 +1572,30 @@ LExit:
1583 1572
1584extern "C" HRESULT PlanExecuteCacheSyncAndRollback( 1573extern "C" HRESULT PlanExecuteCacheSyncAndRollback(
1585 __in BURN_PLAN* pPlan, 1574 __in BURN_PLAN* pPlan,
1586 __in BURN_PACKAGE* pPackage, 1575 __in BURN_PACKAGE* pPackage
1587 __in HANDLE hCacheEvent
1588 ) 1576 )
1589{ 1577{
1590 HRESULT hr = S_OK; 1578 HRESULT hr = S_OK;
1591 BURN_EXECUTE_ACTION* pAction = NULL; 1579 BURN_EXECUTE_ACTION* pAction = NULL;
1592 1580
1593 hr = PlanAppendExecuteAction(pPlan, &pAction); 1581 if (!pPlan->fBundleAlreadyRegistered)
1594 ExitOnFailure(hr, "Failed to append wait action for caching."); 1582 {
1595 1583 hr = PlanAppendRollbackAction(pPlan, &pAction);
1596 pAction->type = BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT; 1584 ExitOnFailure(hr, "Failed to append rollback action.");
1597 pAction->syncpoint.hEvent = hCacheEvent;
1598
1599 hr = PlanAppendRollbackAction(pPlan, &pAction);
1600 ExitOnFailure(hr, "Failed to append rollback action.");
1601 1585
1602 pAction->type = BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE; 1586 pAction->type = BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE;
1603 pAction->uncachePackage.pPackage = pPackage; 1587 pAction->uncachePackage.pPackage = pPackage;
1588 }
1604 1589
1605 hr = PlanExecuteCheckpoint(pPlan); 1590 hr = PlanExecuteCheckpoint(pPlan);
1606 ExitOnFailure(hr, "Failed to append execute checkpoint for cache rollback."); 1591 ExitOnFailure(hr, "Failed to append execute checkpoint for cache rollback.");
1607 1592
1593 hr = PlanAppendExecuteAction(pPlan, &pAction);
1594 ExitOnFailure(hr, "Failed to append wait action for caching.");
1595
1596 pAction->type = BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE;
1597 pAction->waitCachePackage.pPackage = pPackage;
1598
1608LExit: 1599LExit:
1609 return hr; 1600 return hr;
1610} 1601}
@@ -1885,6 +1876,7 @@ static void ResetPlannedPackageState(
1885 pPackage->fDependencyManagerWasHere = FALSE; 1876 pPackage->fDependencyManagerWasHere = FALSE;
1886 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 1877 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1887 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 1878 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1879 pPackage->hCacheEvent = NULL;
1888 1880
1889 ReleaseNullStr(pPackage->sczCacheFolder); 1881 ReleaseNullStr(pPackage->sczCacheFolder);
1890 1882
@@ -2046,8 +2038,7 @@ LExit:
2046 2038
2047static HRESULT AddCachePackage( 2039static HRESULT AddCachePackage(
2048 __in BURN_PLAN* pPlan, 2040 __in BURN_PLAN* pPlan,
2049 __in BURN_PACKAGE* pPackage, 2041 __in BURN_PACKAGE* pPackage
2050 __out HANDLE* phSyncpointEvent
2051 ) 2042 )
2052{ 2043{
2053 HRESULT hr = S_OK; 2044 HRESULT hr = S_OK;
@@ -2059,7 +2050,7 @@ static HRESULT AddCachePackage(
2059 ExitOnFailure(hr, "Failed to plan slipstream patches for package."); 2050 ExitOnFailure(hr, "Failed to plan slipstream patches for package.");
2060 } 2051 }
2061 2052
2062 hr = AddCachePackageHelper(pPlan, pPackage, phSyncpointEvent); 2053 hr = AddCachePackageHelper(pPlan, pPackage);
2063 ExitOnFailure(hr, "Failed to plan cache package."); 2054 ExitOnFailure(hr, "Failed to plan cache package.");
2064 2055
2065LExit: 2056LExit:
@@ -2068,8 +2059,7 @@ LExit:
2068 2059
2069static HRESULT AddCachePackageHelper( 2060static HRESULT AddCachePackageHelper(
2070 __in BURN_PLAN* pPlan, 2061 __in BURN_PLAN* pPlan,
2071 __in BURN_PACKAGE* pPackage, 2062 __in BURN_PACKAGE* pPackage
2072 __out HANDLE* phSyncpointEvent
2073 ) 2063 )
2074{ 2064{
2075 AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id."); 2065 AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id.");
@@ -2083,8 +2073,7 @@ static HRESULT AddCachePackageHelper(
2083 ExitFunction(); 2073 ExitFunction();
2084 } 2074 }
2085 2075
2086 BOOL fPlanned = AlreadyPlannedCachePackage(pPlan, pPackage->sczId, phSyncpointEvent); 2076 if (pPackage->hCacheEvent) // Only cache the package once.
2087 if (fPlanned)
2088 { 2077 {
2089 ExitFunction(); 2078 ExitFunction();
2090 } 2079 }
@@ -2100,12 +2089,15 @@ static HRESULT AddCachePackageHelper(
2100 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CHECKPOINT; 2089 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CHECKPOINT;
2101 pCacheAction->checkpoint.dwId = dwCheckpoint; 2090 pCacheAction->checkpoint.dwId = dwCheckpoint;
2102 2091
2103 // Only plan the cache rollback if the package is also going to be uninstalled; 2092 if (!pPlan->fBundleAlreadyRegistered)
2104 // otherwise, future operations like repair will not be able to locate the cached package.
2105 BOOL fPlanCacheRollback = (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->rollback);
2106
2107 if (fPlanCacheRollback)
2108 { 2093 {
2094 // Create a package cache rollback action *before* the checkpoint.
2095 hr = AppendRollbackCacheAction(pPlan, &pCacheAction);
2096 ExitOnFailure(hr, "Failed to append rollback cache action.");
2097
2098 pCacheAction->type = BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE;
2099 pCacheAction->rollbackPackage.pPackage = pPackage;
2100
2109 hr = AppendRollbackCacheAction(pPlan, &pCacheAction); 2101 hr = AppendRollbackCacheAction(pPlan, &pCacheAction);
2110 ExitOnFailure(hr, "Failed to append rollback cache action."); 2102 ExitOnFailure(hr, "Failed to append rollback cache action.");
2111 2103
@@ -2124,7 +2116,10 @@ static HRESULT AddCachePackageHelper(
2124 pCacheAction->syncpoint.hEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL); 2116 pCacheAction->syncpoint.hEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
2125 ExitOnNullWithLastError(pCacheAction->syncpoint.hEvent, hr, "Failed to create syncpoint event."); 2117 ExitOnNullWithLastError(pCacheAction->syncpoint.hEvent, hr, "Failed to create syncpoint event.");
2126 2118
2127 *phSyncpointEvent = pCacheAction->syncpoint.hEvent; 2119 pPackage->hCacheEvent = pCacheAction->syncpoint.hEvent;
2120
2121 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage);
2122 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
2128 2123
2129 pPackage->fPlannedCache = TRUE; 2124 pPackage->fPlannedCache = TRUE;
2130 if (pPackage->fCanAffectRegistration) 2125 if (pPackage->fCanAffectRegistration)
@@ -2142,7 +2137,6 @@ static HRESULT AddCacheSlipstreamMsps(
2142 ) 2137 )
2143{ 2138{
2144 HRESULT hr = S_OK; 2139 HRESULT hr = S_OK;
2145 HANDLE hIgnored = NULL;
2146 2140
2147 AssertSz(BURN_PACKAGE_TYPE_MSI == pPackage->type, "Only MSI packages can have slipstream patches."); 2141 AssertSz(BURN_PACKAGE_TYPE_MSI == pPackage->type, "Only MSI packages can have slipstream patches.");
2148 2142
@@ -2151,7 +2145,7 @@ static HRESULT AddCacheSlipstreamMsps(
2151 BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage; 2145 BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage;
2152 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); 2146 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
2153 2147
2154 hr = AddCachePackageHelper(pPlan, pMspPackage, &hIgnored); 2148 hr = AddCachePackageHelper(pPlan, pMspPackage);
2155 ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId); 2149 ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId);
2156 } 2150 }
2157 2151
@@ -2159,36 +2153,6 @@ LExit:
2159 return hr; 2153 return hr;
2160} 2154}
2161 2155
2162static BOOL AlreadyPlannedCachePackage(
2163 __in BURN_PLAN* pPlan,
2164 __in_z LPCWSTR wzPackageId,
2165 __out HANDLE* phSyncpointEvent
2166 )
2167{
2168 BOOL fPlanned = FALSE;
2169
2170 for (DWORD iCacheAction = 0; iCacheAction < pPlan->cCacheActions; ++iCacheAction)
2171 {
2172 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + iCacheAction;
2173
2174 if (BURN_CACHE_ACTION_TYPE_PACKAGE == pCacheAction->type)
2175 {
2176 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pCacheAction->package.pPackage->sczId, -1, wzPackageId, -1))
2177 {
2178 if (iCacheAction + 1 < pPlan->cCacheActions && BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT == pPlan->rgCacheActions[iCacheAction + 1].type)
2179 {
2180 *phSyncpointEvent = pPlan->rgCacheActions[iCacheAction + 1].syncpoint.hEvent;
2181 }
2182
2183 fPlanned = TRUE;
2184 break;
2185 }
2186 }
2187 }
2188
2189 return fPlanned;
2190}
2191
2192static DWORD GetNextCheckpointId( 2156static DWORD GetNextCheckpointId(
2193 __in BURN_PLAN* pPlan 2157 __in BURN_PLAN* pPlan
2194 ) 2158 )
@@ -2635,8 +2599,8 @@ static void ExecuteActionLog(
2635 LogStringLine(PlanDumpLevel, "%ls action[%u]: ROLLBACK_BOUNDARY id: %ls, vital: %ls", wzBase, iAction, pAction->rollbackBoundary.pRollbackBoundary->sczId, pAction->rollbackBoundary.pRollbackBoundary->fVital ? L"yes" : L"no"); 2599 LogStringLine(PlanDumpLevel, "%ls action[%u]: ROLLBACK_BOUNDARY id: %ls, vital: %ls", wzBase, iAction, pAction->rollbackBoundary.pRollbackBoundary->sczId, pAction->rollbackBoundary.pRollbackBoundary->fVital ? L"yes" : L"no");
2636 break; 2600 break;
2637 2601
2638 case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT: 2602 case BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE:
2639 LogStringLine(PlanDumpLevel, "%ls action[%u]: WAIT_SYNCPOINT event handle: 0x%p", wzBase, iAction, pAction->syncpoint.hEvent); 2603 LogStringLine(PlanDumpLevel, "%ls action[%u]: WAIT_CACHE_PACKAGE id: %ls, event handle: 0x%p", wzBase, iAction, pAction->waitCachePackage.pPackage->sczId, pAction->waitCachePackage.pPackage->hCacheEvent);
2640 break; 2604 break;
2641 2605
2642 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: 2606 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE:
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 00ab5516..6db464e1 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -48,7 +48,7 @@ enum BURN_EXECUTE_ACTION_TYPE
48{ 48{
49 BURN_EXECUTE_ACTION_TYPE_NONE, 49 BURN_EXECUTE_ACTION_TYPE_NONE,
50 BURN_EXECUTE_ACTION_TYPE_CHECKPOINT, 50 BURN_EXECUTE_ACTION_TYPE_CHECKPOINT,
51 BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT, 51 BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE,
52 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE, 52 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE,
53 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, 53 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE,
54 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, 54 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE,
@@ -151,8 +151,8 @@ typedef struct _BURN_EXECUTE_ACTION
151 BURN_EXECUTE_ACTION_CHECKPOINT checkpoint; 151 BURN_EXECUTE_ACTION_CHECKPOINT checkpoint;
152 struct 152 struct
153 { 153 {
154 HANDLE hEvent; 154 BURN_PACKAGE* pPackage;
155 } syncpoint; 155 } waitCachePackage;
156 struct 156 struct
157 { 157 {
158 BURN_PACKAGE* pPackage; 158 BURN_PACKAGE* pPackage;
@@ -240,6 +240,7 @@ typedef struct _BURN_PLAN
240 BOOL fAffectedMachineState; 240 BOOL fAffectedMachineState;
241 BOOL fIgnoreAllDependents; 241 BOOL fIgnoreAllDependents;
242 LPWSTR sczLayoutDirectory; 242 LPWSTR sczLayoutDirectory;
243 BOOL fBundleAlreadyRegistered;
243 244
244 DWORD64 qwCacheSizeTotal; 245 DWORD64 qwCacheSizeTotal;
245 246
@@ -377,8 +378,7 @@ HRESULT PlanExecutePackage(
377 __in BURN_PLAN* pPlan, 378 __in BURN_PLAN* pPlan,
378 __in BURN_PACKAGE* pPackage, 379 __in BURN_PACKAGE* pPackage,
379 __in BURN_LOGGING* pLog, 380 __in BURN_LOGGING* pLog,
380 __in BURN_VARIABLES* pVariables, 381 __in BURN_VARIABLES* pVariables
381 __inout HANDLE* phSyncpointEvent
382 ); 382 );
383HRESULT PlanDefaultRelatedBundleRequestState( 383HRESULT PlanDefaultRelatedBundleRequestState(
384 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType, 384 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType,
@@ -410,8 +410,7 @@ HRESULT PlanCleanPackage(
410 ); 410 );
411HRESULT PlanExecuteCacheSyncAndRollback( 411HRESULT PlanExecuteCacheSyncAndRollback(
412 __in BURN_PLAN* pPlan, 412 __in BURN_PLAN* pPlan,
413 __in BURN_PACKAGE* pPackage, 413 __in BURN_PACKAGE* pPackage
414 __in HANDLE hCacheEvent
415 ); 414 );
416HRESULT PlanExecuteCheckpoint( 415HRESULT PlanExecuteCheckpoint(
417 __in BURN_PLAN* pPlan 416 __in BURN_PLAN* pPlan
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 23192349..3cb42c5f 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -67,7 +67,12 @@ namespace Bootstrapper
67 67
68 fRollback = TRUE; 68 fRollback = TRUE;
69 dwIndex = 0; 69 dwIndex = 0;
70 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA");
70 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 71 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
72 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageB");
73 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
74 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageC");
75 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
71 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 76 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
72 77
73 Assert::Equal(107082ull, pPlan->qwEstimatedSize); 78 Assert::Equal(107082ull, pPlan->qwEstimatedSize);
@@ -77,8 +82,8 @@ namespace Bootstrapper
77 dwIndex = 0; 82 dwIndex = 0;
78 DWORD dwExecuteCheckpointId = 2; 83 DWORD dwExecuteCheckpointId = 2;
79 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 84 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
80 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
81 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 85 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
86 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
82 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 87 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
83 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 88 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
84 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 89 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -90,18 +95,18 @@ namespace Bootstrapper
90 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE); 95 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
91 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 96 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
92 ValidateExecuteBeginMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); 97 ValidateExecuteBeginMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
93 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[5].syncpoint.hEvent);
94 dwExecuteCheckpointId += 1; // cache checkpoints 98 dwExecuteCheckpointId += 1; // cache checkpoints
95 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 99 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
100 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
96 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 101 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
97 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER); 102 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER);
98 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); 103 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
99 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 104 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
100 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER); 105 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER);
101 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 106 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
102 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[8].syncpoint.hEvent);
103 dwExecuteCheckpointId += 1; // cache checkpoints 107 dwExecuteCheckpointId += 1; // cache checkpoints
104 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 108 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
109 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageC");
105 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 110 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
106 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER); 111 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER);
107 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); 112 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
@@ -304,6 +309,7 @@ namespace Bootstrapper
304 309
305 fRollback = TRUE; 310 fRollback = TRUE;
306 dwIndex = 0; 311 dwIndex = 0;
312 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA");
307 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 313 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
308 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 314 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
309 315
@@ -314,8 +320,8 @@ namespace Bootstrapper
314 dwIndex = 0; 320 dwIndex = 0;
315 DWORD dwExecuteCheckpointId = 2; 321 DWORD dwExecuteCheckpointId = 2;
316 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 322 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
317 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
318 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 323 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
324 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
319 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 325 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
320 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 326 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
321 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 327 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -385,6 +391,8 @@ namespace Bootstrapper
385 391
386 fRollback = TRUE; 392 fRollback = TRUE;
387 dwIndex = 0; 393 dwIndex = 0;
394 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA");
395 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
388 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 396 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
389 397
390 Assert::Equal(33743ull, pPlan->qwEstimatedSize); 398 Assert::Equal(33743ull, pPlan->qwEstimatedSize);
@@ -394,8 +402,8 @@ namespace Bootstrapper
394 dwIndex = 0; 402 dwIndex = 0;
395 DWORD dwExecuteCheckpointId = 2; 403 DWORD dwExecuteCheckpointId = 2;
396 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 404 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
397 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
398 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 405 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
406 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
399 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 407 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
400 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 408 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
401 Assert::Equal(dwIndex, pPlan->cExecuteActions); 409 Assert::Equal(dwIndex, pPlan->cExecuteActions);
@@ -454,6 +462,7 @@ namespace Bootstrapper
454 462
455 fRollback = TRUE; 463 fRollback = TRUE;
456 dwIndex = 0; 464 dwIndex = 0;
465 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA");
457 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 466 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
458 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 467 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
459 468
@@ -464,8 +473,8 @@ namespace Bootstrapper
464 dwIndex = 0; 473 dwIndex = 0;
465 DWORD dwExecuteCheckpointId = 2; 474 DWORD dwExecuteCheckpointId = 2;
466 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 475 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
467 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
468 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 476 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
477 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
469 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 478 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
470 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 479 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
471 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 480 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -731,14 +740,13 @@ namespace Bootstrapper
731 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 3); 740 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 3);
732 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA"); 741 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
733 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 742 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
734 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 4); 743 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 5);
735 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 744 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
736 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 745 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
737 Assert::Equal(dwIndex, pPlan->cCacheActions); 746 Assert::Equal(dwIndex, pPlan->cCacheActions);
738 747
739 fRollback = TRUE; 748 fRollback = TRUE;
740 dwIndex = 0; 749 dwIndex = 0;
741 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 4);
742 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 750 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
743 751
744 Assert::Equal(3055111ull, pPlan->qwEstimatedSize); 752 Assert::Equal(3055111ull, pPlan->qwEstimatedSize);
@@ -749,11 +757,14 @@ namespace Bootstrapper
749 DWORD dwExecuteCheckpointId = 2; 757 DWORD dwExecuteCheckpointId = 2;
750 BURN_EXECUTE_ACTION* pExecuteAction = NULL; 758 BURN_EXECUTE_ACTION* pExecuteAction = NULL;
751 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 759 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
752 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
753 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 760 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
754 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[8].syncpoint.hEvent); 761 dwExecuteCheckpointId += 1; // cache checkpoints
755 dwExecuteCheckpointId += 2; // cache checkpoints 762 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
756 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 763 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
764 dwExecuteCheckpointId += 1; // cache checkpoints
765 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
766 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
767 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
757 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 768 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
758 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 769 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
759 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 770 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -761,8 +772,6 @@ namespace Bootstrapper
761 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 772 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
762 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER); 773 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER);
763 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 774 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
764 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[5].syncpoint.hEvent);
765 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
766 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 775 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
767 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_REGISTER); 776 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_REGISTER);
768 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_INSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE); 777 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_INSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE);
@@ -777,10 +786,10 @@ namespace Bootstrapper
777 dwIndex = 0; 786 dwIndex = 0;
778 dwExecuteCheckpointId = 2; 787 dwExecuteCheckpointId = 2;
779 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 788 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
780 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
781 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 789 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
782 dwExecuteCheckpointId += 2; // cache checkpoints 790 dwExecuteCheckpointId += 1; // cache checkpoints
783 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 791 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
792 dwExecuteCheckpointId += 1; // cache checkpoints
784 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 793 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
785 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); 794 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
786 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 795 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -789,8 +798,6 @@ namespace Bootstrapper
789 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_UNREGISTER); 798 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_UNREGISTER);
790 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 799 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
791 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 800 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
792 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
793 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
794 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_UNREGISTER); 801 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_UNREGISTER);
795 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 802 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
796 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE); 803 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE);
@@ -1414,16 +1421,16 @@ namespace Bootstrapper
1414 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 1421 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1415 } 1422 }
1416 1423
1417 void ValidateExecuteWaitSyncpoint( 1424 void ValidateExecuteWaitCachePackage(
1418 __in BURN_PLAN* pPlan, 1425 __in BURN_PLAN* pPlan,
1419 __in BOOL fRollback, 1426 __in BOOL fRollback,
1420 __in DWORD dwIndex, 1427 __in DWORD dwIndex,
1421 __in HANDLE hEvent 1428 __in_z LPCWSTR wzPackageId
1422 ) 1429 )
1423 { 1430 {
1424 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); 1431 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1425 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT, pAction->type); 1432 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE, pAction->type);
1426 Assert::Equal((DWORD_PTR)hEvent, (DWORD_PTR)pAction->syncpoint.hEvent); 1433 NativeAssert::StringEqual(wzPackageId, pAction->waitCachePackage.pPackage->sczId);
1427 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 1434 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1428 } 1435 }
1429 1436
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
index d563bbe7..08370631 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
@@ -79,7 +79,7 @@ namespace WixToolsetTest.BurnE2E
79 packageA.VerifyInstalled(false); 79 packageA.VerifyInstalled(false);
80 } 80 }
81 81
82 [Fact(Skip = "https://github.com/wixtoolset/issues/issues/exea")] 82 [Fact]
83 public void CanKeepUpgradedPackageAfterUninstallUpgradedBundle() 83 public void CanKeepUpgradedPackageAfterUninstallUpgradedBundle()
84 { 84 {
85 var testRegistryValueExe = "ExeA"; 85 var testRegistryValueExe = "ExeA";
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs
index a11a5eb6..d8428a54 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs
@@ -64,7 +64,7 @@ namespace WixToolsetTest.BurnE2E
64 packageB.VerifyInstalled(false); 64 packageB.VerifyInstalled(false);
65 } 65 }
66 66
67 [Fact(Skip = "https://github.com/wixtoolset/issues/issues/5750")] 67 [Fact]
68 public void CanCancelExecuteWhileCaching() 68 public void CanCancelExecuteWhileCaching()
69 { 69 {
70 var packageA = this.CreatePackageInstaller("PackageA"); 70 var packageA = this.CreatePackageInstaller("PackageA");