From af68033509730ffe01602f839861a47287bb709f Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 10 Mar 2021 18:18:38 -0600 Subject: Handle when related bundles have an uninstall key but aren't cached. #4991 --- .../inc/BootstrapperApplication.h | 2 + src/engine/core.cpp | 39 ++++++--- src/engine/dependency.cpp | 8 +- src/engine/detect.cpp | 17 ++-- src/engine/engine.mc | 11 ++- src/engine/externalengine.cpp | 2 +- src/engine/plan.cpp | 11 +++ src/engine/pseudobundle.cpp | 5 +- src/engine/pseudobundle.h | 1 + src/engine/registration.h | 1 + src/engine/relatedbundle.cpp | 16 +++- src/engine/userexperience.cpp | 8 +- src/engine/userexperience.h | 6 +- src/test/BurnUnitTest/PlanTest.cpp | 95 +++++++++++++++++++++- 14 files changed, 188 insertions(+), 34 deletions(-) diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h index c3242167..fb4b6ea3 100644 --- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h +++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h @@ -491,6 +491,7 @@ struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_ARGS LPCWSTR wzBundleTag; BOOL fPerMachine; LPCWSTR wzVersion; + BOOL fMissingFromCache; }; struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS @@ -547,6 +548,7 @@ struct BA_ONDETECTRELATEDBUNDLE_ARGS BOOL fPerMachine; LPCWSTR wzVersion; BOOTSTRAPPER_RELATED_OPERATION operation; + BOOL fMissingFromCache; }; struct BA_ONDETECTRELATEDBUNDLE_RESULTS diff --git a/src/engine/core.cpp b/src/engine/core.cpp index eb8a84fe..50ed6ea0 100644 --- a/src/engine/core.cpp +++ b/src/engine/core.cpp @@ -59,6 +59,10 @@ static void LogPackages( __in const BURN_RELATED_BUNDLES* pRelatedBundles, __in const BOOTSTRAPPER_ACTION action ); +static void LogRelatedBundles( + __in const BURN_RELATED_BUNDLES* pRelatedBundles, + __in BOOL fReverse + ); // function definitions @@ -1793,15 +1797,9 @@ static void LogPackages( else { // Display related bundles first if uninstalling. - if (BOOTSTRAPPER_ACTION_UNINSTALL == action && 0 < pRelatedBundles->cRelatedBundles) + if (BOOTSTRAPPER_ACTION_UNINSTALL == action) { - for (int i = pRelatedBundles->cRelatedBundles - 1; 0 <= i; --i) - { - const BURN_RELATED_BUNDLE* pRelatedBundle = &pRelatedBundles->rgRelatedBundles[i]; - const BURN_PACKAGE* pPackage = &pRelatedBundle->package; - - LogId(REPORT_STANDARD, MSG_PLANNED_RELATED_BUNDLE, pPackage->sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingDependencyActionToString(pPackage->dependencyExecute)); - } + LogRelatedBundles(pRelatedBundles, TRUE); } // Display all the packages in the log. @@ -1852,13 +1850,28 @@ static void LogPackages( } // Display related bundles last if caching, installing, modifying, or repairing. - if (BOOTSTRAPPER_ACTION_UNINSTALL < action && 0 < pRelatedBundles->cRelatedBundles) + if (BOOTSTRAPPER_ACTION_UNINSTALL < action) { - for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) - { - const BURN_RELATED_BUNDLE* pRelatedBundle = &pRelatedBundles->rgRelatedBundles[i]; - const BURN_PACKAGE* pPackage = &pRelatedBundle->package; + LogRelatedBundles(pRelatedBundles, FALSE); + } + } +} + +static void LogRelatedBundles( + __in const BURN_RELATED_BUNDLES* pRelatedBundles, + __in BOOL fReverse + ) +{ + if (0 < pRelatedBundles->cRelatedBundles) + { + for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) + { + const DWORD iRelatedBundle = fReverse ? pRelatedBundles->cRelatedBundles - 1 - i : i; + const BURN_RELATED_BUNDLE* pRelatedBundle = pRelatedBundles->rgRelatedBundles + iRelatedBundle; + const BURN_PACKAGE* pPackage = &pRelatedBundle->package; + if (pRelatedBundle->fPlannable) + { LogId(REPORT_STANDARD, MSG_PLANNED_RELATED_BUNDLE, pPackage->sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingDependencyActionToString(pPackage->dependencyExecute)); } } diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp index 9ab76551..51aca239 100644 --- a/src/engine/dependency.cpp +++ b/src/engine/dependency.cpp @@ -260,7 +260,13 @@ extern "C" HRESULT DependencyDetect( for (DWORD iRelatedBundle = 0; iRelatedBundle < pEngineState->registration.relatedBundles.cRelatedBundles; ++iRelatedBundle) { - pPackage = &pEngineState->registration.relatedBundles.rgRelatedBundles[iRelatedBundle].package; + BURN_RELATED_BUNDLE* pRelatedBundle = pEngineState->registration.relatedBundles.rgRelatedBundles + iRelatedBundle; + if (!pRelatedBundle->fPlannable) + { + continue; + } + + pPackage = &pRelatedBundle->package; hr = DetectPackageDependents(pPackage, sdIgnoredDependents, pRegistration); ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId); } diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp index 74e8b9ca..8ca74986 100644 --- a/src/engine/detect.cpp +++ b/src/engine/detect.cpp @@ -143,13 +143,16 @@ extern "C" HRESULT DetectForwardCompatibleBundles( if (nCompareResult <= 0) { - pRelatedBundle->fForwardCompatible = TRUE; - pRegistration->fForwardCompatibleBundleExists = TRUE; + if (pRelatedBundle->fPlannable) + { + pRelatedBundle->fForwardCompatible = TRUE; + pRegistration->fForwardCompatibleBundleExists = TRUE; + } - hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion); + hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, BURN_CACHE_STATE_COMPLETE != pRelatedBundle->package.cache); ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); - LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion); + 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)); } } } @@ -222,13 +225,13 @@ extern "C" HRESULT DetectReportRelatedBundles( break; } - LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingRelatedOperationToString(operation)); + 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)); - hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation); + hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation, BURN_CACHE_STATE_COMPLETE != pRelatedBundle->package.cache); ExitOnRootFailure(hr, "BA aborted detect related bundle."); // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle. - if (*pfEligibleForCleanup) + if (*pfEligibleForCleanup && pRelatedBundle->fPlannable) { uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, BOOTSTRAPPER_ACTION_UNINSTALL, pRegistration->pVersion, pRelatedBundle->pVersion, &uninstallRequestState); diff --git a/src/engine/engine.mc b/src/engine/engine.mc index 687d2b60..a793540a 100644 --- a/src/engine/engine.mc +++ b/src/engine/engine.mc @@ -202,7 +202,7 @@ MessageId=102 Severity=Success SymbolicName=MSG_DETECTED_RELATED_BUNDLE Language=English -Detected related bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, operation: %5!hs! +Detected related bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, operation: %5!hs!, cached: %6!hs! . MessageId=103 @@ -237,7 +237,14 @@ MessageId=107 Severity=Success SymbolicName=MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE Language=English -Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls! +Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, cached: %5!hs! +. + +MessageId=108 +Severity=Warning +SymbolicName=MSG_DETECT_RELATED_BUNDLE_NOT_FULLY_CACHED +Language=English +Detected partially cached related bundle: %1!ls!, cache path: %2!ls!, reason: 0x%3!x! . MessageId=120 diff --git a/src/engine/externalengine.cpp b/src/engine/externalengine.cpp index 26ab9fba..d881544c 100644 --- a/src/engine/externalengine.cpp +++ b/src/engine/externalengine.cpp @@ -327,7 +327,7 @@ HRESULT ExternalEngineSetUpdate( sczId = pEngineState->registration.sczId; } - hr = PseudoBundleInitialize(FILEMAKEVERSION(rmj, rmm, rup, rpr), &pEngineState->update.package, FALSE, sczId, BOOTSTRAPPER_RELATION_UPDATE, BOOTSTRAPPER_PACKAGE_STATE_ABSENT, pEngineState->registration.sczExecutableName, sczLocalSource ? sczLocalSource : wzLocalSource, wzDownloadSource, qwSize, TRUE, sczCommandline, NULL, NULL, NULL, rgbHash, cbHash); + 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); ExitOnFailure(hr, "Failed to set update bundle."); pEngineState->update.fUpdateAvailable = TRUE; diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 87607382..a4b8d0c1 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp @@ -1292,6 +1292,12 @@ extern "C" HRESULT PlanRelatedBundlesBegin( for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) { BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; + + if (!pRelatedBundle->fPlannable) + { + continue; + } + pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; @@ -1417,6 +1423,11 @@ extern "C" HRESULT PlanRelatedBundlesComplete( DWORD *pdwInsertIndex = NULL; BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; + if (!pRelatedBundle->fPlannable) + { + continue; + } + // Do not execute if a major upgrade to the related bundle is an embedded bundle (Provider keys are the same) if (0 < pRelatedBundle->package.cDependencyProviders) { diff --git a/src/engine/pseudobundle.cpp b/src/engine/pseudobundle.cpp index 3b05ea0b..63300065 100644 --- a/src/engine/pseudobundle.cpp +++ b/src/engine/pseudobundle.cpp @@ -10,6 +10,7 @@ extern "C" HRESULT PseudoBundleInitialize( __in_z LPCWSTR wzId, __in BOOTSTRAPPER_RELATION_TYPE relationType, __in BOOTSTRAPPER_PACKAGE_STATE state, + __in BURN_CACHE_STATE cacheState, __in_z LPCWSTR wzFilePath, __in_z LPCWSTR wzLocalSource, __in_z_opt LPCWSTR wzDownloadSource, @@ -66,14 +67,14 @@ extern "C" HRESULT PseudoBundleInitialize( memcpy_s(pPackage->rgPayloads->pPayload->pbHash, pPackage->rgPayloads->pPayload->cbHash, pbHash, cbHash); } - pPackage->rgPayloads->fCached = (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_CACHED == state); + pPackage->rgPayloads->fCached = BURN_CACHE_STATE_NONE < cacheState; pPackage->Exe.fPseudoBundle = TRUE; pPackage->type = BURN_PACKAGE_TYPE_EXE; pPackage->fPerMachine = fPerMachine; pPackage->currentState = state; - pPackage->cache = (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_CACHED == state) ? BURN_CACHE_STATE_COMPLETE : BURN_CACHE_STATE_NONE; + pPackage->cache = cacheState; pPackage->qwInstallSize = qwSize; pPackage->qwSize = qwSize; pPackage->fVital = fVital; diff --git a/src/engine/pseudobundle.h b/src/engine/pseudobundle.h index 3b8157a0..c7940976 100644 --- a/src/engine/pseudobundle.h +++ b/src/engine/pseudobundle.h @@ -13,6 +13,7 @@ HRESULT PseudoBundleInitialize( __in_z LPCWSTR wzId, __in BOOTSTRAPPER_RELATION_TYPE relationType, __in BOOTSTRAPPER_PACKAGE_STATE state, + __in BURN_CACHE_STATE cacheState, __in_z LPCWSTR wzFilePath, __in_z LPCWSTR wzLocalSource, __in_z_opt LPCWSTR wzDownloadSource, diff --git a/src/engine/registration.h b/src/engine/registration.h index bb87b6e9..e0418fa3 100644 --- a/src/engine/registration.h +++ b/src/engine/registration.h @@ -62,6 +62,7 @@ typedef struct _BURN_RELATED_BUNDLE VERUTIL_VERSION* pVersion; LPWSTR sczTag; + BOOL fPlannable; BURN_PACKAGE package; } BURN_RELATED_BUNDLE; diff --git a/src/engine/relatedbundle.cpp b/src/engine/relatedbundle.cpp index bc79b954..a4948a88 100644 --- a/src/engine/relatedbundle.cpp +++ b/src/engine/relatedbundle.cpp @@ -398,6 +398,7 @@ static HRESULT LoadRelatedBundleFromKey( DWORD64 qwEngineVersion = 0; LPWSTR sczBundleVersion = NULL; LPWSTR sczCachePath = NULL; + BURN_CACHE_STATE cacheState = BURN_CACHE_STATE_NONE; DWORD64 qwFileSize = 0; BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; @@ -423,7 +424,18 @@ static HRESULT LoadRelatedBundleFromKey( ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId); hr = FileSize(sczCachePath, reinterpret_cast(&qwFileSize)); - ExitOnFailure(hr, "Failed to get size of pseudo bundle: %ls", sczCachePath); + if (SUCCEEDED(hr)) + { + cacheState = BURN_CACHE_STATE_COMPLETE; + } + else if (E_FILENOTFOUND != hr) + { + cacheState = BURN_CACHE_STATE_PARTIAL; + LogId(REPORT_STANDARD, MSG_DETECT_RELATED_BUNDLE_NOT_FULLY_CACHED, wzRelatedBundleId, sczCachePath, hr); + } + hr = S_OK; + + pRelatedBundle->fPlannable = BURN_CACHE_STATE_COMPLETE == cacheState; hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY, &dependencyProvider.sczKey); if (E_FILENOTFOUND != hr) @@ -452,7 +464,7 @@ static HRESULT LoadRelatedBundleFromKey( pRelatedBundle->relationType = relationType; hr = PseudoBundleInitialize(qwEngineVersion, &pRelatedBundle->package, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, - BOOTSTRAPPER_PACKAGE_STATE_PRESENT, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, + BOOTSTRAPPER_PACKAGE_STATE_PRESENT, cacheState, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, NULL, 0); diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp index e1e32a87..ad1529ea 100644 --- a/src/engine/userexperience.cpp +++ b/src/engine/userexperience.cpp @@ -763,7 +763,8 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, - __in VERUTIL_VERSION* pVersion + __in VERUTIL_VERSION* pVersion, + __in BOOL fMissingFromCache ) { HRESULT hr = S_OK; @@ -776,6 +777,7 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle( args.wzBundleTag = wzBundleTag; args.fPerMachine = fPerMachine; args.wzVersion = pVersion->sczVersion; + args.fMissingFromCache = fMissingFromCache; results.cbSize = sizeof(results); @@ -879,7 +881,8 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, __in VERUTIL_VERSION* pVersion, - __in BOOTSTRAPPER_RELATED_OPERATION operation + __in BOOTSTRAPPER_RELATED_OPERATION operation, + __in BOOL fMissingFromCache ) { HRESULT hr = S_OK; @@ -893,6 +896,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( args.fPerMachine = fPerMachine; args.wzVersion = pVersion->sczVersion; args.operation = operation; + args.fMissingFromCache = fMissingFromCache; results.cbSize = sizeof(results); diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h index eccc0786..bac79e33 100644 --- a/src/engine/userexperience.h +++ b/src/engine/userexperience.h @@ -200,7 +200,8 @@ BAAPI UserExperienceOnDetectForwardCompatibleBundle( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, - __in VERUTIL_VERSION* pVersion + __in VERUTIL_VERSION* pVersion, + __in BOOL fMissingFromCache ); BAAPI UserExperienceOnDetectMsiFeature( __in BURN_USER_EXPERIENCE* pUserExperience, @@ -225,7 +226,8 @@ BAAPI UserExperienceOnDetectRelatedBundle( __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, __in VERUTIL_VERSION* pVersion, - __in BOOTSTRAPPER_RELATED_OPERATION operation + __in BOOTSTRAPPER_RELATED_OPERATION operation, + __in BOOL fMissingFromCache ); BAAPI UserExperienceOnDetectRelatedMsiPackage( __in BURN_USER_EXPERIENCE* pUserExperience, diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp index 40a61fe3..2a34cb16 100644 --- a/src/test/BurnUnitTest/PlanTest.cpp +++ b/src/test/BurnUnitTest/PlanTest.cpp @@ -292,6 +292,94 @@ namespace Bootstrapper ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[2], L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT); } + [Fact] + void RelatedBundleMissingFromCacheTest() + { + HRESULT hr = S_OK; + BURN_ENGINE_STATE engineState = { }; + BURN_ENGINE_STATE* pEngineState = &engineState; + BURN_PLAN* pPlan = &engineState.plan; + + InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); + DetectAttachedContainerAsAttached(pEngineState); + DetectPackagesAsAbsent(pEngineState); + BURN_RELATED_BUNDLE* pRelatedBundle = DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); + pRelatedBundle->fPlannable = FALSE; + + hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL); + NativeAssert::Succeeded(hr, "CorePlan failed"); + + Assert::Equal(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action); + Assert::Equal(TRUE, pPlan->fPerMachine); + Assert::Equal(FALSE, pPlan->fDisableRollback); + + BOOL fRollback = FALSE; + DWORD dwIndex = 0; + DWORD dwPackageStart = 0; + ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); + ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); + ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart); + ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart); + ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); + ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE); + Assert::Equal(dwIndex, pPlan->cCacheActions); + + fRollback = TRUE; + dwIndex = 0; + ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); + ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); + Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); + + Assert::Equal(35694ull, pPlan->qwEstimatedSize); + Assert::Equal(33743ull, pPlan->qwCacheSizeTotal); + + fRollback = FALSE; + dwIndex = 0; + DWORD dwExecuteCheckpointId = 2; + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); + ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + Assert::Equal(dwIndex, pPlan->cExecuteActions); + + fRollback = TRUE; + dwIndex = 0; + dwExecuteCheckpointId = 2; + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); + ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + Assert::Equal(dwIndex, pPlan->cRollbackActions); + + Assert::Equal(1ul, pPlan->cExecutePackagesTotal); + Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); + + dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cCleanActions); + + UINT uIndex = 0; + ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL); + Assert::Equal(uIndex, pPlan->cPlannedProviders); + + Assert::Equal(1ul, pEngineState->packages.cPackages); + ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT); + } + [Fact] void SingleMsiCacheTest() { @@ -1041,7 +1129,7 @@ namespace Bootstrapper } } - void DetectUpgradeBundle( + BURN_RELATED_BUNDLE* DetectUpgradeBundle( __in BURN_ENGINE_STATE* pEngineState, __in LPCWSTR wzId, __in LPCWSTR wzVersion @@ -1067,12 +1155,15 @@ namespace Bootstrapper hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion); NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion); + pRelatedBundle->fPlannable = TRUE; pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; - hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, NULL, NULL, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0); + 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); NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); ++pRelatedBundles->cRelatedBundles; + + return pRelatedBundle; } void DetectAsRelatedUpgradeBundle( -- cgit v1.2.3-55-g6feb