diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-03-10 18:18:38 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-03-11 20:24:18 -0600 |
commit | af68033509730ffe01602f839861a47287bb709f (patch) | |
tree | 2960f6cdd023e74a4ca2bbc49d0294b7bfbed5c5 | |
parent | 10ef9d5bfbf81f454113a1c2716009831a916222 (diff) | |
download | wix-af68033509730ffe01602f839861a47287bb709f.tar.gz wix-af68033509730ffe01602f839861a47287bb709f.tar.bz2 wix-af68033509730ffe01602f839861a47287bb709f.zip |
Handle when related bundles have an uninstall key but aren't cached.
#4991
-rw-r--r-- | src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h | 2 | ||||
-rw-r--r-- | src/engine/core.cpp | 39 | ||||
-rw-r--r-- | src/engine/dependency.cpp | 8 | ||||
-rw-r--r-- | src/engine/detect.cpp | 17 | ||||
-rw-r--r-- | src/engine/engine.mc | 11 | ||||
-rw-r--r-- | src/engine/externalengine.cpp | 2 | ||||
-rw-r--r-- | src/engine/plan.cpp | 11 | ||||
-rw-r--r-- | src/engine/pseudobundle.cpp | 5 | ||||
-rw-r--r-- | src/engine/pseudobundle.h | 1 | ||||
-rw-r--r-- | src/engine/registration.h | 1 | ||||
-rw-r--r-- | src/engine/relatedbundle.cpp | 16 | ||||
-rw-r--r-- | src/engine/userexperience.cpp | 8 | ||||
-rw-r--r-- | src/engine/userexperience.h | 6 | ||||
-rw-r--r-- | 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 | |||
491 | LPCWSTR wzBundleTag; | 491 | LPCWSTR wzBundleTag; |
492 | BOOL fPerMachine; | 492 | BOOL fPerMachine; |
493 | LPCWSTR wzVersion; | 493 | LPCWSTR wzVersion; |
494 | BOOL fMissingFromCache; | ||
494 | }; | 495 | }; |
495 | 496 | ||
496 | struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS | 497 | struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS |
@@ -547,6 +548,7 @@ struct BA_ONDETECTRELATEDBUNDLE_ARGS | |||
547 | BOOL fPerMachine; | 548 | BOOL fPerMachine; |
548 | LPCWSTR wzVersion; | 549 | LPCWSTR wzVersion; |
549 | BOOTSTRAPPER_RELATED_OPERATION operation; | 550 | BOOTSTRAPPER_RELATED_OPERATION operation; |
551 | BOOL fMissingFromCache; | ||
550 | }; | 552 | }; |
551 | 553 | ||
552 | struct BA_ONDETECTRELATEDBUNDLE_RESULTS | 554 | 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( | |||
59 | __in const BURN_RELATED_BUNDLES* pRelatedBundles, | 59 | __in const BURN_RELATED_BUNDLES* pRelatedBundles, |
60 | __in const BOOTSTRAPPER_ACTION action | 60 | __in const BOOTSTRAPPER_ACTION action |
61 | ); | 61 | ); |
62 | static void LogRelatedBundles( | ||
63 | __in const BURN_RELATED_BUNDLES* pRelatedBundles, | ||
64 | __in BOOL fReverse | ||
65 | ); | ||
62 | 66 | ||
63 | 67 | ||
64 | // function definitions | 68 | // function definitions |
@@ -1793,15 +1797,9 @@ static void LogPackages( | |||
1793 | else | 1797 | else |
1794 | { | 1798 | { |
1795 | // Display related bundles first if uninstalling. | 1799 | // Display related bundles first if uninstalling. |
1796 | if (BOOTSTRAPPER_ACTION_UNINSTALL == action && 0 < pRelatedBundles->cRelatedBundles) | 1800 | if (BOOTSTRAPPER_ACTION_UNINSTALL == action) |
1797 | { | 1801 | { |
1798 | for (int i = pRelatedBundles->cRelatedBundles - 1; 0 <= i; --i) | 1802 | LogRelatedBundles(pRelatedBundles, TRUE); |
1799 | { | ||
1800 | const BURN_RELATED_BUNDLE* pRelatedBundle = &pRelatedBundles->rgRelatedBundles[i]; | ||
1801 | const BURN_PACKAGE* pPackage = &pRelatedBundle->package; | ||
1802 | |||
1803 | 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)); | ||
1804 | } | ||
1805 | } | 1803 | } |
1806 | 1804 | ||
1807 | // Display all the packages in the log. | 1805 | // Display all the packages in the log. |
@@ -1852,13 +1850,28 @@ static void LogPackages( | |||
1852 | } | 1850 | } |
1853 | 1851 | ||
1854 | // Display related bundles last if caching, installing, modifying, or repairing. | 1852 | // Display related bundles last if caching, installing, modifying, or repairing. |
1855 | if (BOOTSTRAPPER_ACTION_UNINSTALL < action && 0 < pRelatedBundles->cRelatedBundles) | 1853 | if (BOOTSTRAPPER_ACTION_UNINSTALL < action) |
1856 | { | 1854 | { |
1857 | for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) | 1855 | LogRelatedBundles(pRelatedBundles, FALSE); |
1858 | { | 1856 | } |
1859 | const BURN_RELATED_BUNDLE* pRelatedBundle = &pRelatedBundles->rgRelatedBundles[i]; | 1857 | } |
1860 | const BURN_PACKAGE* pPackage = &pRelatedBundle->package; | 1858 | } |
1859 | |||
1860 | static void LogRelatedBundles( | ||
1861 | __in const BURN_RELATED_BUNDLES* pRelatedBundles, | ||
1862 | __in BOOL fReverse | ||
1863 | ) | ||
1864 | { | ||
1865 | if (0 < pRelatedBundles->cRelatedBundles) | ||
1866 | { | ||
1867 | for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) | ||
1868 | { | ||
1869 | const DWORD iRelatedBundle = fReverse ? pRelatedBundles->cRelatedBundles - 1 - i : i; | ||
1870 | const BURN_RELATED_BUNDLE* pRelatedBundle = pRelatedBundles->rgRelatedBundles + iRelatedBundle; | ||
1871 | const BURN_PACKAGE* pPackage = &pRelatedBundle->package; | ||
1861 | 1872 | ||
1873 | if (pRelatedBundle->fPlannable) | ||
1874 | { | ||
1862 | 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)); | 1875 | 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)); |
1863 | } | 1876 | } |
1864 | } | 1877 | } |
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( | |||
260 | 260 | ||
261 | for (DWORD iRelatedBundle = 0; iRelatedBundle < pEngineState->registration.relatedBundles.cRelatedBundles; ++iRelatedBundle) | 261 | for (DWORD iRelatedBundle = 0; iRelatedBundle < pEngineState->registration.relatedBundles.cRelatedBundles; ++iRelatedBundle) |
262 | { | 262 | { |
263 | pPackage = &pEngineState->registration.relatedBundles.rgRelatedBundles[iRelatedBundle].package; | 263 | BURN_RELATED_BUNDLE* pRelatedBundle = pEngineState->registration.relatedBundles.rgRelatedBundles + iRelatedBundle; |
264 | if (!pRelatedBundle->fPlannable) | ||
265 | { | ||
266 | continue; | ||
267 | } | ||
268 | |||
269 | pPackage = &pRelatedBundle->package; | ||
264 | hr = DetectPackageDependents(pPackage, sdIgnoredDependents, pRegistration); | 270 | hr = DetectPackageDependents(pPackage, sdIgnoredDependents, pRegistration); |
265 | ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId); | 271 | ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId); |
266 | } | 272 | } |
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( | |||
143 | 143 | ||
144 | if (nCompareResult <= 0) | 144 | if (nCompareResult <= 0) |
145 | { | 145 | { |
146 | pRelatedBundle->fForwardCompatible = TRUE; | 146 | if (pRelatedBundle->fPlannable) |
147 | pRegistration->fForwardCompatibleBundleExists = TRUE; | 147 | { |
148 | pRelatedBundle->fForwardCompatible = TRUE; | ||
149 | pRegistration->fForwardCompatibleBundleExists = TRUE; | ||
150 | } | ||
148 | 151 | ||
149 | hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion); | 152 | hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, BURN_CACHE_STATE_COMPLETE != pRelatedBundle->package.cache); |
150 | ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); | 153 | ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); |
151 | 154 | ||
152 | LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion); | 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)); |
153 | } | 156 | } |
154 | } | 157 | } |
155 | } | 158 | } |
@@ -222,13 +225,13 @@ extern "C" HRESULT DetectReportRelatedBundles( | |||
222 | break; | 225 | break; |
223 | } | 226 | } |
224 | 227 | ||
225 | LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingRelatedOperationToString(operation)); | 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)); |
226 | 229 | ||
227 | hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation); | 230 | hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation, BURN_CACHE_STATE_COMPLETE != pRelatedBundle->package.cache); |
228 | ExitOnRootFailure(hr, "BA aborted detect related bundle."); | 231 | ExitOnRootFailure(hr, "BA aborted detect related bundle."); |
229 | 232 | ||
230 | // 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. |
231 | if (*pfEligibleForCleanup) | 234 | if (*pfEligibleForCleanup && pRelatedBundle->fPlannable) |
232 | { | 235 | { |
233 | uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; | 236 | uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; |
234 | hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, BOOTSTRAPPER_ACTION_UNINSTALL, pRegistration->pVersion, pRelatedBundle->pVersion, &uninstallRequestState); | 237 | 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 | |||
202 | Severity=Success | 202 | Severity=Success |
203 | SymbolicName=MSG_DETECTED_RELATED_BUNDLE | 203 | SymbolicName=MSG_DETECTED_RELATED_BUNDLE |
204 | Language=English | 204 | Language=English |
205 | Detected related bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, operation: %5!hs! | 205 | Detected related bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, operation: %5!hs!, cached: %6!hs! |
206 | . | 206 | . |
207 | 207 | ||
208 | MessageId=103 | 208 | MessageId=103 |
@@ -237,7 +237,14 @@ MessageId=107 | |||
237 | Severity=Success | 237 | Severity=Success |
238 | SymbolicName=MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE | 238 | SymbolicName=MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE |
239 | Language=English | 239 | Language=English |
240 | Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls! | 240 | Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, cached: %5!hs! |
241 | . | ||
242 | |||
243 | MessageId=108 | ||
244 | Severity=Warning | ||
245 | SymbolicName=MSG_DETECT_RELATED_BUNDLE_NOT_FULLY_CACHED | ||
246 | Language=English | ||
247 | Detected partially cached related bundle: %1!ls!, cache path: %2!ls!, reason: 0x%3!x! | ||
241 | . | 248 | . |
242 | 249 | ||
243 | MessageId=120 | 250 | 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( | |||
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, 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, BURN_CACHE_STATE_NONE, 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/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( | |||
1292 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) | 1292 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) |
1293 | { | 1293 | { |
1294 | BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; | 1294 | BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; |
1295 | |||
1296 | if (!pRelatedBundle->fPlannable) | ||
1297 | { | ||
1298 | continue; | ||
1299 | } | ||
1300 | |||
1295 | pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; | 1301 | pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; |
1296 | pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; | 1302 | pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; |
1297 | 1303 | ||
@@ -1417,6 +1423,11 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1417 | DWORD *pdwInsertIndex = NULL; | 1423 | DWORD *pdwInsertIndex = NULL; |
1418 | BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; | 1424 | BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; |
1419 | 1425 | ||
1426 | if (!pRelatedBundle->fPlannable) | ||
1427 | { | ||
1428 | continue; | ||
1429 | } | ||
1430 | |||
1420 | // Do not execute if a major upgrade to the related bundle is an embedded bundle (Provider keys are the same) | 1431 | // Do not execute if a major upgrade to the related bundle is an embedded bundle (Provider keys are the same) |
1421 | if (0 < pRelatedBundle->package.cDependencyProviders) | 1432 | if (0 < pRelatedBundle->package.cDependencyProviders) |
1422 | { | 1433 | { |
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( | |||
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_z LPCWSTR wzFilePath, | 14 | __in_z LPCWSTR wzFilePath, |
14 | __in_z LPCWSTR wzLocalSource, | 15 | __in_z LPCWSTR wzLocalSource, |
15 | __in_z_opt LPCWSTR wzDownloadSource, | 16 | __in_z_opt LPCWSTR wzDownloadSource, |
@@ -66,14 +67,14 @@ extern "C" HRESULT PseudoBundleInitialize( | |||
66 | 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); |
67 | } | 68 | } |
68 | 69 | ||
69 | pPackage->rgPayloads->fCached = (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_CACHED == state); | 70 | pPackage->rgPayloads->fCached = BURN_CACHE_STATE_NONE < cacheState; |
70 | 71 | ||
71 | pPackage->Exe.fPseudoBundle = TRUE; | 72 | pPackage->Exe.fPseudoBundle = TRUE; |
72 | 73 | ||
73 | pPackage->type = BURN_PACKAGE_TYPE_EXE; | 74 | pPackage->type = BURN_PACKAGE_TYPE_EXE; |
74 | pPackage->fPerMachine = fPerMachine; | 75 | pPackage->fPerMachine = fPerMachine; |
75 | pPackage->currentState = state; | 76 | pPackage->currentState = state; |
76 | pPackage->cache = (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_CACHED == state) ? BURN_CACHE_STATE_COMPLETE : BURN_CACHE_STATE_NONE; | 77 | pPackage->cache = cacheState; |
77 | pPackage->qwInstallSize = qwSize; | 78 | pPackage->qwInstallSize = qwSize; |
78 | pPackage->qwSize = qwSize; | 79 | pPackage->qwSize = qwSize; |
79 | pPackage->fVital = fVital; | 80 | 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( | |||
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_z LPCWSTR wzFilePath, | 17 | __in_z LPCWSTR wzFilePath, |
17 | __in_z LPCWSTR wzLocalSource, | 18 | __in_z LPCWSTR wzLocalSource, |
18 | __in_z_opt LPCWSTR wzDownloadSource, | 19 | __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 | |||
62 | 62 | ||
63 | VERUTIL_VERSION* pVersion; | 63 | VERUTIL_VERSION* pVersion; |
64 | LPWSTR sczTag; | 64 | LPWSTR sczTag; |
65 | BOOL fPlannable; | ||
65 | 66 | ||
66 | BURN_PACKAGE package; | 67 | BURN_PACKAGE package; |
67 | } BURN_RELATED_BUNDLE; | 68 | } 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( | |||
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 | DWORD64 qwFileSize = 0; | 402 | DWORD64 qwFileSize = 0; |
402 | BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; | 403 | BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; |
403 | 404 | ||
@@ -423,7 +424,18 @@ static HRESULT LoadRelatedBundleFromKey( | |||
423 | 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); |
424 | 425 | ||
425 | hr = FileSize(sczCachePath, reinterpret_cast<LONGLONG *>(&qwFileSize)); | 426 | hr = FileSize(sczCachePath, reinterpret_cast<LONGLONG *>(&qwFileSize)); |
426 | ExitOnFailure(hr, "Failed to get size of pseudo bundle: %ls", sczCachePath); | 427 | if (SUCCEEDED(hr)) |
428 | { | ||
429 | cacheState = BURN_CACHE_STATE_COMPLETE; | ||
430 | } | ||
431 | else if (E_FILENOTFOUND != hr) | ||
432 | { | ||
433 | cacheState = BURN_CACHE_STATE_PARTIAL; | ||
434 | LogId(REPORT_STANDARD, MSG_DETECT_RELATED_BUNDLE_NOT_FULLY_CACHED, wzRelatedBundleId, sczCachePath, hr); | ||
435 | } | ||
436 | hr = S_OK; | ||
437 | |||
438 | pRelatedBundle->fPlannable = BURN_CACHE_STATE_COMPLETE == cacheState; | ||
427 | 439 | ||
428 | hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY, &dependencyProvider.sczKey); | 440 | hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY, &dependencyProvider.sczKey); |
429 | if (E_FILENOTFOUND != hr) | 441 | if (E_FILENOTFOUND != hr) |
@@ -452,7 +464,7 @@ static HRESULT LoadRelatedBundleFromKey( | |||
452 | pRelatedBundle->relationType = relationType; | 464 | pRelatedBundle->relationType = relationType; |
453 | 465 | ||
454 | hr = PseudoBundleInitialize(qwEngineVersion, &pRelatedBundle->package, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, | 466 | hr = PseudoBundleInitialize(qwEngineVersion, &pRelatedBundle->package, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, |
455 | BOOTSTRAPPER_PACKAGE_STATE_PRESENT, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, | 467 | BOOTSTRAPPER_PACKAGE_STATE_PRESENT, cacheState, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, |
456 | L"-quiet", L"-repair -quiet", L"-uninstall -quiet", | 468 | L"-quiet", L"-repair -quiet", L"-uninstall -quiet", |
457 | (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, | 469 | (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, |
458 | NULL, 0); | 470 | 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( | |||
763 | __in BOOTSTRAPPER_RELATION_TYPE relationType, | 763 | __in BOOTSTRAPPER_RELATION_TYPE relationType, |
764 | __in_z LPCWSTR wzBundleTag, | 764 | __in_z LPCWSTR wzBundleTag, |
765 | __in BOOL fPerMachine, | 765 | __in BOOL fPerMachine, |
766 | __in VERUTIL_VERSION* pVersion | 766 | __in VERUTIL_VERSION* pVersion, |
767 | __in BOOL fMissingFromCache | ||
767 | ) | 768 | ) |
768 | { | 769 | { |
769 | HRESULT hr = S_OK; | 770 | HRESULT hr = S_OK; |
@@ -776,6 +777,7 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle( | |||
776 | args.wzBundleTag = wzBundleTag; | 777 | args.wzBundleTag = wzBundleTag; |
777 | args.fPerMachine = fPerMachine; | 778 | args.fPerMachine = fPerMachine; |
778 | args.wzVersion = pVersion->sczVersion; | 779 | args.wzVersion = pVersion->sczVersion; |
780 | args.fMissingFromCache = fMissingFromCache; | ||
779 | 781 | ||
780 | results.cbSize = sizeof(results); | 782 | results.cbSize = sizeof(results); |
781 | 783 | ||
@@ -879,7 +881,8 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( | |||
879 | __in_z LPCWSTR wzBundleTag, | 881 | __in_z LPCWSTR wzBundleTag, |
880 | __in BOOL fPerMachine, | 882 | __in BOOL fPerMachine, |
881 | __in VERUTIL_VERSION* pVersion, | 883 | __in VERUTIL_VERSION* pVersion, |
882 | __in BOOTSTRAPPER_RELATED_OPERATION operation | 884 | __in BOOTSTRAPPER_RELATED_OPERATION operation, |
885 | __in BOOL fMissingFromCache | ||
883 | ) | 886 | ) |
884 | { | 887 | { |
885 | HRESULT hr = S_OK; | 888 | HRESULT hr = S_OK; |
@@ -893,6 +896,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( | |||
893 | args.fPerMachine = fPerMachine; | 896 | args.fPerMachine = fPerMachine; |
894 | args.wzVersion = pVersion->sczVersion; | 897 | args.wzVersion = pVersion->sczVersion; |
895 | args.operation = operation; | 898 | args.operation = operation; |
899 | args.fMissingFromCache = fMissingFromCache; | ||
896 | 900 | ||
897 | results.cbSize = sizeof(results); | 901 | results.cbSize = sizeof(results); |
898 | 902 | ||
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( | |||
200 | __in BOOTSTRAPPER_RELATION_TYPE relationType, | 200 | __in BOOTSTRAPPER_RELATION_TYPE relationType, |
201 | __in_z LPCWSTR wzBundleTag, | 201 | __in_z LPCWSTR wzBundleTag, |
202 | __in BOOL fPerMachine, | 202 | __in BOOL fPerMachine, |
203 | __in VERUTIL_VERSION* pVersion | 203 | __in VERUTIL_VERSION* pVersion, |
204 | __in BOOL fMissingFromCache | ||
204 | ); | 205 | ); |
205 | BAAPI UserExperienceOnDetectMsiFeature( | 206 | BAAPI UserExperienceOnDetectMsiFeature( |
206 | __in BURN_USER_EXPERIENCE* pUserExperience, | 207 | __in BURN_USER_EXPERIENCE* pUserExperience, |
@@ -225,7 +226,8 @@ BAAPI UserExperienceOnDetectRelatedBundle( | |||
225 | __in_z LPCWSTR wzBundleTag, | 226 | __in_z LPCWSTR wzBundleTag, |
226 | __in BOOL fPerMachine, | 227 | __in BOOL fPerMachine, |
227 | __in VERUTIL_VERSION* pVersion, | 228 | __in VERUTIL_VERSION* pVersion, |
228 | __in BOOTSTRAPPER_RELATED_OPERATION operation | 229 | __in BOOTSTRAPPER_RELATED_OPERATION operation, |
230 | __in BOOL fMissingFromCache | ||
229 | ); | 231 | ); |
230 | BAAPI UserExperienceOnDetectRelatedMsiPackage( | 232 | BAAPI UserExperienceOnDetectRelatedMsiPackage( |
231 | __in BURN_USER_EXPERIENCE* pUserExperience, | 233 | __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 | |||
@@ -293,6 +293,94 @@ namespace Bootstrapper | |||
293 | } | 293 | } |
294 | 294 | ||
295 | [Fact] | 295 | [Fact] |
296 | void RelatedBundleMissingFromCacheTest() | ||
297 | { | ||
298 | HRESULT hr = S_OK; | ||
299 | BURN_ENGINE_STATE engineState = { }; | ||
300 | BURN_ENGINE_STATE* pEngineState = &engineState; | ||
301 | BURN_PLAN* pPlan = &engineState.plan; | ||
302 | |||
303 | InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); | ||
304 | DetectAttachedContainerAsAttached(pEngineState); | ||
305 | DetectPackagesAsAbsent(pEngineState); | ||
306 | BURN_RELATED_BUNDLE* pRelatedBundle = DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); | ||
307 | pRelatedBundle->fPlannable = FALSE; | ||
308 | |||
309 | hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL); | ||
310 | NativeAssert::Succeeded(hr, "CorePlan failed"); | ||
311 | |||
312 | Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action); | ||
313 | Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine); | ||
314 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | ||
315 | |||
316 | BOOL fRollback = FALSE; | ||
317 | DWORD dwIndex = 0; | ||
318 | DWORD dwPackageStart = 0; | ||
319 | ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); | ||
320 | dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); | ||
321 | ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); | ||
322 | ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart); | ||
323 | ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart); | ||
324 | ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); | ||
325 | ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE); | ||
326 | Assert::Equal(dwIndex, pPlan->cCacheActions); | ||
327 | |||
328 | fRollback = TRUE; | ||
329 | dwIndex = 0; | ||
330 | ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); | ||
331 | ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); | ||
332 | Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); | ||
333 | |||
334 | Assert::Equal(35694ull, pPlan->qwEstimatedSize); | ||
335 | Assert::Equal(33743ull, pPlan->qwCacheSizeTotal); | ||
336 | |||
337 | fRollback = FALSE; | ||
338 | dwIndex = 0; | ||
339 | DWORD dwExecuteCheckpointId = 2; | ||
340 | ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); | ||
341 | ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent); | ||
342 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
343 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
344 | ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); | ||
345 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
346 | ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); | ||
347 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
348 | ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER); | ||
349 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
350 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
351 | Assert::Equal(dwIndex, pPlan->cExecuteActions); | ||
352 | |||
353 | fRollback = TRUE; | ||
354 | dwIndex = 0; | ||
355 | dwExecuteCheckpointId = 2; | ||
356 | ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); | ||
357 | ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); | ||
358 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
359 | ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); | ||
360 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
361 | ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); | ||
362 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
363 | ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER); | ||
364 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
365 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
366 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
367 | Assert::Equal(dwIndex, pPlan->cRollbackActions); | ||
368 | |||
369 | Assert::Equal(1ul, pPlan->cExecutePackagesTotal); | ||
370 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); | ||
371 | |||
372 | dwIndex = 0; | ||
373 | Assert::Equal(dwIndex, pPlan->cCleanActions); | ||
374 | |||
375 | UINT uIndex = 0; | ||
376 | ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL); | ||
377 | Assert::Equal(uIndex, pPlan->cPlannedProviders); | ||
378 | |||
379 | Assert::Equal(1ul, pEngineState->packages.cPackages); | ||
380 | ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT); | ||
381 | } | ||
382 | |||
383 | [Fact] | ||
296 | void SingleMsiCacheTest() | 384 | void SingleMsiCacheTest() |
297 | { | 385 | { |
298 | HRESULT hr = S_OK; | 386 | HRESULT hr = S_OK; |
@@ -1041,7 +1129,7 @@ namespace Bootstrapper | |||
1041 | } | 1129 | } |
1042 | } | 1130 | } |
1043 | 1131 | ||
1044 | void DetectUpgradeBundle( | 1132 | BURN_RELATED_BUNDLE* DetectUpgradeBundle( |
1045 | __in BURN_ENGINE_STATE* pEngineState, | 1133 | __in BURN_ENGINE_STATE* pEngineState, |
1046 | __in LPCWSTR wzId, | 1134 | __in LPCWSTR wzId, |
1047 | __in LPCWSTR wzVersion | 1135 | __in LPCWSTR wzVersion |
@@ -1067,12 +1155,15 @@ namespace Bootstrapper | |||
1067 | hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion); | 1155 | hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion); |
1068 | NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion); | 1156 | NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion); |
1069 | 1157 | ||
1158 | pRelatedBundle->fPlannable = TRUE; | ||
1070 | pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; | 1159 | pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; |
1071 | 1160 | ||
1072 | 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); | 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); |
1073 | NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); | 1162 | NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); |
1074 | 1163 | ||
1075 | ++pRelatedBundles->cRelatedBundles; | 1164 | ++pRelatedBundles->cRelatedBundles; |
1165 | |||
1166 | return pRelatedBundle; | ||
1076 | } | 1167 | } |
1077 | 1168 | ||
1078 | void DetectAsRelatedUpgradeBundle( | 1169 | void DetectAsRelatedUpgradeBundle( |