aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-04-16 09:40:18 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-04-19 23:12:55 -0500
commit941c47e5a3f57ce9626b447a95740b1444e69343 (patch)
tree6225b78f5fc7c8f88a2abf187a6a76d45b36ec26
parentd32f770ca05748df9e356444c7e617d5eeedb60c (diff)
downloadwix-941c47e5a3f57ce9626b447a95740b1444e69343.tar.gz
wix-941c47e5a3f57ce9626b447a95740b1444e69343.tar.bz2
wix-941c47e5a3f57ce9626b447a95740b1444e69343.zip
Detect a package as cached if any of its payloads exist.
Detect is supposed to be fast, so it can't fully verify every payload for every package. The engine was wasting its time by trying to verify file sizes without the hash. Even worse, it was making decisions during planning based on that insufficient verification. Contributes to #3640
-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;