Handle when related bundles have an uninstall key but aren't cached.
#4991
Sean Hall committed
Mar 10, 2021 at 18:18 UTC
af68033509730ffe01602f839861a47287bb709f
14 files changed
+188
-34
src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+2
@@ -491,6 +491,7 @@ struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_ARGS
491
LPCWSTR wzBundleTag;
492
BOOL fPerMachine;
493
LPCWSTR wzVersion;
494
+ BOOL fMissingFromCache;
495
};
496
497
struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS
@@ -547,6 +548,7 @@ struct BA_ONDETECTRELATEDBUNDLE_ARGS
548
BOOL fPerMachine;
549
LPCWSTR wzVersion;
550
BOOTSTRAPPER_RELATED_OPERATION operation;
551
+ BOOL fMissingFromCache;
552
};
553
554
struct BA_ONDETECTRELATEDBUNDLE_RESULTS
src/engine/core.cpp
+26
-13
@@ -59,6 +59,10 @@ static void LogPackages(
59
__in const BURN_RELATED_BUNDLES* pRelatedBundles,
60
__in const BOOTSTRAPPER_ACTION action
61
);
62
+static void LogRelatedBundles(
63
+ __in const BURN_RELATED_BUNDLES* pRelatedBundles,
64
+ __in BOOL fReverse
65
+ );
66
67
68
// function definitions
@@ -1793,15 +1797,9 @@ static void LogPackages(
1797
else
1798
{
1799
// Display related bundles first if uninstalling.
1796
- if (BOOTSTRAPPER_ACTION_UNINSTALL == action && 0 < pRelatedBundles->cRelatedBundles)
1800
+ if (BOOTSTRAPPER_ACTION_UNINSTALL == action)
1801
{
1798
- for (int i = pRelatedBundles->cRelatedBundles - 1; 0 <= i; --i)
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
- }
1802
+ LogRelatedBundles(pRelatedBundles, TRUE);
1803
}
1804
1805
// Display all the packages in the log.
@@ -1852,13 +1850,28 @@ static void LogPackages(
1850
}
1851
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)
1854
{
1857
- for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i)
1858
- {
1859
- const BURN_RELATED_BUNDLE* pRelatedBundle = &pRelatedBundles->rgRelatedBundles[i];
1860
- const BURN_PACKAGE* pPackage = &pRelatedBundle->package;
1855
+ LogRelatedBundles(pRelatedBundles, FALSE);
1856
+ }
1857
+ }
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;
1872
1873
+ if (pRelatedBundle->fPlannable)
1874
+ {
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));
1876
}
1877
}
src/engine/dependency.cpp
+7
-1
@@ -260,7 +260,13 @@ extern "C" HRESULT DependencyDetect(
260
261
for (DWORD iRelatedBundle = 0; iRelatedBundle < pEngineState->registration.relatedBundles.cRelatedBundles; ++iRelatedBundle)
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;
270
hr = DetectPackageDependents(pPackage, sdIgnoredDependents, pRegistration);
271
ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId);
272
}
src/engine/detect.cpp
+10
-7
@@ -143,13 +143,16 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
143
144
if (nCompareResult <= 0)
145
{
146
- pRelatedBundle->fForwardCompatible = TRUE;
147
- pRegistration->fForwardCompatibleBundleExists = TRUE;
146
+ if (pRelatedBundle->fPlannable)
147
+ {
148
+ pRelatedBundle->fForwardCompatible = TRUE;
149
+ pRegistration->fForwardCompatibleBundleExists = TRUE;
150
+ }
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);
153
ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle.");
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));
156
}
157
}
158
}
@@ -222,13 +225,13 @@ extern "C" HRESULT DetectReportRelatedBundles(
225
break;
226
}
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));
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);
231
ExitOnRootFailure(hr, "BA aborted detect related bundle.");
232
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)
235
{
236
uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
237
hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, BOOTSTRAPPER_ACTION_UNINSTALL, pRegistration->pVersion, pRelatedBundle->pVersion, &uninstallRequestState);
src/engine/engine.mc
+9
-2
@@ -202,7 +202,7 @@ MessageId=102
202
Severity=Success
203
SymbolicName=MSG_DETECTED_RELATED_BUNDLE
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
.
207
208
MessageId=103
@@ -237,7 +237,14 @@ MessageId=107
237
Severity=Success
238
SymbolicName=MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE
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!
248
.
249
250
MessageId=120
src/engine/externalengine.cpp
+1
-1
@@ -327,7 +327,7 @@ HRESULT ExternalEngineSetUpdate(
327
sczId = pEngineState->registration.sczId;
328
}
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.");
332
333
pEngineState->update.fUpdateAvailable = TRUE;
src/engine/plan.cpp
+11
@@ -1292,6 +1292,12 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1292
for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
1293
{
1294
BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
1295
+
1296
+ if (!pRelatedBundle->fPlannable)
1297
+ {
1298
+ continue;
1299
+ }
1300
+
1301
pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1302
pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1303
@@ -1417,6 +1423,11 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1423
DWORD *pdwInsertIndex = NULL;
1424
BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
1425
1426
+ if (!pRelatedBundle->fPlannable)
1427
+ {
1428
+ continue;
1429
+ }
1430
+
1431
// Do not execute if a major upgrade to the related bundle is an embedded bundle (Provider keys are the same)
1432
if (0 < pRelatedBundle->package.cDependencyProviders)
1433
{
src/engine/pseudobundle.cpp
+3
-2
@@ -10,6 +10,7 @@ extern "C" HRESULT PseudoBundleInitialize(
10
__in_z LPCWSTR wzId,
11
__in BOOTSTRAPPER_RELATION_TYPE relationType,
12
__in BOOTSTRAPPER_PACKAGE_STATE state,
13
+ __in BURN_CACHE_STATE cacheState,
14
__in_z LPCWSTR wzFilePath,
15
__in_z LPCWSTR wzLocalSource,
16
__in_z_opt LPCWSTR wzDownloadSource,
@@ -66,14 +67,14 @@ extern "C" HRESULT PseudoBundleInitialize(
67
memcpy_s(pPackage->rgPayloads->pPayload->pbHash, pPackage->rgPayloads->pPayload->cbHash, pbHash, cbHash);
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;
71
72
pPackage->Exe.fPseudoBundle = TRUE;
73
74
pPackage->type = BURN_PACKAGE_TYPE_EXE;
75
pPackage->fPerMachine = fPerMachine;
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;
78
pPackage->qwInstallSize = qwSize;
79
pPackage->qwSize = qwSize;
80
pPackage->fVital = fVital;
src/engine/pseudobundle.h
+1
@@ -13,6 +13,7 @@ HRESULT PseudoBundleInitialize(
13
__in_z LPCWSTR wzId,
14
__in BOOTSTRAPPER_RELATION_TYPE relationType,
15
__in BOOTSTRAPPER_PACKAGE_STATE state,
16
+ __in BURN_CACHE_STATE cacheState,
17
__in_z LPCWSTR wzFilePath,
18
__in_z LPCWSTR wzLocalSource,
19
__in_z_opt LPCWSTR wzDownloadSource,
src/engine/registration.h
+1
@@ -62,6 +62,7 @@ typedef struct _BURN_RELATED_BUNDLE
62
63
VERUTIL_VERSION* pVersion;
64
LPWSTR sczTag;
65
+ BOOL fPlannable;
66
67
BURN_PACKAGE package;
68
} BURN_RELATED_BUNDLE;
src/engine/relatedbundle.cpp
+14
-2
@@ -398,6 +398,7 @@ static HRESULT LoadRelatedBundleFromKey(
398
DWORD64 qwEngineVersion = 0;
399
LPWSTR sczBundleVersion = NULL;
400
LPWSTR sczCachePath = NULL;
401
+ BURN_CACHE_STATE cacheState = BURN_CACHE_STATE_NONE;
402
DWORD64 qwFileSize = 0;
403
BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
404
@@ -423,7 +424,18 @@ static HRESULT LoadRelatedBundleFromKey(
424
ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId);
425
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;
439
440
hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY, &dependencyProvider.sczKey);
441
if (E_FILENOTFOUND != hr)
@@ -452,7 +464,7 @@ static HRESULT LoadRelatedBundleFromKey(
464
pRelatedBundle->relationType = relationType;
465
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,
468
L"-quiet", L"-repair -quiet", L"-uninstall -quiet",
469
(dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL,
470
NULL, 0);
src/engine/userexperience.cpp
+6
-2
@@ -763,7 +763,8 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle(
763
__in BOOTSTRAPPER_RELATION_TYPE relationType,
764
__in_z LPCWSTR wzBundleTag,
765
__in BOOL fPerMachine,
766
- __in VERUTIL_VERSION* pVersion
766
+ __in VERUTIL_VERSION* pVersion,
767
+ __in BOOL fMissingFromCache
768
)
769
{
770
HRESULT hr = S_OK;
@@ -776,6 +777,7 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle(
777
args.wzBundleTag = wzBundleTag;
778
args.fPerMachine = fPerMachine;
779
args.wzVersion = pVersion->sczVersion;
780
+ args.fMissingFromCache = fMissingFromCache;
781
782
results.cbSize = sizeof(results);
783
@@ -879,7 +881,8 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle(
881
__in_z LPCWSTR wzBundleTag,
882
__in BOOL fPerMachine,
883
__in VERUTIL_VERSION* pVersion,
882
- __in BOOTSTRAPPER_RELATED_OPERATION operation
884
+ __in BOOTSTRAPPER_RELATED_OPERATION operation,
885
+ __in BOOL fMissingFromCache
886
)
887
{
888
HRESULT hr = S_OK;
@@ -893,6 +896,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle(
896
args.fPerMachine = fPerMachine;
897
args.wzVersion = pVersion->sczVersion;
898
args.operation = operation;
899
+ args.fMissingFromCache = fMissingFromCache;
900
901
results.cbSize = sizeof(results);
902
src/engine/userexperience.h
+4
-2
@@ -200,7 +200,8 @@ BAAPI UserExperienceOnDetectForwardCompatibleBundle(
200
__in BOOTSTRAPPER_RELATION_TYPE relationType,
201
__in_z LPCWSTR wzBundleTag,
202
__in BOOL fPerMachine,
203
- __in VERUTIL_VERSION* pVersion
203
+ __in VERUTIL_VERSION* pVersion,
204
+ __in BOOL fMissingFromCache
205
);
206
BAAPI UserExperienceOnDetectMsiFeature(
207
__in BURN_USER_EXPERIENCE* pUserExperience,
@@ -225,7 +226,8 @@ BAAPI UserExperienceOnDetectRelatedBundle(
226
__in_z LPCWSTR wzBundleTag,
227
__in BOOL fPerMachine,
228
__in VERUTIL_VERSION* pVersion,
228
- __in BOOTSTRAPPER_RELATED_OPERATION operation
229
+ __in BOOTSTRAPPER_RELATED_OPERATION operation,
230
+ __in BOOL fMissingFromCache
231
);
232
BAAPI UserExperienceOnDetectRelatedMsiPackage(
233
__in BURN_USER_EXPERIENCE* pUserExperience,
src/test/BurnUnitTest/PlanTest.cpp
+93
-2
@@ -292,6 +292,94 @@ namespace Bootstrapper
292
ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[2], L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
293
}
294
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]
384
void SingleMsiCacheTest()
385
{
@@ -1041,7 +1129,7 @@ namespace Bootstrapper
1129
}
1130
}
1131
1044
- void DetectUpgradeBundle(
1132
+ BURN_RELATED_BUNDLE* DetectUpgradeBundle(
1133
__in BURN_ENGINE_STATE* pEngineState,
1134
__in LPCWSTR wzId,
1135
__in LPCWSTR wzVersion
@@ -1067,12 +1155,15 @@ namespace Bootstrapper
1155
hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion);
1156
NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion);
1157
1158
+ pRelatedBundle->fPlannable = TRUE;
1159
pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
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);
1162
NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
1163
1164
++pRelatedBundles->cRelatedBundles;
1165
+
1166
+ return pRelatedBundle;
1167
}
1168
1169
void DetectAsRelatedUpgradeBundle(