aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/engine/apply.cpp2
-rw-r--r--src/engine/cache.cpp25
-rw-r--r--src/engine/core.cpp44
-rw-r--r--src/engine/detect.cpp10
-rw-r--r--src/engine/engine.mc8
-rw-r--r--src/engine/exeengine.cpp5
-rw-r--r--src/engine/exeengine.h3
-rw-r--r--src/engine/externalengine.cpp2
-rw-r--r--src/engine/logging.cpp17
-rw-r--r--src/engine/logging.h4
-rw-r--r--src/engine/msiengine.cpp5
-rw-r--r--src/engine/msiengine.h3
-rw-r--r--src/engine/mspengine.cpp5
-rw-r--r--src/engine/mspengine.h3
-rw-r--r--src/engine/msuengine.cpp5
-rw-r--r--src/engine/msuengine.h3
-rw-r--r--src/engine/package.h13
-rw-r--r--src/engine/plan.cpp76
-rw-r--r--src/engine/plan.h13
-rw-r--r--src/engine/pseudobundle.cpp8
-rw-r--r--src/engine/pseudobundle.h2
-rw-r--r--src/engine/relatedbundle.cpp19
-rw-r--r--src/test/BurnUnitTest/PlanTest.cpp7
23 files changed, 111 insertions, 171 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 2815f7da..b79bf934 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -1910,6 +1910,8 @@ static HRESULT DoRollbackActions(
1910 ExitFunction1(hr = S_OK); 1910 ExitFunction1(hr = S_OK);
1911 1911
1912 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: 1912 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE:
1913 // TODO: This used to be skipped if the package was already cached.
1914 // Need to figure out new logic for when (if?) to skip it.
1913 hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage); 1915 hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage);
1914 IgnoreRollbackError(hr, "Failed to uncache package for rollback."); 1916 IgnoreRollbackError(hr, "Failed to uncache package for rollback.");
1915 break; 1917 break;
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp
index 2349a357..667ca9e0 100644
--- a/src/engine/cache.cpp
+++ b/src/engine/cache.cpp
@@ -91,6 +91,7 @@ static HRESULT RemoveBundleOrPackage(
91static HRESULT VerifyHash( 91static HRESULT VerifyHash(
92 __in BYTE* pbHash, 92 __in BYTE* pbHash,
93 __in DWORD cbHash, 93 __in DWORD cbHash,
94 __in DWORD64 qwFileSize,
94 __in_z LPCWSTR wzUnverifiedPayloadPath, 95 __in_z LPCWSTR wzUnverifiedPayloadPath,
95 __in HANDLE hFile 96 __in HANDLE hFile
96 ); 97 );
@@ -1288,7 +1289,7 @@ static HRESULT VerifyThenTransferContainer(
1288 // Container should have a hash we can use to verify with. 1289 // Container should have a hash we can use to verify with.
1289 if (pContainer->pbHash) 1290 if (pContainer->pbHash)
1290 { 1291 {
1291 hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, wzUnverifiedContainerPath, hFile); 1292 hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzUnverifiedContainerPath, hFile);
1292 ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath); 1293 ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath);
1293 } 1294 }
1294 1295
@@ -1330,7 +1331,7 @@ static HRESULT VerifyThenTransferPayload(
1330 1331
1331 if (pPayload->pbHash) // the payload should have a hash we can use to verify it. 1332 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1332 { 1333 {
1333 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzUnverifiedPayloadPath, hFile); 1334 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzUnverifiedPayloadPath, hFile);
1334 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); 1335 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath);
1335 } 1336 }
1336 1337
@@ -1398,7 +1399,7 @@ static HRESULT VerifyFileAgainstPayload(
1398 1399
1399 if (pPayload->pbHash) // the payload should have a hash we can use to verify it. 1400 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1400 { 1401 {
1401 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzVerifyPath, hFile); 1402 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzVerifyPath, hFile);
1402 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); 1403 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey);
1403 } 1404 }
1404 1405
@@ -1712,7 +1713,7 @@ static HRESULT RemoveBundleOrPackage(
1712 } 1713 }
1713 } 1714 }
1714 1715
1715 if (FAILED(hr)) 1716 if (E_PATHNOTFOUND != hr && FAILED(hr))
1716 { 1717 {
1717 LogId(REPORT_STANDARD, fBundle ? MSG_UNABLE_UNCACHE_BUNDLE : MSG_UNABLE_UNCACHE_PACKAGE, wzBundleOrPackageId, sczDirectory, hr); 1718 LogId(REPORT_STANDARD, fBundle ? MSG_UNABLE_UNCACHE_BUNDLE : MSG_UNABLE_UNCACHE_PACKAGE, wzBundleOrPackageId, sczDirectory, hr);
1718 hr = S_OK; 1719 hr = S_OK;
@@ -1743,6 +1744,7 @@ LExit:
1743static HRESULT VerifyHash( 1744static HRESULT VerifyHash(
1744 __in BYTE* pbHash, 1745 __in BYTE* pbHash,
1745 __in DWORD cbHash, 1746 __in DWORD cbHash,
1747 __in DWORD64 qwFileSize,
1746 __in_z LPCWSTR wzUnverifiedPayloadPath, 1748 __in_z LPCWSTR wzUnverifiedPayloadPath,
1747 __in HANDLE hFile 1749 __in HANDLE hFile
1748 ) 1750 )
@@ -1751,22 +1753,31 @@ static HRESULT VerifyHash(
1751 1753
1752 HRESULT hr = S_OK; 1754 HRESULT hr = S_OK;
1753 BYTE rgbActualHash[SHA512_HASH_LEN] = { }; 1755 BYTE rgbActualHash[SHA512_HASH_LEN] = { };
1754 DWORD64 qwHashedBytes; 1756 DWORD64 qwHashedBytes = 0;
1757 LONGLONG llSize = 0;
1755 LPWSTR pszExpected = NULL; 1758 LPWSTR pszExpected = NULL;
1756 LPWSTR pszActual = NULL; 1759 LPWSTR pszActual = NULL;
1757 1760
1761 hr = FileSizeByHandle(hFile, &llSize);
1762 ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath);
1763
1764 if (static_cast<DWORD64>(llSize) != qwFileSize)
1765 {
1766 ExitOnFailure(hr = ERROR_FILE_CORRUPT, "File size mismatch for path: %ls, expected: %llu, actual: %lld", wzUnverifiedPayloadPath, qwFileSize, llSize);
1767 }
1768
1758 // TODO: create a cryp hash file that sends progress. 1769 // TODO: create a cryp hash file that sends progress.
1759 hr = CrypHashFileHandle(hFile, PROV_RSA_AES, CALG_SHA_512, rgbActualHash, sizeof(rgbActualHash), &qwHashedBytes); 1770 hr = CrypHashFileHandle(hFile, PROV_RSA_AES, CALG_SHA_512, rgbActualHash, sizeof(rgbActualHash), &qwHashedBytes);
1760 ExitOnFailure(hr, "Failed to calculate hash for path: %ls", wzUnverifiedPayloadPath); 1771 ExitOnFailure(hr, "Failed to calculate hash for path: %ls", wzUnverifiedPayloadPath);
1761 1772
1762 // Compare hashes. 1773 // Compare hashes.
1763 if (cbHash != sizeof(rgbActualHash) || 0 != memcmp(pbHash, rgbActualHash, SHA512_HASH_LEN)) 1774 if (cbHash != sizeof(rgbActualHash) || 0 != memcmp(pbHash, rgbActualHash, sizeof(rgbActualHash)))
1764 { 1775 {
1765 hr = CRYPT_E_HASH_VALUE; 1776 hr = CRYPT_E_HASH_VALUE;
1766 1777
1767 // Best effort to log the expected and actual hash value strings. 1778 // Best effort to log the expected and actual hash value strings.
1768 if (SUCCEEDED(StrAllocHexEncode(pbHash, cbHash, &pszExpected)) && 1779 if (SUCCEEDED(StrAllocHexEncode(pbHash, cbHash, &pszExpected)) &&
1769 SUCCEEDED(StrAllocHexEncode(rgbActualHash, (SIZE_T)qwHashedBytes, &pszActual))) 1780 SUCCEEDED(StrAllocHexEncode(rgbActualHash, sizeof(rgbActualHash), &pszActual)))
1770 { 1781 {
1771 ExitOnFailure(hr, "Hash mismatch for path: %ls, expected: %ls, actual: %ls", wzUnverifiedPayloadPath, pszExpected, pszActual); 1782 ExitOnFailure(hr, "Hash mismatch for path: %ls, expected: %ls, actual: %ls", wzUnverifiedPayloadPath, pszExpected, pszActual);
1772 } 1783 }
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index 50ed6ea0..7341e4b8 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -388,7 +388,7 @@ extern "C" HRESULT CoreDetect(
388 pEngineState->registration.fEligibleForCleanup = FALSE; 388 pEngineState->registration.fEligibleForCleanup = FALSE;
389 } 389 }
390 390
391 LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingCacheStateToString(pPackage->cache), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); 391 LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingBoolToString(pPackage->fCached), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState));
392 392
393 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 393 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
394 { 394 {
@@ -439,7 +439,6 @@ extern "C" HRESULT CorePlan(
439 HRESULT hr = S_OK; 439 HRESULT hr = S_OK;
440 BOOL fPlanBegan = FALSE; 440 BOOL fPlanBegan = FALSE;
441 LPWSTR sczLayoutDirectory = NULL; 441 LPWSTR sczLayoutDirectory = NULL;
442 HANDLE hSyncpointEvent = NULL;
443 BURN_PACKAGE* pUpgradeBundlePackage = NULL; 442 BURN_PACKAGE* pUpgradeBundlePackage = NULL;
444 BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL; 443 BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL;
445 BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies. 444 BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies.
@@ -489,7 +488,7 @@ extern "C" HRESULT CorePlan(
489 ExitOnFailure(hr, "Failed to plan the layout of the bundle."); 488 ExitOnFailure(hr, "Failed to plan the layout of the bundle.");
490 489
491 // Plan the packages' layout. 490 // Plan the packages' layout.
492 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory, &hSyncpointEvent); 491 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory);
493 ExitOnFailure(hr, "Failed to plan packages."); 492 ExitOnFailure(hr, "Failed to plan packages.");
494 } 493 }
495 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) 494 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action)
@@ -498,7 +497,7 @@ extern "C" HRESULT CorePlan(
498 497
499 pUpgradeBundlePackage = &pEngineState->update.package; 498 pUpgradeBundlePackage = &pEngineState->update.package;
500 499
501 hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent); 500 hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
502 ExitOnFailure(hr, "Failed to plan update."); 501 ExitOnFailure(hr, "Failed to plan update.");
503 } 502 }
504 else 503 else
@@ -512,7 +511,7 @@ extern "C" HRESULT CorePlan(
512 511
513 pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle; 512 pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle;
514 513
515 hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent); 514 hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
516 ExitOnFailure(hr, "Failed to plan passthrough."); 515 ExitOnFailure(hr, "Failed to plan passthrough.");
517 } 516 }
518 else // doing an action that modifies the machine state. 517 else // doing an action that modifies the machine state.
@@ -533,11 +532,11 @@ extern "C" HRESULT CorePlan(
533 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); 532 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
534 ExitOnFailure(hr, "Failed to plan related bundles."); 533 ExitOnFailure(hr, "Failed to plan related bundles.");
535 534
536 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent); 535 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL);
537 ExitOnFailure(hr, "Failed to plan packages."); 536 ExitOnFailure(hr, "Failed to plan packages.");
538 537
539 // Schedule the update of related bundles last. 538 // Schedule the update of related bundles last.
540 hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, &hSyncpointEvent, dwExecuteActionEarlyIndex); 539 hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, dwExecuteActionEarlyIndex);
541 ExitOnFailure(hr, "Failed to schedule related bundles."); 540 ExitOnFailure(hr, "Failed to schedule related bundles.");
542 } 541 }
543 } 542 }
@@ -1669,9 +1668,8 @@ static HRESULT DetectPackagePayloadsCached(
1669{ 1668{
1670 HRESULT hr = S_OK; 1669 HRESULT hr = S_OK;
1671 LPWSTR sczCachePath = NULL; 1670 LPWSTR sczCachePath = NULL;
1672 BURN_CACHE_STATE cache = BURN_CACHE_STATE_NONE; // assume the package will not be cached. 1671 BOOL fCached = FALSE; // assume the package is not cached.
1673 LPWSTR sczPayloadCachePath = NULL; 1672 LPWSTR sczPayloadCachePath = NULL;
1674 LONGLONG llSize = 0;
1675 1673
1676 if (pPackage->sczCacheId && *pPackage->sczCacheId) 1674 if (pPackage->sczCacheId && *pPackage->sczCacheId)
1677 { 1675 {
@@ -1681,9 +1679,7 @@ static HRESULT DetectPackagePayloadsCached(
1681 // If the cached directory exists, we have something. 1679 // If the cached directory exists, we have something.
1682 if (DirExists(sczCachePath, NULL)) 1680 if (DirExists(sczCachePath, NULL))
1683 { 1681 {
1684 cache = BURN_CACHE_STATE_COMPLETE; // assume all payloads are cached. 1682 // Check all payloads to see if they exist.
1685
1686 // Check all payloads to see if any are missing or not the right size.
1687 for (DWORD i = 0; i < pPackage->cPayloads; ++i) 1683 for (DWORD i = 0; i < pPackage->cPayloads; ++i)
1688 { 1684 {
1689 BURN_PACKAGE_PAYLOAD* pPackagePayload = pPackage->rgPayloads + i; 1685 BURN_PACKAGE_PAYLOAD* pPackagePayload = pPackage->rgPayloads + i;
@@ -1691,35 +1687,25 @@ static HRESULT DetectPackagePayloadsCached(
1691 hr = PathConcat(sczCachePath, pPackagePayload->pPayload->sczFilePath, &sczPayloadCachePath); 1687 hr = PathConcat(sczCachePath, pPackagePayload->pPayload->sczFilePath, &sczPayloadCachePath);
1692 ExitOnFailure(hr, "Failed to concat payload cache path."); 1688 ExitOnFailure(hr, "Failed to concat payload cache path.");
1693 1689
1694 hr = FileSize(sczPayloadCachePath, &llSize); 1690 if (FileExistsEx(sczPayloadCachePath, NULL))
1695 if (SUCCEEDED(hr) && static_cast<DWORD64>(llSize) != pPackagePayload->pPayload->qwFileSize)
1696 {
1697 hr = HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT); // size did not match expectations, so cache must have the wrong file.
1698 }
1699
1700 if (SUCCEEDED(hr))
1701 { 1691 {
1702 // TODO: should we do a full on hash verification on the file to ensure 1692 // TODO: We shouldn't track whether the payload was cached since all we did was check whether the file exists.
1703 // the exact right file is cached?
1704
1705 pPackagePayload->fCached = TRUE; 1693 pPackagePayload->fCached = TRUE;
1694 fCached = TRUE;
1706 } 1695 }
1707 else 1696 else
1708 { 1697 {
1709 LogId(REPORT_STANDARD, MSG_DETECT_PACKAGE_NOT_FULLY_CACHED, pPackage->sczId, pPackagePayload->pPayload->sczKey, hr); 1698 LogId(REPORT_STANDARD, MSG_DETECT_PACKAGE_NOT_FULLY_CACHED, pPackage->sczId, pPackagePayload->pPayload->sczKey);
1710
1711 cache = BURN_CACHE_STATE_PARTIAL; // found a payload that was not cached so we are partial.
1712 hr = S_OK;
1713 } 1699 }
1714 } 1700 }
1715 } 1701 }
1716 } 1702 }
1717 1703
1718 pPackage->cache = cache; 1704 pPackage->fCached = fCached;
1719 1705
1720 if (pPackage->fCanAffectRegistration) 1706 if (pPackage->fCanAffectRegistration)
1721 { 1707 {
1722 pPackage->cacheRegistrationState = BURN_CACHE_STATE_NONE < pPackage->cache ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; 1708 pPackage->cacheRegistrationState = pPackage->fCached ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
1723 } 1709 }
1724 1710
1725LExit: 1711LExit:
@@ -1808,7 +1794,7 @@ static void LogPackages(
1808 const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i; 1794 const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i;
1809 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; 1795 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage];
1810 1796
1811 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); 1797 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fPlannedCache), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState));
1812 1798
1813 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 1799 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
1814 { 1800 {
diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp
index 3a58f3dc..355b49f5 100644
--- a/src/engine/detect.cpp
+++ b/src/engine/detect.cpp
@@ -67,7 +67,7 @@ extern "C" void DetectReset(
67 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 67 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
68 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 68 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
69 69
70 pPackage->cache = BURN_CACHE_STATE_NONE; 70 pPackage->fCached = FALSE;
71 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload) 71 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload)
72 { 72 {
73 BURN_PACKAGE_PAYLOAD* pPayload = pPackage->rgPayloads + iPayload; 73 BURN_PACKAGE_PAYLOAD* pPayload = pPackage->rgPayloads + iPayload;
@@ -149,10 +149,10 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
149 pRegistration->fForwardCompatibleBundleExists = TRUE; 149 pRegistration->fForwardCompatibleBundleExists = TRUE;
150 } 150 }
151 151
152 hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, BURN_CACHE_STATE_COMPLETE != pRelatedBundle->package.cache); 152 hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, !pRelatedBundle->package.fCached);
153 ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); 153 ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle.");
154 154
155 LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingCacheStateToString(pRelatedBundle->package.cache)); 155 LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRelatedBundle->package.fCached));
156 } 156 }
157 } 157 }
158 } 158 }
@@ -225,9 +225,9 @@ extern "C" HRESULT DetectReportRelatedBundles(
225 break; 225 break;
226 } 226 }
227 227
228 LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingRelatedOperationToString(operation), LoggingCacheStateToString(pRelatedBundle->package.cache)); 228 LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingRelatedOperationToString(operation), LoggingBoolToString(pRelatedBundle->package.fCached));
229 229
230 hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation, BURN_CACHE_STATE_COMPLETE != pRelatedBundle->package.cache); 230 hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation, !pRelatedBundle->package.fCached);
231 ExitOnRootFailure(hr, "BA aborted detect related bundle."); 231 ExitOnRootFailure(hr, "BA aborted detect related bundle.");
232 232
233 // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle. 233 // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle.
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index d0897a95..365da1d9 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -242,16 +242,16 @@ Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version
242 242
243MessageId=108 243MessageId=108
244Severity=Warning 244Severity=Warning
245SymbolicName=MSG_DETECT_RELATED_BUNDLE_NOT_FULLY_CACHED 245SymbolicName=MSG_DETECT_RELATED_BUNDLE_NOT_CACHED
246Language=English 246Language=English
247Detected partially cached related bundle: %1!ls!, cache path: %2!ls!, reason: 0x%3!x! 247Detected related bundle missing from cache: %1!ls!, cache path: %2!ls!
248. 248.
249 249
250MessageId=120 250MessageId=120
251Severity=Warning 251Severity=Warning
252SymbolicName=MSG_DETECT_PACKAGE_NOT_FULLY_CACHED 252SymbolicName=MSG_DETECT_PACKAGE_NOT_FULLY_CACHED
253Language=English 253Language=English
254Detected partially cached package: %1!ls!, invalid payload: %2!ls!, reason: 0x%3!x! 254Detected partially cached package: %1!ls!, missing payload: %2!ls!
255. 255.
256 256
257MessageId=121 257MessageId=121
@@ -363,7 +363,7 @@ MessageId=208
363Severity=Warning 363Severity=Warning
364SymbolicName=MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE 364SymbolicName=MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE
365Language=English 365Language=English
366Plan disabled rollback for package: %1!ls!, due to incomplete cache: %2!hs!, original rollback action: %3!hs! 366Plan disabled rollback due to incomplete cache for package: %1!ls!, original rollback action: %2!hs!
367. 367.
368 368
369MessageId=209 369MessageId=209
diff --git a/src/engine/exeengine.cpp b/src/engine/exeengine.cpp
index cee755e3..46905fc3 100644
--- a/src/engine/exeengine.cpp
+++ b/src/engine/exeengine.cpp
@@ -269,8 +269,7 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
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, 272 __in_opt HANDLE hCacheEvent
273 __in BOOL fPlanPackageCacheRollback
274 ) 273 )
275{ 274{
276 HRESULT hr = S_OK; 275 HRESULT hr = S_OK;
@@ -279,7 +278,7 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
279 // add wait for cache 278 // add wait for cache
280 if (hCacheEvent) 279 if (hCacheEvent)
281 { 280 {
282 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback); 281 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
283 ExitOnFailure(hr, "Failed to plan package cache syncpoint"); 282 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
284 } 283 }
285 284
diff --git a/src/engine/exeengine.h b/src/engine/exeengine.h
index 88a884eb..e032ea01 100644
--- a/src/engine/exeengine.h
+++ b/src/engine/exeengine.h
@@ -29,8 +29,7 @@ HRESULT ExeEnginePlanAddPackage(
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, 32 __in_opt HANDLE hCacheEvent
33 __in BOOL fPlanPackageCacheRollback
34 ); 33 );
35HRESULT ExeEngineExecutePackage( 34HRESULT ExeEngineExecutePackage(
36 __in BURN_EXECUTE_ACTION* pExecuteAction, 35 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/engine/externalengine.cpp b/src/engine/externalengine.cpp
index fffd96bf..7e9bb25c 100644
--- a/src/engine/externalengine.cpp
+++ b/src/engine/externalengine.cpp
@@ -327,7 +327,7 @@ HRESULT ExternalEngineSetUpdate(
327 sczId = pEngineState->registration.sczId; 327 sczId = pEngineState->registration.sczId;
328 } 328 }
329 329
330 hr = PseudoBundleInitialize(FILEMAKEVERSION(rmj, rmm, rup, rpr), &pEngineState->update.package, FALSE, sczId, BOOTSTRAPPER_RELATION_UPDATE, BOOTSTRAPPER_PACKAGE_STATE_ABSENT, BURN_CACHE_STATE_NONE, pEngineState->registration.sczExecutableName, sczLocalSource ? sczLocalSource : wzLocalSource, wzDownloadSource, qwSize, TRUE, sczCommandline, NULL, NULL, NULL, rgbHash, cbHash); 330 hr = PseudoBundleInitialize(FILEMAKEVERSION(rmj, rmm, rup, rpr), &pEngineState->update.package, FALSE, sczId, BOOTSTRAPPER_RELATION_UPDATE, BOOTSTRAPPER_PACKAGE_STATE_ABSENT, FALSE, pEngineState->registration.sczExecutableName, sczLocalSource ? sczLocalSource : wzLocalSource, wzDownloadSource, qwSize, TRUE, sczCommandline, NULL, NULL, NULL, rgbHash, cbHash);
331 ExitOnFailure(hr, "Failed to set update bundle."); 331 ExitOnFailure(hr, "Failed to set update bundle.");
332 332
333 pEngineState->update.fUpdateAvailable = TRUE; 333 pEngineState->update.fUpdateAvailable = TRUE;
diff --git a/src/engine/logging.cpp b/src/engine/logging.cpp
index 67f39c85..fd2343fa 100644
--- a/src/engine/logging.cpp
+++ b/src/engine/logging.cpp
@@ -426,23 +426,6 @@ extern "C" LPCSTR LoggingPackageRegistrationStateToString(
426 } 426 }
427} 427}
428 428
429extern "C" LPCSTR LoggingCacheStateToString(
430 __in BURN_CACHE_STATE cacheState
431 )
432{
433 switch (cacheState)
434 {
435 case BURN_CACHE_STATE_NONE:
436 return "None";
437 case BURN_CACHE_STATE_PARTIAL:
438 return "Partial";
439 case BURN_CACHE_STATE_COMPLETE:
440 return "Complete";
441 default:
442 return "Invalid";
443 }
444}
445
446extern "C" LPCSTR LoggingMsiFeatureStateToString( 429extern "C" LPCSTR LoggingMsiFeatureStateToString(
447 __in BOOTSTRAPPER_FEATURE_STATE featureState 430 __in BOOTSTRAPPER_FEATURE_STATE featureState
448 ) 431 )
diff --git a/src/engine/logging.h b/src/engine/logging.h
index a69e34c5..601039f9 100644
--- a/src/engine/logging.h
+++ b/src/engine/logging.h
@@ -94,10 +94,6 @@ LPCSTR LoggingPackageRegistrationStateToString(
94 __in BURN_PACKAGE_REGISTRATION_STATE registrationState 94 __in BURN_PACKAGE_REGISTRATION_STATE registrationState
95 ); 95 );
96 96
97LPCSTR LoggingCacheStateToString(
98 __in BURN_CACHE_STATE cacheState
99 );
100
101LPCSTR LoggingMsiFeatureStateToString( 97LPCSTR LoggingMsiFeatureStateToString(
102 __in BOOTSTRAPPER_FEATURE_STATE featureState 98 __in BOOTSTRAPPER_FEATURE_STATE featureState
103 ); 99 );
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index 269fc831..35ca5c62 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -932,8 +932,7 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
932 __in BURN_PLAN* pPlan, 932 __in BURN_PLAN* pPlan,
933 __in BURN_LOGGING* pLog, 933 __in BURN_LOGGING* pLog,
934 __in BURN_VARIABLES* pVariables, 934 __in BURN_VARIABLES* pVariables,
935 __in_opt HANDLE hCacheEvent, 935 __in_opt HANDLE hCacheEvent
936 __in BOOL fPlanPackageCacheRollback
937 ) 936 )
938{ 937{
939 HRESULT hr = S_OK; 938 HRESULT hr = S_OK;
@@ -963,7 +962,7 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
963 // add wait for cache 962 // add wait for cache
964 if (hCacheEvent) 963 if (hCacheEvent)
965 { 964 {
966 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback); 965 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
967 ExitOnFailure(hr, "Failed to plan package cache syncpoint"); 966 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
968 } 967 }
969 968
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index 99f97413..8b5bcdd0 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -50,8 +50,7 @@ HRESULT MsiEnginePlanAddPackage(
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, 53 __in_opt HANDLE hCacheEvent
54 __in BOOL fPlanPackageCacheRollback
55 ); 54 );
56HRESULT MsiEngineBeginTransaction( 55HRESULT MsiEngineBeginTransaction(
57 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary 56 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp
index ed105d24..5ccb6718 100644
--- a/src/engine/mspengine.cpp
+++ b/src/engine/mspengine.cpp
@@ -506,8 +506,7 @@ extern "C" HRESULT MspEnginePlanAddPackage(
506 __in BURN_PLAN* pPlan, 506 __in BURN_PLAN* pPlan,
507 __in BURN_LOGGING* pLog, 507 __in BURN_LOGGING* pLog,
508 __in BURN_VARIABLES* pVariables, 508 __in BURN_VARIABLES* pVariables,
509 __in_opt HANDLE hCacheEvent, 509 __in_opt HANDLE hCacheEvent
510 __in BOOL fPlanPackageCacheRollback
511 ) 510 )
512{ 511{
513 HRESULT hr = S_OK; 512 HRESULT hr = S_OK;
@@ -517,7 +516,7 @@ extern "C" HRESULT MspEnginePlanAddPackage(
517 // add wait for cache 516 // add wait for cache
518 if (hCacheEvent) 517 if (hCacheEvent)
519 { 518 {
520 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback); 519 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
521 ExitOnFailure(hr, "Failed to plan package cache syncpoint"); 520 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
522 } 521 }
523 522
diff --git a/src/engine/mspengine.h b/src/engine/mspengine.h
index 1530954b..79998030 100644
--- a/src/engine/mspengine.h
+++ b/src/engine/mspengine.h
@@ -58,8 +58,7 @@ HRESULT MspEnginePlanAddPackage(
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, 61 __in_opt HANDLE hCacheEvent
62 __in BOOL fPlanPackageCacheRollback
63 ); 62 );
64HRESULT MspEngineExecutePackage( 63HRESULT MspEngineExecutePackage(
65 __in_opt HWND hwndParent, 64 __in_opt HWND hwndParent,
diff --git a/src/engine/msuengine.cpp b/src/engine/msuengine.cpp
index 91bbf361..59f9a656 100644
--- a/src/engine/msuengine.cpp
+++ b/src/engine/msuengine.cpp
@@ -193,8 +193,7 @@ extern "C" HRESULT MsuEnginePlanAddPackage(
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, 196 __in HANDLE hCacheEvent
197 __in BOOL fPlanPackageCacheRollback
198 ) 197 )
199{ 198{
200 HRESULT hr = S_OK; 199 HRESULT hr = S_OK;
@@ -203,7 +202,7 @@ extern "C" HRESULT MsuEnginePlanAddPackage(
203 // add wait for cache 202 // add wait for cache
204 if (hCacheEvent) 203 if (hCacheEvent)
205 { 204 {
206 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback); 205 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent);
207 ExitOnFailure(hr, "Failed to plan package cache syncpoint"); 206 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
208 } 207 }
209 208
diff --git a/src/engine/msuengine.h b/src/engine/msuengine.h
index cd966b0a..fda7a5ab 100644
--- a/src/engine/msuengine.h
+++ b/src/engine/msuengine.h
@@ -28,8 +28,7 @@ HRESULT MsuEnginePlanAddPackage(
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, 31 __in HANDLE hCacheEvent
32 __in BOOL fPlanPackageCacheRollback
33 ); 32 );
34HRESULT MsuEngineExecutePackage( 33HRESULT MsuEngineExecutePackage(
35 __in BURN_EXECUTE_ACTION* pExecuteAction, 34 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/engine/package.h b/src/engine/package.h
index 42f1febe..262262ab 100644
--- a/src/engine/package.h
+++ b/src/engine/package.h
@@ -41,13 +41,6 @@ enum BURN_PACKAGE_TYPE
41 BURN_PACKAGE_TYPE_MSU, 41 BURN_PACKAGE_TYPE_MSU,
42}; 42};
43 43
44enum BURN_CACHE_STATE
45{
46 BURN_CACHE_STATE_NONE,
47 BURN_CACHE_STATE_PARTIAL,
48 BURN_CACHE_STATE_COMPLETE,
49};
50
51enum BURN_CACHE_TYPE 44enum BURN_CACHE_TYPE
52{ 45{
53 BURN_CACHE_TYPE_NO, 46 BURN_CACHE_TYPE_NO,
@@ -246,12 +239,12 @@ typedef struct _BURN_PACKAGE
246 BURN_ROLLBACK_BOUNDARY* pRollbackBoundaryBackward; // used during uninstall. 239 BURN_ROLLBACK_BOUNDARY* pRollbackBoundaryBackward; // used during uninstall.
247 240
248 BOOTSTRAPPER_PACKAGE_STATE currentState; // only valid after Detect. 241 BOOTSTRAPPER_PACKAGE_STATE currentState; // only valid after Detect.
249 BURN_CACHE_STATE cache; // only valid after Detect. 242 BOOL fCached; // only valid after Detect.
250 BOOL fPackageProviderExists; // only valid after Detect. 243 BOOL fPackageProviderExists; // only valid after Detect.
251 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan. 244 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan.
252 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan. 245 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan.
253 BOOL fAcquire; // only valid during Plan. 246 BOOL fPlannedCache; // only valid during Plan.
254 BOOL fUncache; // only valid during Plan. 247 BOOL fPlannedUncache; // only valid during Plan.
255 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. 248 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
256 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. 249 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
257 BURN_DEPENDENCY_ACTION providerExecute; // only valid during Plan. 250 BURN_DEPENDENCY_ACTION providerExecute; // only valid during Plan.
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index c75c1753..187b1f15 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -31,8 +31,7 @@ static HRESULT PlanPackagesHelper(
31 __in BURN_VARIABLES* pVariables, 31 __in BURN_VARIABLES* pVariables,
32 __in BOOTSTRAPPER_DISPLAY display, 32 __in BOOTSTRAPPER_DISPLAY display,
33 __in BOOTSTRAPPER_RELATION_TYPE relationType, 33 __in BOOTSTRAPPER_RELATION_TYPE relationType,
34 __in_z_opt LPCWSTR wzLayoutDirectory, 34 __in_z_opt LPCWSTR wzLayoutDirectory
35 __inout HANDLE* phSyncpointEvent
36 ); 35 );
37static HRESULT InitializePackage( 36static HRESULT InitializePackage(
38 __in BURN_PLAN* pPlan, 37 __in BURN_PLAN* pPlan,
@@ -564,13 +563,12 @@ extern "C" HRESULT PlanPackages(
564 __in BURN_VARIABLES* pVariables, 563 __in BURN_VARIABLES* pVariables,
565 __in BOOTSTRAPPER_DISPLAY display, 564 __in BOOTSTRAPPER_DISPLAY display,
566 __in BOOTSTRAPPER_RELATION_TYPE relationType, 565 __in BOOTSTRAPPER_RELATION_TYPE relationType,
567 __in_z_opt LPCWSTR wzLayoutDirectory, 566 __in_z_opt LPCWSTR wzLayoutDirectory
568 __inout HANDLE* phSyncpointEvent
569 ) 567 )
570{ 568{
571 HRESULT hr = S_OK; 569 HRESULT hr = S_OK;
572 570
573 hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent); 571 hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, wzLayoutDirectory);
574 572
575 return hr; 573 return hr;
576} 574}
@@ -776,8 +774,7 @@ extern "C" HRESULT PlanPassThroughBundle(
776 __in BURN_LOGGING* pLog, 774 __in BURN_LOGGING* pLog,
777 __in BURN_VARIABLES* pVariables, 775 __in BURN_VARIABLES* pVariables,
778 __in BOOTSTRAPPER_DISPLAY display, 776 __in BOOTSTRAPPER_DISPLAY display,
779 __in BOOTSTRAPPER_RELATION_TYPE relationType, 777 __in BOOTSTRAPPER_RELATION_TYPE relationType
780 __inout HANDLE* phSyncpointEvent
781 ) 778 )
782{ 779{
783 HRESULT hr = S_OK; 780 HRESULT hr = S_OK;
@@ -785,7 +782,7 @@ extern "C" HRESULT PlanPassThroughBundle(
785 // Plan passthrough package. 782 // Plan passthrough package.
786 // Passthrough packages are never cleaned up by the calling bundle (they delete themselves when appropriate) 783 // Passthrough packages are never cleaned up by the calling bundle (they delete themselves when appropriate)
787 // so we don't need to plan clean up. 784 // so we don't need to plan clean up.
788 hr = PlanPackagesHelper(pPackage, 1, FALSE, pUX, pPlan, pLog, pVariables, display, relationType, NULL, phSyncpointEvent); 785 hr = PlanPackagesHelper(pPackage, 1, FALSE, pUX, pPlan, pLog, pVariables, display, relationType, NULL);
789 ExitOnFailure(hr, "Failed to process passthrough package."); 786 ExitOnFailure(hr, "Failed to process passthrough package.");
790 787
791LExit: 788LExit:
@@ -799,14 +796,13 @@ extern "C" HRESULT PlanUpdateBundle(
799 __in BURN_LOGGING* pLog, 796 __in BURN_LOGGING* pLog,
800 __in BURN_VARIABLES* pVariables, 797 __in BURN_VARIABLES* pVariables,
801 __in BOOTSTRAPPER_DISPLAY display, 798 __in BOOTSTRAPPER_DISPLAY display,
802 __in BOOTSTRAPPER_RELATION_TYPE relationType, 799 __in BOOTSTRAPPER_RELATION_TYPE relationType
803 __inout HANDLE* phSyncpointEvent
804 ) 800 )
805{ 801{
806 HRESULT hr = S_OK; 802 HRESULT hr = S_OK;
807 803
808 // Plan update package. 804 // Plan update package.
809 hr = PlanPackagesHelper(pPackage, 1, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, NULL, phSyncpointEvent); 805 hr = PlanPackagesHelper(pPackage, 1, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, NULL);
810 ExitOnFailure(hr, "Failed to process update package."); 806 ExitOnFailure(hr, "Failed to process update package.");
811 807
812LExit: 808LExit:
@@ -823,13 +819,13 @@ static HRESULT PlanPackagesHelper(
823 __in BURN_VARIABLES* pVariables, 819 __in BURN_VARIABLES* pVariables,
824 __in BOOTSTRAPPER_DISPLAY display, 820 __in BOOTSTRAPPER_DISPLAY display,
825 __in BOOTSTRAPPER_RELATION_TYPE relationType, 821 __in BOOTSTRAPPER_RELATION_TYPE relationType,
826 __in_z_opt LPCWSTR wzLayoutDirectory, 822 __in_z_opt LPCWSTR wzLayoutDirectory
827 __inout HANDLE* phSyncpointEvent
828 ) 823 )
829{ 824{
830 HRESULT hr = S_OK; 825 HRESULT hr = S_OK;
831 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. 826 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
832 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 827 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
828 HANDLE hSyncpointEvent = NULL;
833 829
834 // Initialize the packages. 830 // Initialize the packages.
835 for (DWORD i = 0; i < cPackages; ++i) 831 for (DWORD i = 0; i < cPackages; ++i)
@@ -860,7 +856,7 @@ static HRESULT PlanPackagesHelper(
860 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 856 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
861 BURN_PACKAGE* pPackage = rgPackages + iPackage; 857 BURN_PACKAGE* pPackage = rgPackages + iPackage;
862 858
863 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary); 859 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, wzLayoutDirectory, &hSyncpointEvent, &pRollbackBoundary);
864 ExitOnFailure(hr, "Failed to process package."); 860 ExitOnFailure(hr, "Failed to process package.");
865 } 861 }
866 862
@@ -1126,10 +1122,11 @@ extern "C" HRESULT PlanExecutePackage(
1126 hr = AddCachePackage(pPlan, pPackage, phSyncpointEvent); 1122 hr = AddCachePackage(pPlan, pPackage, phSyncpointEvent);
1127 ExitOnFailure(hr, "Failed to plan cache package."); 1123 ExitOnFailure(hr, "Failed to plan cache package.");
1128 } 1124 }
1129 else if (BURN_CACHE_STATE_COMPLETE != pPackage->cache && NeedsCache(pPackage, FALSE)) 1125 else if (!pPackage->fCached && NeedsCache(pPackage, FALSE))
1130 { 1126 {
1127 // TODO: this decision should be made during apply instead of plan based on whether the package is actually cached.
1131 // If the package is not in the cache, disable any rollback that would require the package from the cache. 1128 // If the package is not in the cache, disable any rollback that would require the package from the cache.
1132 LogId(REPORT_STANDARD, MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE, pPackage->sczId, LoggingCacheStateToString(pPackage->cache), LoggingActionStateToString(pPackage->rollback)); 1129 LogId(REPORT_STANDARD, MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE, pPackage->sczId, LoggingActionStateToString(pPackage->rollback));
1133 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 1130 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
1134 } 1131 }
1135 1132
@@ -1162,19 +1159,19 @@ extern "C" HRESULT PlanExecutePackage(
1162 switch (pPackage->type) 1159 switch (pPackage->type)
1163 { 1160 {
1164 case BURN_PACKAGE_TYPE_EXE: 1161 case BURN_PACKAGE_TYPE_EXE:
1165 hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent, pPackage->fAcquire); 1162 hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent);
1166 break; 1163 break;
1167 1164
1168 case BURN_PACKAGE_TYPE_MSI: 1165 case BURN_PACKAGE_TYPE_MSI:
1169 hr = MsiEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent, pPackage->fAcquire); 1166 hr = MsiEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent);
1170 break; 1167 break;
1171 1168
1172 case BURN_PACKAGE_TYPE_MSP: 1169 case BURN_PACKAGE_TYPE_MSP:
1173 hr = MspEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent, pPackage->fAcquire); 1170 hr = MspEnginePlanAddPackage(display, pUserExperience, pPackage, pPlan, pLog, pVariables, *phSyncpointEvent);
1174 break; 1171 break;
1175 1172
1176 case BURN_PACKAGE_TYPE_MSU: 1173 case BURN_PACKAGE_TYPE_MSU:
1177 hr = MsuEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables, *phSyncpointEvent, pPackage->fAcquire); 1174 hr = MsuEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables, *phSyncpointEvent);
1178 break; 1175 break;
1179 1176
1180 default: 1177 default:
@@ -1368,7 +1365,6 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1368 __in BURN_PLAN* pPlan, 1365 __in BURN_PLAN* pPlan,
1369 __in BURN_LOGGING* pLog, 1366 __in BURN_LOGGING* pLog,
1370 __in BURN_VARIABLES* pVariables, 1367 __in BURN_VARIABLES* pVariables,
1371 __inout HANDLE* phSyncpointEvent,
1372 __in DWORD dwExecuteActionEarlyIndex 1368 __in DWORD dwExecuteActionEarlyIndex
1373 ) 1369 )
1374{ 1370{
@@ -1488,7 +1484,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1488 } 1484 }
1489 } 1485 }
1490 1486
1491 hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables, *phSyncpointEvent, FALSE); 1487 hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables, NULL);
1492 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId); 1488 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1493 1489
1494 // Calculate package states based on reference count for addon and patch related bundles. 1490 // Calculate package states based on reference count for addon and patch related bundles.
@@ -1560,11 +1556,8 @@ extern "C" HRESULT PlanCleanPackage(
1560 BOOL fPlanCleanPackage = FALSE; 1556 BOOL fPlanCleanPackage = FALSE;
1561 BURN_CLEAN_ACTION* pCleanAction = NULL; 1557 BURN_CLEAN_ACTION* pCleanAction = NULL;
1562 1558
1563 // The following is a complex set of logic that determines when a package should be cleaned 1559 // The following is a complex set of logic that determines when a package should be cleaned from the cache.
1564 // from the cache. Start by noting that we only clean if the package is being acquired or 1560 if (BURN_CACHE_TYPE_ALWAYS > pPackage->cacheType || BOOTSTRAPPER_ACTION_CACHE > pPlan->action)
1565 // already cached and the package is not supposed to always be cached.
1566 if ((pPackage->fAcquire || BURN_CACHE_STATE_PARTIAL == pPackage->cache || BURN_CACHE_STATE_COMPLETE == pPackage->cache) &&
1567 (BURN_CACHE_TYPE_ALWAYS > pPackage->cacheType || BOOTSTRAPPER_ACTION_CACHE > pPlan->action))
1568 { 1561 {
1569 // The following are all different reasons why the package should be cleaned from the cache. 1562 // The following are all different reasons why the package should be cleaned from the cache.
1570 // The else-ifs are used to make the conditions easier to see (rather than have them combined 1563 // The else-ifs are used to make the conditions easier to see (rather than have them combined
@@ -1607,7 +1600,7 @@ extern "C" HRESULT PlanCleanPackage(
1607 1600
1608 pCleanAction->pPackage = pPackage; 1601 pCleanAction->pPackage = pPackage;
1609 1602
1610 pPackage->fUncache = TRUE; 1603 pPackage->fPlannedUncache = TRUE;
1611 1604
1612 if (pPackage->fCanAffectRegistration) 1605 if (pPackage->fCanAffectRegistration)
1613 { 1606 {
@@ -1622,8 +1615,7 @@ LExit:
1622extern "C" HRESULT PlanExecuteCacheSyncAndRollback( 1615extern "C" HRESULT PlanExecuteCacheSyncAndRollback(
1623 __in BURN_PLAN* pPlan, 1616 __in BURN_PLAN* pPlan,
1624 __in BURN_PACKAGE* pPackage, 1617 __in BURN_PACKAGE* pPackage,
1625 __in HANDLE hCacheEvent, 1618 __in HANDLE hCacheEvent
1626 __in BOOL fPlanPackageCacheRollback
1627 ) 1619 )
1628{ 1620{
1629 HRESULT hr = S_OK; 1621 HRESULT hr = S_OK;
@@ -1635,17 +1627,14 @@ extern "C" HRESULT PlanExecuteCacheSyncAndRollback(
1635 pAction->type = BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT; 1627 pAction->type = BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT;
1636 pAction->syncpoint.hEvent = hCacheEvent; 1628 pAction->syncpoint.hEvent = hCacheEvent;
1637 1629
1638 if (fPlanPackageCacheRollback) 1630 hr = PlanAppendRollbackAction(pPlan, &pAction);
1639 { 1631 ExitOnFailure(hr, "Failed to append rollback action.");
1640 hr = PlanAppendRollbackAction(pPlan, &pAction);
1641 ExitOnFailure(hr, "Failed to append rollback action.");
1642 1632
1643 pAction->type = BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE; 1633 pAction->type = BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE;
1644 pAction->uncachePackage.pPackage = pPackage; 1634 pAction->uncachePackage.pPackage = pPackage;
1645 1635
1646 hr = PlanExecuteCheckpoint(pPlan); 1636 hr = PlanExecuteCheckpoint(pPlan);
1647 ExitOnFailure(hr, "Failed to append execute checkpoint for cache rollback."); 1637 ExitOnFailure(hr, "Failed to append execute checkpoint for cache rollback.");
1648 }
1649 1638
1650LExit: 1639LExit:
1651 return hr; 1640 return hr;
@@ -1895,8 +1884,8 @@ static void ResetPlannedPackageState(
1895 // Reset package state that is a result of planning. 1884 // Reset package state that is a result of planning.
1896 pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1885 pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1897 pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1886 pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1898 pPackage->fAcquire = FALSE; 1887 pPackage->fPlannedCache = FALSE;
1899 pPackage->fUncache = FALSE; 1888 pPackage->fPlannedUncache = FALSE;
1900 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; 1889 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
1901 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 1890 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
1902 pPackage->providerExecute = BURN_DEPENDENCY_ACTION_NONE; 1891 pPackage->providerExecute = BURN_DEPENDENCY_ACTION_NONE;
@@ -2191,10 +2180,7 @@ static HRESULT AddCachePackageHelper(
2191 2180
2192 ++pPlan->cOverallProgressTicksTotal; 2181 ++pPlan->cOverallProgressTicksTotal;
2193 2182
2194 // If the package was not already fully cached then note that we planned the cache here. Otherwise, we only 2183 pPackage->fPlannedCache = TRUE;
2195 // did cache operations to verify the cache is valid so we did not plan the acquisition of the package.
2196 pPackage->fAcquire = (BURN_CACHE_STATE_COMPLETE != pPackage->cache);
2197
2198 if (pPackage->fCanAffectRegistration) 2184 if (pPackage->fCanAffectRegistration)
2199 { 2185 {
2200 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 2186 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
diff --git a/src/engine/plan.h b/src/engine/plan.h
index 77f82e1f..0024b0aa 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -411,8 +411,7 @@ HRESULT PlanPackages(
411 __in BURN_VARIABLES* pVariables, 411 __in BURN_VARIABLES* pVariables,
412 __in BOOTSTRAPPER_DISPLAY display, 412 __in BOOTSTRAPPER_DISPLAY display,
413 __in BOOTSTRAPPER_RELATION_TYPE relationType, 413 __in BOOTSTRAPPER_RELATION_TYPE relationType,
414 __in_z_opt LPCWSTR wzLayoutDirectory, 414 __in_z_opt LPCWSTR wzLayoutDirectory
415 __inout HANDLE* phSyncpointEvent
416 ); 415 );
417HRESULT PlanRegistration( 416HRESULT PlanRegistration(
418 __in BURN_PLAN* pPlan, 417 __in BURN_PLAN* pPlan,
@@ -428,8 +427,7 @@ HRESULT PlanPassThroughBundle(
428 __in BURN_LOGGING* pLog, 427 __in BURN_LOGGING* pLog,
429 __in BURN_VARIABLES* pVariables, 428 __in BURN_VARIABLES* pVariables,
430 __in BOOTSTRAPPER_DISPLAY display, 429 __in BOOTSTRAPPER_DISPLAY display,
431 __in BOOTSTRAPPER_RELATION_TYPE relationType, 430 __in BOOTSTRAPPER_RELATION_TYPE relationType
432 __inout HANDLE* phSyncpointEvent
433 ); 431 );
434HRESULT PlanUpdateBundle( 432HRESULT PlanUpdateBundle(
435 __in BURN_USER_EXPERIENCE* pUX, 433 __in BURN_USER_EXPERIENCE* pUX,
@@ -438,8 +436,7 @@ HRESULT PlanUpdateBundle(
438 __in BURN_LOGGING* pLog, 436 __in BURN_LOGGING* pLog,
439 __in BURN_VARIABLES* pVariables, 437 __in BURN_VARIABLES* pVariables,
440 __in BOOTSTRAPPER_DISPLAY display, 438 __in BOOTSTRAPPER_DISPLAY display,
441 __in BOOTSTRAPPER_RELATION_TYPE relationType, 439 __in BOOTSTRAPPER_RELATION_TYPE relationType
442 __inout HANDLE* phSyncpointEvent
443 ); 440 );
444HRESULT PlanLayoutPackage( 441HRESULT PlanLayoutPackage(
445 __in BURN_PLAN* pPlan, 442 __in BURN_PLAN* pPlan,
@@ -475,7 +472,6 @@ HRESULT PlanRelatedBundlesComplete(
475 __in BURN_PLAN* pPlan, 472 __in BURN_PLAN* pPlan,
476 __in BURN_LOGGING* pLog, 473 __in BURN_LOGGING* pLog,
477 __in BURN_VARIABLES* pVariables, 474 __in BURN_VARIABLES* pVariables,
478 __inout HANDLE* phSyncpointEvent,
479 __in DWORD dwExecuteActionEarlyIndex 475 __in DWORD dwExecuteActionEarlyIndex
480 ); 476 );
481HRESULT PlanFinalizeActions( 477HRESULT PlanFinalizeActions(
@@ -488,8 +484,7 @@ HRESULT PlanCleanPackage(
488HRESULT PlanExecuteCacheSyncAndRollback( 484HRESULT PlanExecuteCacheSyncAndRollback(
489 __in BURN_PLAN* pPlan, 485 __in BURN_PLAN* pPlan,
490 __in BURN_PACKAGE* pPackage, 486 __in BURN_PACKAGE* pPackage,
491 __in HANDLE hCacheEvent, 487 __in HANDLE hCacheEvent
492 __in BOOL fPlanPackageCacheRollback
493 ); 488 );
494HRESULT PlanExecuteCheckpoint( 489HRESULT PlanExecuteCheckpoint(
495 __in BURN_PLAN* pPlan 490 __in BURN_PLAN* pPlan
diff --git a/src/engine/pseudobundle.cpp b/src/engine/pseudobundle.cpp
index 63300065..73fbb019 100644
--- a/src/engine/pseudobundle.cpp
+++ b/src/engine/pseudobundle.cpp
@@ -10,7 +10,7 @@ extern "C" HRESULT PseudoBundleInitialize(
10 __in_z LPCWSTR wzId, 10 __in_z LPCWSTR wzId,
11 __in BOOTSTRAPPER_RELATION_TYPE relationType, 11 __in BOOTSTRAPPER_RELATION_TYPE relationType,
12 __in BOOTSTRAPPER_PACKAGE_STATE state, 12 __in BOOTSTRAPPER_PACKAGE_STATE state,
13 __in BURN_CACHE_STATE cacheState, 13 __in BOOL fCached,
14 __in_z LPCWSTR wzFilePath, 14 __in_z LPCWSTR wzFilePath,
15 __in_z LPCWSTR wzLocalSource, 15 __in_z LPCWSTR wzLocalSource,
16 __in_z_opt LPCWSTR wzDownloadSource, 16 __in_z_opt LPCWSTR wzDownloadSource,
@@ -67,14 +67,14 @@ extern "C" HRESULT PseudoBundleInitialize(
67 memcpy_s(pPackage->rgPayloads->pPayload->pbHash, pPackage->rgPayloads->pPayload->cbHash, pbHash, cbHash); 67 memcpy_s(pPackage->rgPayloads->pPayload->pbHash, pPackage->rgPayloads->pPayload->cbHash, pbHash, cbHash);
68 } 68 }
69 69
70 pPackage->rgPayloads->fCached = BURN_CACHE_STATE_NONE < cacheState; 70 pPackage->rgPayloads->fCached = fCached;
71 71
72 pPackage->Exe.fPseudoBundle = TRUE; 72 pPackage->Exe.fPseudoBundle = TRUE;
73 73
74 pPackage->type = BURN_PACKAGE_TYPE_EXE; 74 pPackage->type = BURN_PACKAGE_TYPE_EXE;
75 pPackage->fPerMachine = fPerMachine; 75 pPackage->fPerMachine = fPerMachine;
76 pPackage->currentState = state; 76 pPackage->currentState = state;
77 pPackage->cache = cacheState; 77 pPackage->fCached = fCached;
78 pPackage->qwInstallSize = qwSize; 78 pPackage->qwInstallSize = qwSize;
79 pPackage->qwSize = qwSize; 79 pPackage->qwSize = qwSize;
80 pPackage->fVital = fVital; 80 pPackage->fVital = fVital;
@@ -216,7 +216,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
216 pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user. 216 pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user.
217 pPassthroughPackage->type = pPackage->type; 217 pPassthroughPackage->type = pPackage->type;
218 pPassthroughPackage->currentState = pPackage->currentState; 218 pPassthroughPackage->currentState = pPackage->currentState;
219 pPassthroughPackage->cache = pPackage->cache; 219 pPassthroughPackage->fCached = pPackage->fCached;
220 pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize; 220 pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize;
221 pPassthroughPackage->qwSize = pPackage->qwSize; 221 pPassthroughPackage->qwSize = pPackage->qwSize;
222 pPassthroughPackage->fVital = pPackage->fVital; 222 pPassthroughPackage->fVital = pPackage->fVital;
diff --git a/src/engine/pseudobundle.h b/src/engine/pseudobundle.h
index c7940976..9fb530aa 100644
--- a/src/engine/pseudobundle.h
+++ b/src/engine/pseudobundle.h
@@ -13,7 +13,7 @@ HRESULT PseudoBundleInitialize(
13 __in_z LPCWSTR wzId, 13 __in_z LPCWSTR wzId,
14 __in BOOTSTRAPPER_RELATION_TYPE relationType, 14 __in BOOTSTRAPPER_RELATION_TYPE relationType,
15 __in BOOTSTRAPPER_PACKAGE_STATE state, 15 __in BOOTSTRAPPER_PACKAGE_STATE state,
16 __in BURN_CACHE_STATE cacheState, 16 __in BOOL fCached,
17 __in_z LPCWSTR wzFilePath, 17 __in_z LPCWSTR wzFilePath,
18 __in_z LPCWSTR wzLocalSource, 18 __in_z LPCWSTR wzLocalSource,
19 __in_z_opt LPCWSTR wzDownloadSource, 19 __in_z_opt LPCWSTR wzDownloadSource,
diff --git a/src/engine/relatedbundle.cpp b/src/engine/relatedbundle.cpp
index a4948a88..6953c678 100644
--- a/src/engine/relatedbundle.cpp
+++ b/src/engine/relatedbundle.cpp
@@ -391,14 +391,14 @@ static HRESULT LoadRelatedBundleFromKey(
391 __in HKEY hkBundleId, 391 __in HKEY hkBundleId,
392 __in BOOL fPerMachine, 392 __in BOOL fPerMachine,
393 __in BOOTSTRAPPER_RELATION_TYPE relationType, 393 __in BOOTSTRAPPER_RELATION_TYPE relationType,
394 __inout BURN_RELATED_BUNDLE *pRelatedBundle 394 __inout BURN_RELATED_BUNDLE* pRelatedBundle
395 ) 395 )
396{ 396{
397 HRESULT hr = S_OK; 397 HRESULT hr = S_OK;
398 DWORD64 qwEngineVersion = 0; 398 DWORD64 qwEngineVersion = 0;
399 LPWSTR sczBundleVersion = NULL; 399 LPWSTR sczBundleVersion = NULL;
400 LPWSTR sczCachePath = NULL; 400 LPWSTR sczCachePath = NULL;
401 BURN_CACHE_STATE cacheState = BURN_CACHE_STATE_NONE; 401 BOOL fCached = FALSE;
402 DWORD64 qwFileSize = 0; 402 DWORD64 qwFileSize = 0;
403 BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; 403 BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
404 404
@@ -423,19 +423,16 @@ static HRESULT LoadRelatedBundleFromKey(
423 hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath); 423 hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath);
424 ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId); 424 ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId);
425 425
426 hr = FileSize(sczCachePath, reinterpret_cast<LONGLONG *>(&qwFileSize)); 426 if (FileExistsEx(sczCachePath, NULL))
427 if (SUCCEEDED(hr))
428 { 427 {
429 cacheState = BURN_CACHE_STATE_COMPLETE; 428 fCached = TRUE;
430 } 429 }
431 else if (E_FILENOTFOUND != hr) 430 else
432 { 431 {
433 cacheState = BURN_CACHE_STATE_PARTIAL; 432 LogId(REPORT_STANDARD, MSG_DETECT_RELATED_BUNDLE_NOT_CACHED, wzRelatedBundleId, sczCachePath);
434 LogId(REPORT_STANDARD, MSG_DETECT_RELATED_BUNDLE_NOT_FULLY_CACHED, wzRelatedBundleId, sczCachePath, hr);
435 } 433 }
436 hr = S_OK;
437 434
438 pRelatedBundle->fPlannable = BURN_CACHE_STATE_COMPLETE == cacheState; 435 pRelatedBundle->fPlannable = fCached;
439 436
440 hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY, &dependencyProvider.sczKey); 437 hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY, &dependencyProvider.sczKey);
441 if (E_FILENOTFOUND != hr) 438 if (E_FILENOTFOUND != hr)
@@ -464,7 +461,7 @@ static HRESULT LoadRelatedBundleFromKey(
464 pRelatedBundle->relationType = relationType; 461 pRelatedBundle->relationType = relationType;
465 462
466 hr = PseudoBundleInitialize(qwEngineVersion, &pRelatedBundle->package, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, 463 hr = PseudoBundleInitialize(qwEngineVersion, &pRelatedBundle->package, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType,
467 BOOTSTRAPPER_PACKAGE_STATE_PRESENT, cacheState, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, 464 BOOTSTRAPPER_PACKAGE_STATE_PRESENT, fCached, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE,
468 L"-quiet", L"-repair -quiet", L"-uninstall -quiet", 465 L"-quiet", L"-repair -quiet", L"-uninstall -quiet",
469 (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, 466 (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL,
470 NULL, 0); 467 NULL, 0);
diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp
index 2a34cb16..2ebbca74 100644
--- a/src/test/BurnUnitTest/PlanTest.cpp
+++ b/src/test/BurnUnitTest/PlanTest.cpp
@@ -127,7 +127,6 @@ namespace Bootstrapper
127 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 127 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
128 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); 128 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
129 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 129 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
130 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent);
131 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); 130 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
132 Assert::Equal(dwIndex, pPlan->cExecuteActions); 131 Assert::Equal(dwIndex, pPlan->cExecuteActions);
133 132
@@ -509,7 +508,6 @@ namespace Bootstrapper
509 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER); 508 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER);
510 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 509 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
511 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 510 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
512 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent);
513 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); 511 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
514 Assert::Equal(dwIndex, pPlan->cExecuteActions); 512 Assert::Equal(dwIndex, pPlan->cExecuteActions);
515 513
@@ -593,6 +591,7 @@ namespace Bootstrapper
593 Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); 591 Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal);
594 592
595 dwIndex = 0; 593 dwIndex = 0;
594 ValidateCleanAction(pPlan, dwIndex++, L"PackageA");
596 Assert::Equal(dwIndex, pPlan->cCleanActions); 595 Assert::Equal(dwIndex, pPlan->cCleanActions);
597 596
598 UINT uIndex = 0; 597 UINT uIndex = 0;
@@ -1042,7 +1041,7 @@ namespace Bootstrapper
1042 void DetectPackageAsPresentAndCached(BURN_PACKAGE* pPackage) 1041 void DetectPackageAsPresentAndCached(BURN_PACKAGE* pPackage)
1043 { 1042 {
1044 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; 1043 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
1045 pPackage->cache = BURN_CACHE_STATE_COMPLETE; 1044 pPackage->fCached = TRUE;
1046 if (pPackage->fCanAffectRegistration) 1045 if (pPackage->fCanAffectRegistration)
1047 { 1046 {
1048 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 1047 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
@@ -1158,7 +1157,7 @@ namespace Bootstrapper
1158 pRelatedBundle->fPlannable = TRUE; 1157 pRelatedBundle->fPlannable = TRUE;
1159 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; 1158 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1160 1159
1161 hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, BURN_CACHE_STATE_COMPLETE, NULL, NULL, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0); 1160 hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, TRUE, NULL, NULL, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0);
1162 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); 1161 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
1163 1162
1164 ++pRelatedBundles->cRelatedBundles; 1163 ++pRelatedBundles->cRelatedBundles;