Add patch target for slipstream MSI package even if not installed.
Fixes #3897
Sean Hall committed
Feb 22, 2021 at 16:16 UTC
4f4c85ed66f1b2dfb1bec76d54d7b50c637d5bfa
12 files changed
+546
-91
src/engine/core.cpp
+3
@@ -351,6 +351,9 @@ extern "C" HRESULT CoreDetect(
351
{
352
hr = MspEngineDetectInitialize(&pEngineState->packages);
353
ExitOnFailure(hr, "Failed to initialize MSP engine detection.");
354
+
355
+ hr = MsiEngineDetectInitialize(&pEngineState->packages);
356
+ ExitOnFailure(hr, "Failed to initialize MSI engine detection.");
357
}
358
359
for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
src/engine/detect.cpp
+10
@@ -82,6 +82,16 @@ extern "C" void DetectReset(
82
83
pFeature->currentState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN;
84
}
85
+
86
+ for (DWORD iSlipstreamMsp = 0; iSlipstreamMsp < pPackage->Msi.cSlipstreamMspPackages; ++iSlipstreamMsp)
87
+ {
88
+ BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + iSlipstreamMsp;
89
+
90
+ pSlipstreamMsp->dwMsiChainedPatchIndex = BURN_PACKAGE_INVALID_PATCH_INDEX;
91
+ }
92
+
93
+ ReleaseNullMem(pPackage->Msi.rgChainedPatches);
94
+ pPackage->Msi.cChainedPatches = 0;
95
}
96
else if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
97
{
src/engine/msiengine.cpp
+42
-14
@@ -213,8 +213,8 @@ extern "C" HRESULT MsiEngineParsePackageFromXml(
213
214
if (cNodes)
215
{
216
- pPackage->Msi.rgpSlipstreamMspPackages = reinterpret_cast<BURN_PACKAGE**>(MemAlloc(sizeof(BURN_PACKAGE*) * cNodes, TRUE));
217
- ExitOnNull(pPackage->Msi.rgpSlipstreamMspPackages, hr, E_OUTOFMEMORY, "Failed to allocate memory for slipstream MSP packages.");
216
+ pPackage->Msi.rgSlipstreamMsps = reinterpret_cast<BURN_SLIPSTREAM_MSP*>(MemAlloc(sizeof(BURN_SLIPSTREAM_MSP) * cNodes, TRUE));
217
+ ExitOnNull(pPackage->Msi.rgSlipstreamMsps, hr, E_OUTOFMEMORY, "Failed to allocate memory for slipstream MSP packages.");
218
219
pPackage->Msi.rgsczSlipstreamMspPackageIds = reinterpret_cast<LPWSTR*>(MemAlloc(sizeof(LPWSTR*) * cNodes, TRUE));
220
ExitOnNull(pPackage->Msi.rgsczSlipstreamMspPackageIds, hr, E_OUTOFMEMORY, "Failed to allocate memory for slipstream MSP ids.");
@@ -383,15 +383,52 @@ extern "C" void MsiEnginePackageUninitialize(
383
MemFree(pPackage->Msi.rgsczSlipstreamMspPackageIds);
384
}
385
386
- if (pPackage->Msi.rgpSlipstreamMspPackages)
386
+ if (pPackage->Msi.rgSlipstreamMsps)
387
{
388
- MemFree(pPackage->Msi.rgpSlipstreamMspPackages);
388
+ MemFree(pPackage->Msi.rgSlipstreamMsps);
389
+ }
390
+
391
+ if (pPackage->Msi.rgChainedPatches)
392
+ {
393
+ MemFree(pPackage->Msi.rgChainedPatches);
394
}
395
396
// clear struct
397
memset(&pPackage->Msi, 0, sizeof(pPackage->Msi));
398
}
399
400
+extern "C" HRESULT MsiEngineDetectInitialize(
401
+ __in BURN_PACKAGES* pPackages
402
+ )
403
+{
404
+ AssertSz(pPackages->cPatchInfo, "MsiEngineDetectInitialize() should only be called if there are MSP packages.");
405
+
406
+ HRESULT hr = S_OK;
407
+
408
+ // Add target products for slipstream MSIs that weren't detected.
409
+ for (DWORD iPackage = 0; iPackage < pPackages->cPackages; ++iPackage)
410
+ {
411
+ BURN_PACKAGE* pMsiPackage = pPackages->rgPackages + iPackage;
412
+ if (BURN_PACKAGE_TYPE_MSI == pMsiPackage->type)
413
+ {
414
+ for (DWORD j = 0; j < pMsiPackage->Msi.cSlipstreamMspPackages; ++j)
415
+ {
416
+ BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pMsiPackage->Msi.rgSlipstreamMsps + j;
417
+ Assert(pSlipstreamMsp->pMspPackage && BURN_PACKAGE_TYPE_MSP == pSlipstreamMsp->pMspPackage->type);
418
+
419
+ if (pSlipstreamMsp->pMspPackage && BURN_PACKAGE_INVALID_PATCH_INDEX == pSlipstreamMsp->dwMsiChainedPatchIndex)
420
+ {
421
+ hr = MspEngineAddMissingSlipstreamTarget(pMsiPackage, pSlipstreamMsp);
422
+ ExitOnFailure(hr, "Failed to add slipstreamed target product code to package: %ls", pSlipstreamMsp->pMspPackage->sczId);
423
+ }
424
+ }
425
+ }
426
+ }
427
+
428
+LExit:
429
+ return hr;
430
+}
431
+
432
extern "C" HRESULT MsiEngineDetectPackage(
433
__in BURN_PACKAGE* pPackage,
434
__in BURN_USER_EXPERIENCE* pUserExperience
@@ -971,15 +1008,6 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
1008
pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes;
1009
}
1010
974
- // Update any slipstream patches' state.
975
- for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i)
976
- {
977
- BURN_PACKAGE* pMspPackage = pPackage->Msi.rgpSlipstreamMspPackages[i];
978
- AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
979
-
980
- MspEngineSlipstreamUpdateState(pMspPackage, pPackage->execute, pPackage->rollback);
981
- }
982
-
1011
LExit:
1012
ReleaseMem(rgFeatureActions);
1013
ReleaseMem(rgRollbackFeatureActions);
@@ -1897,7 +1925,7 @@ static HRESULT ConcatPatchProperty(
1925
{
1926
for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i)
1927
{
1900
- BURN_PACKAGE* pMspPackage = pPackage->Msi.rgpSlipstreamMspPackages[i];
1928
+ BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage;
1929
AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
1930
1931
BOOTSTRAPPER_ACTION_STATE patchExecuteAction = rgSlipstreamPatchActions[i];
src/engine/msiengine.h
+3
@@ -27,6 +27,9 @@ HRESULT MsiEngineParsePropertiesFromXml(
27
void MsiEnginePackageUninitialize(
28
__in BURN_PACKAGE* pPackage
29
);
30
+HRESULT MsiEngineDetectInitialize(
31
+ __in BURN_PACKAGES* pPackages
32
+ );
33
HRESULT MsiEngineDetectPackage(
34
__in BURN_PACKAGE* pPackage,
35
__in BURN_USER_EXPERIENCE* pUserExperience
src/engine/mspengine.cpp
+130
-66
@@ -30,18 +30,23 @@ static HRESULT AddPossibleTargetProduct(
30
__inout DWORD* pcPossibleTargetProducts
31
);
32
static HRESULT AddDetectedTargetProduct(
33
- __in BURN_PACKAGES* pPackages,
33
__in BURN_PACKAGE* pPackage,
34
__in DWORD dwOrder,
35
__in_z LPCWSTR wzProductCode,
37
- __in MSIINSTALLCONTEXT context
36
+ __in MSIINSTALLCONTEXT context,
37
+ __out DWORD* pdwTargetProductIndex
38
+ );
39
+static HRESULT AddMsiChainedPatch(
40
+ __in BURN_PACKAGE* pPackage,
41
+ __in BURN_PACKAGE* pMspPackage,
42
+ __in DWORD dwMspTargetProductIndex,
43
+ __out DWORD* pdwChainedPatchIndex
44
);
39
-static void DeterminePatchChainedTarget(
45
+static HRESULT DeterminePatchChainedTarget(
46
__in BURN_PACKAGES* pPackages,
47
__in BURN_PACKAGE* pMspPackage,
48
__in LPCWSTR wzTargetProductCode,
43
- __out BURN_PACKAGE** ppChainedTargetPackage,
44
- __out BOOL* pfSlipstreamed
49
+ __in DWORD dwMspTargetProductIndex
50
);
51
static HRESULT PlanTargetProduct(
52
__in BOOTSTRAPPER_DISPLAY display,
@@ -159,16 +164,20 @@ extern "C" HRESULT MspEngineDetectInitialize(
164
{
165
for (DWORD iPatchInfo = 0; iPatchInfo < pPackages->cPatchInfo; ++iPatchInfo)
166
{
162
- if (ERROR_SUCCESS == pPackages->rgPatchInfo[iPatchInfo].uStatus)
163
- {
164
- BURN_PACKAGE* pMspPackage = pPackages->rgPatchInfoToPackage[iPatchInfo];
165
- Assert(BURN_PACKAGE_TYPE_MSP == pMspPackage->type);
167
+ hr = HRESULT_FROM_WIN32(pPackages->rgPatchInfo[iPatchInfo].uStatus);
168
+ BURN_PACKAGE* pMspPackage = pPackages->rgPatchInfoToPackage[iPatchInfo];
169
+ Assert(BURN_PACKAGE_TYPE_MSP == pMspPackage->type);
170
171
+ if (S_OK == hr)
172
+ {
173
// Note that we do add superseded and obsolete MSP packages. Package Detect and Plan will sort them out later.
168
- hr = AddDetectedTargetProduct(pPackages, pMspPackage, pPackages->rgPatchInfo[iPatchInfo].dwOrder, pPossibleTargetProduct->wzProductCode, pPossibleTargetProduct->context);
174
+ hr = MspEngineAddDetectedTargetProduct(pPackages, pMspPackage, pPackages->rgPatchInfo[iPatchInfo].dwOrder, pPossibleTargetProduct->wzProductCode, pPossibleTargetProduct->context);
175
ExitOnFailure(hr, "Failed to add target product code to package: %ls", pMspPackage->sczId);
176
}
171
- // TODO: should we log something for this error case?
177
+ else
178
+ {
179
+ LogStringLine(REPORT_DEBUG, " 0x%x: Patch applicability failed for package: %ls", hr, pMspPackage->sczId);
180
+ }
181
}
182
}
183
else
@@ -192,6 +201,54 @@ LExit:
201
return hr;
202
}
203
204
+extern "C" HRESULT MspEngineAddDetectedTargetProduct(
205
+ __in BURN_PACKAGES* pPackages,
206
+ __in BURN_PACKAGE* pPackage,
207
+ __in DWORD dwOrder,
208
+ __in_z LPCWSTR wzProductCode,
209
+ __in MSIINSTALLCONTEXT context
210
+ )
211
+{
212
+ HRESULT hr = S_OK;
213
+ DWORD dwTargetProductIndex = 0;
214
+
215
+ hr = AddDetectedTargetProduct(pPackage, dwOrder, wzProductCode, context, &dwTargetProductIndex);
216
+ ExitOnFailure(hr, "Failed to add detected target product.");
217
+
218
+ hr = DeterminePatchChainedTarget(pPackages, pPackage, wzProductCode, dwTargetProductIndex);
219
+ ExitOnFailure(hr, "Failed to determine patch chained target.");
220
+
221
+LExit:
222
+ return hr;
223
+}
224
+
225
+extern "C" HRESULT MspEngineAddMissingSlipstreamTarget(
226
+ __in BURN_PACKAGE* pMsiPackage,
227
+ __in BURN_SLIPSTREAM_MSP* pSlipstreamMsp
228
+ )
229
+{
230
+ HRESULT hr = S_OK;
231
+ DWORD dwTargetProductIndex = 0;
232
+ BURN_MSPTARGETPRODUCT* pTargetProduct = NULL;
233
+ DWORD dwChainedPatchIndex = 0;
234
+
235
+ hr = AddDetectedTargetProduct(pSlipstreamMsp->pMspPackage, 0, pMsiPackage->Msi.sczProductCode, pMsiPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, &dwTargetProductIndex);
236
+ ExitOnFailure(hr, "Failed to add missing slipstream target.");
237
+
238
+ pTargetProduct = pSlipstreamMsp->pMspPackage->Msp.rgTargetProducts + dwTargetProductIndex;
239
+ pTargetProduct->fSlipstream = TRUE;
240
+ pTargetProduct->fSlipstreamRequired = TRUE;
241
+ pTargetProduct->pChainedTargetPackage = pMsiPackage;
242
+
243
+ hr = AddMsiChainedPatch(pMsiPackage, pSlipstreamMsp->pMspPackage, dwTargetProductIndex, &dwChainedPatchIndex);
244
+ ExitOnFailure(hr, "Failed to add chained patch.");
245
+
246
+ pSlipstreamMsp->dwMsiChainedPatchIndex = dwChainedPatchIndex;
247
+
248
+LExit:
249
+ return hr;
250
+}
251
+
252
extern "C" HRESULT MspEngineDetectPackage(
253
__in BURN_PACKAGE* pPackage,
254
__in BURN_USER_EXPERIENCE* pUserExperience
@@ -219,7 +276,6 @@ extern "C" HRESULT MspEngineDetectPackage(
276
for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
277
{
278
BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
222
- BOOL fInstalled = FALSE;
279
280
hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState);
281
if (SUCCEEDED(hr))
@@ -227,17 +283,17 @@ extern "C" HRESULT MspEngineDetectPackage(
283
switch (*sczState)
284
{
285
case '1':
230
- fInstalled = TRUE;
286
+ pTargetProduct->fInstalled = TRUE;
287
pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
288
break;
289
290
case '2':
235
- fInstalled = TRUE;
291
+ pTargetProduct->fInstalled = TRUE;
292
pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
293
break;
294
295
case '4':
240
- fInstalled = TRUE;
296
+ pTargetProduct->fInstalled = TRUE;
297
pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE;
298
break;
299
@@ -246,7 +302,7 @@ extern "C" HRESULT MspEngineDetectPackage(
302
break;
303
}
304
}
249
- else if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PATCH) == hr)
305
+ else if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PATCH) == hr || HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr)
306
{
307
pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
308
hr = S_OK;
@@ -260,9 +316,9 @@ extern "C" HRESULT MspEngineDetectPackage(
316
317
if (pPackage->fCanAffectRegistration)
318
{
263
- pTargetProduct->registrationState = fInstalled ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
319
+ pTargetProduct->registrationState = pTargetProduct->fInstalled ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
320
265
- if (fInstalled)
321
+ if (pTargetProduct->fInstalled)
322
{
323
pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
324
}
@@ -290,6 +346,13 @@ extern "C" HRESULT MspEnginePlanInitializePackage(
346
{
347
BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
348
349
+ if (!pTargetProduct->fInstalled && pTargetProduct->fSlipstreamRequired && BOOTSTRAPPER_REQUEST_STATE_PRESENT > pTargetProduct->pChainedTargetPackage->requested)
350
+ {
351
+ // There's no way to apply the patch if the target isn't installed.
352
+ pTargetProduct->defaultRequested = pTargetProduct->requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
353
+ continue;
354
+ }
355
+
356
pTargetProduct->defaultRequested = pTargetProduct->requested = pPackage->requested;
357
358
hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &pTargetProduct->requested);
@@ -637,32 +700,6 @@ LExit:
700
return hr;
701
}
702
640
-extern "C" void MspEngineSlipstreamUpdateState(
641
- __in BURN_PACKAGE* pPackage,
642
- __in BOOTSTRAPPER_ACTION_STATE execute,
643
- __in BOOTSTRAPPER_ACTION_STATE rollback
644
- )
645
-{
646
- Assert(BURN_PACKAGE_TYPE_MSP == pPackage->type);
647
-
648
- // If the dependency manager set our state then that means something else
649
- // is dependent on our package. That trumps whatever the slipstream update
650
- // state might set.
651
- if (!pPackage->fDependencyManagerWasHere)
652
- {
653
- // The highest aggregate action state found will be returned.
654
- if (pPackage->execute < execute)
655
- {
656
- pPackage->execute = execute;
657
- }
658
-
659
- if (pPackage->rollback < rollback)
660
- {
661
- pPackage->rollback = rollback;
662
- }
663
- }
664
-}
665
-
703
extern "C" void MspEngineUpdateInstallRegistrationState(
704
__in BURN_EXECUTE_ACTION* pAction,
705
__in HRESULT hrExecute,
@@ -926,43 +963,68 @@ LExit:
963
}
964
965
static HRESULT AddDetectedTargetProduct(
929
- __in BURN_PACKAGES* pPackages,
966
__in BURN_PACKAGE* pPackage,
967
__in DWORD dwOrder,
968
__in_z LPCWSTR wzProductCode,
933
- __in MSIINSTALLCONTEXT context
969
+ __in MSIINSTALLCONTEXT context,
970
+ __out DWORD* pdwTargetProductIndex
971
)
972
{
973
HRESULT hr = S_OK;
974
+ BURN_MSPTARGETPRODUCT* pTargetProduct = NULL;
975
+
976
+ *pdwTargetProductIndex = BURN_PACKAGE_INVALID_PATCH_INDEX;
977
978
hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPackage->Msp.rgTargetProducts), pPackage->Msp.cTargetProductCodes + 1, sizeof(BURN_MSPTARGETPRODUCT), 5);
979
ExitOnFailure(hr, "Failed to ensure enough target product codes were allocated.");
980
941
- hr = ::StringCchCopyW(pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].wzTargetProductCode, countof(pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].wzTargetProductCode), wzProductCode);
981
+ pTargetProduct = pPackage->Msp.rgTargetProducts + pPackage->Msp.cTargetProductCodes;
982
+
983
+ hr = ::StringCchCopyW(pTargetProduct->wzTargetProductCode, countof(pTargetProduct->wzTargetProductCode), wzProductCode);
984
ExitOnFailure(hr, "Failed to copy target product code.");
985
944
- DeterminePatchChainedTarget(pPackages, pPackage, wzProductCode,
945
- &pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].pChainedTargetPackage,
946
- &pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].fSlipstream);
986
+ pTargetProduct->context = context;
987
+ pTargetProduct->dwOrder = dwOrder;
988
948
- pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].context = context;
949
- pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].dwOrder = dwOrder;
989
+ *pdwTargetProductIndex = pPackage->Msp.cTargetProductCodes;
990
++pPackage->Msp.cTargetProductCodes;
991
992
LExit:
993
return hr;
994
}
995
956
-static void DeterminePatchChainedTarget(
996
+static HRESULT AddMsiChainedPatch(
997
+ __in BURN_PACKAGE* pPackage,
998
+ __in BURN_PACKAGE* pMspPackage,
999
+ __in DWORD dwMspTargetProductIndex,
1000
+ __out DWORD* pdwChainedPatchIndex
1001
+ )
1002
+{
1003
+ HRESULT hr = S_OK;
1004
+
1005
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPackage->Msi.rgChainedPatches), pPackage->Msi.cChainedPatches + 1, sizeof(BURN_CHAINED_PATCH), 5);
1006
+ ExitOnFailure(hr, "Failed to ensure enough chained patches were allocated.");
1007
+
1008
+ BURN_CHAINED_PATCH* pChainedPatch = pPackage->Msi.rgChainedPatches + pPackage->Msi.cChainedPatches;
1009
+ pChainedPatch->pMspPackage = pMspPackage;
1010
+ pChainedPatch->dwMspTargetProductIndex = dwMspTargetProductIndex;
1011
+
1012
+ *pdwChainedPatchIndex = pPackage->Msi.cChainedPatches;
1013
+ ++pPackage->Msi.cChainedPatches;
1014
+LExit:
1015
+ return hr;
1016
+}
1017
+
1018
+static HRESULT DeterminePatchChainedTarget(
1019
__in BURN_PACKAGES* pPackages,
1020
__in BURN_PACKAGE* pMspPackage,
1021
__in LPCWSTR wzTargetProductCode,
960
- __out BURN_PACKAGE** ppChainedTargetPackage,
961
- __out BOOL* pfSlipstreamed
1022
+ __in DWORD dwMspTargetProductIndex
1023
)
1024
{
964
- BURN_PACKAGE* pTargetMsiPackage = NULL;
965
- BOOL fSlipstreamed = FALSE;
1025
+ HRESULT hr = S_OK;
1026
+ DWORD dwChainedPatchIndex = 0;
1027
+ BURN_MSPTARGETPRODUCT* pTargetProduct = pMspPackage->Msp.rgTargetProducts + dwMspTargetProductIndex;
1028
1029
for (DWORD iPackage = 0; iPackage < pPackages->cPackages; ++iPackage)
1030
{
@@ -970,15 +1032,19 @@ static void DeterminePatchChainedTarget(
1032
1033
if (BURN_PACKAGE_TYPE_MSI == pPackage->type && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzTargetProductCode, -1, pPackage->Msi.sczProductCode, -1))
1034
{
973
- pTargetMsiPackage = pPackage;
1035
+ pTargetProduct->pChainedTargetPackage = pPackage;
1036
+
1037
+ hr = AddMsiChainedPatch(pPackage, pMspPackage, dwMspTargetProductIndex, &dwChainedPatchIndex);
1038
+ ExitOnFailure(hr, "Failed to add chained patch.");
1039
1040
for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j)
1041
{
977
- BURN_PACKAGE* pSlipstreamMsp = pPackage->Msi.rgpSlipstreamMspPackages[j];
978
- if (pSlipstreamMsp == pMspPackage)
1042
+ BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + j;
1043
+ if (pSlipstreamMsp->pMspPackage == pMspPackage)
1044
{
980
- AssertSz(!fSlipstreamed, "An MSP should only show up as a slipstreamed patch in an MSI once.");
981
- fSlipstreamed = TRUE;
1045
+ AssertSz(BURN_PACKAGE_INVALID_PATCH_INDEX == pSlipstreamMsp->dwMsiChainedPatchIndex, "An MSP should only show up as a slipstreamed patch in an MSI once.");
1046
+ pTargetProduct->fSlipstream = TRUE;
1047
+ pSlipstreamMsp->dwMsiChainedPatchIndex = dwChainedPatchIndex;
1048
break;
1049
}
1050
}
@@ -987,10 +1053,8 @@ static void DeterminePatchChainedTarget(
1053
}
1054
}
1055
990
- *ppChainedTargetPackage = pTargetMsiPackage;
991
- *pfSlipstreamed = fSlipstreamed;
992
-
993
- return;
1056
+LExit:
1057
+ return hr;
1058
}
1059
1060
static HRESULT PlanTargetProduct(
src/engine/mspengine.h
+11
-5
@@ -28,6 +28,17 @@ void MspEnginePackageUninitialize(
28
HRESULT MspEngineDetectInitialize(
29
__in BURN_PACKAGES* pPackages
30
);
31
+HRESULT MspEngineAddDetectedTargetProduct(
32
+ __in BURN_PACKAGES* pPackages,
33
+ __in BURN_PACKAGE* pPackage,
34
+ __in DWORD dwOrder,
35
+ __in_z LPCWSTR wzProductCode,
36
+ __in MSIINSTALLCONTEXT context
37
+ );
38
+HRESULT MspEngineAddMissingSlipstreamTarget(
39
+ __in BURN_PACKAGE* pMsiPackage,
40
+ __in BURN_SLIPSTREAM_MSP* pSlipstreamMsp
41
+ );
42
HRESULT MspEngineDetectPackage(
43
__in BURN_PACKAGE* pPackage,
44
__in BURN_USER_EXPERIENCE* pUserExperience
@@ -59,11 +70,6 @@ HRESULT MspEngineExecutePackage(
70
__in LPVOID pvContext,
71
__out BOOTSTRAPPER_APPLY_RESTART* pRestart
72
);
62
-void MspEngineSlipstreamUpdateState(
63
- __in BURN_PACKAGE* pMspPackage,
64
- __in BOOTSTRAPPER_ACTION_STATE execute,
65
- __in BOOTSTRAPPER_ACTION_STATE rollback
66
- );
73
void MspEngineUpdateInstallRegistrationState(
74
__in BURN_EXECUTE_ACTION* pAction,
75
__in HRESULT hrExecute,
src/engine/package.cpp
+22
-1
@@ -282,7 +282,9 @@ extern "C" HRESULT PackagesParseFromXml(
282
{
283
if (pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k] && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k], -1))
284
{
285
- pMsiPackage->Msi.rgpSlipstreamMspPackages[k] = pPackage;
285
+ BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pMsiPackage->Msi.rgSlipstreamMsps + k;
286
+ pSlipstreamMsp->pMspPackage = pPackage;
287
+ pSlipstreamMsp->dwMsiChainedPatchIndex = BURN_PACKAGE_INVALID_PATCH_INDEX;
288
289
ReleaseNullStr(pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k]); // we don't need the slipstream package id any longer so free it.
290
}
@@ -295,6 +297,25 @@ extern "C" HRESULT PackagesParseFromXml(
297
298
AssertSz(pPackages->cPatchInfo == cMspPackages, "Count of packages patch info should be equal to the number of MSP packages.");
299
300
+#if DEBUG
301
+ // Loop through all MSI packages seeing if any of them are missing their slipstream MSP.
302
+ for (DWORD i = 0; i < pPackages->cPackages; ++i)
303
+ {
304
+ BURN_PACKAGE* pPackage = &pPackages->rgPackages[i];
305
+
306
+ if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
307
+ {
308
+ for (DWORD k = 0; k < pPackage->Msi.cSlipstreamMspPackages; ++k)
309
+ {
310
+ if (pPackage->Msi.rgsczSlipstreamMspPackageIds[k])
311
+ {
312
+ AssertSz(FALSE, "MSI slipstream MSP package doesn't exist.");
313
+ }
314
+ }
315
+ }
316
+ }
317
+#endif
318
+
319
hr = ParsePatchTargetCode(pPackages, pixnBundle);
320
ExitOnFailure(hr, "Failed to parse target product codes.");
321
src/engine/package.h
+20
-1
@@ -14,6 +14,8 @@ typedef _BURN_PACKAGE BURN_PACKAGE;
14
15
// constants
16
17
+const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000;
18
+
19
enum BURN_EXE_EXIT_CODE_TYPE
20
{
21
BURN_EXE_EXIT_CODE_TYPE_NONE,
@@ -116,7 +118,9 @@ typedef struct _BURN_MSPTARGETPRODUCT
118
DWORD dwOrder;
119
WCHAR wzTargetProductCode[39];
120
BURN_PACKAGE* pChainedTargetPackage;
121
+ BOOL fInstalled;
122
BOOL fSlipstream;
123
+ BOOL fSlipstreamRequired; // this means the target product is not present on the machine, but is available in the chain as a slipstream target.
124
125
BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect.
126
BOOTSTRAPPER_REQUEST_STATE defaultRequested; // only valid during Plan.
@@ -172,6 +176,18 @@ typedef struct _BURN_RELATED_MSI
176
DWORD cLanguages;
177
} BURN_RELATED_MSI;
178
179
+typedef struct _BURN_CHAINED_PATCH
180
+{
181
+ BURN_PACKAGE* pMspPackage;
182
+ DWORD dwMspTargetProductIndex; // index into the Msp.rgTargetProducts
183
+} BURN_CHAINED_PATCH;
184
+
185
+typedef struct _BURN_SLIPSTREAM_MSP
186
+{
187
+ BURN_PACKAGE* pMspPackage;
188
+ DWORD dwMsiChainedPatchIndex; // index into the Msi.rgChainedPatches
189
+} BURN_SLIPSTREAM_MSP;
190
+
191
typedef struct _BURN_PACKAGE_PAYLOAD
192
{
193
BURN_PAYLOAD* pPayload;
@@ -295,9 +311,12 @@ typedef struct _BURN_PACKAGE
311
BURN_RELATED_MSI* rgRelatedMsis;
312
DWORD cRelatedMsis;
313
298
- _BURN_PACKAGE** rgpSlipstreamMspPackages;
314
+ BURN_SLIPSTREAM_MSP* rgSlipstreamMsps;
315
LPWSTR* rgsczSlipstreamMspPackageIds;
316
DWORD cSlipstreamMspPackages;
317
+
318
+ BURN_CHAINED_PATCH* rgChainedPatches;
319
+ DWORD cChainedPatches;
320
} Msi;
321
struct
322
{
src/engine/plan.cpp
+2
-2
@@ -2168,7 +2168,7 @@ static HRESULT AddCacheSlipstreamMsps(
2168
2169
for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i)
2170
{
2171
- BURN_PACKAGE* pMspPackage = pPackage->Msi.rgpSlipstreamMspPackages[i];
2171
+ BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage;
2172
AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
2173
2174
hr = AddCachePackageHelper(pPlan, pMspPackage, &hIgnored);
@@ -2791,7 +2791,7 @@ static HRESULT FinalizeSlipstreamPatchActions(
2791
{
2792
for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j)
2793
{
2794
- BURN_PACKAGE* pMspPackage = pPackage->Msi.rgpSlipstreamMspPackages[j];
2794
+ BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[j].pMspPackage;
2795
AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
2796
2797
pAction->msiPackage.rgSlipstreamPatches[j] = fExecute ? pMspPackage->execute : pMspPackage->rollback;
src/test/BurnUnitTest/BurnUnitTest.vcxproj
+1
@@ -71,6 +71,7 @@
71
<ItemGroup>
72
<None Include="TestData\PlanTest\BasicFunctionality_BundleA_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
73
<None Include="TestData\PlanTest\MsiTransaction_BundleAv1_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
74
+ <None Include="TestData\PlanTest\Slipstream_BundleA_manifest.xml" CopyToOutputDirectory="PreserveNewest" />
75
</ItemGroup>
76
<ItemGroup>
77
<Reference Include="System" />
src/test/BurnUnitTest/PlanTest.cpp
+301
-2
@@ -11,6 +11,7 @@ static HRESULT WINAPI PlanTestBAProc(
11
12
static LPCWSTR wzMsiTransactionManifestFileName = L"MsiTransaction_BundleAv1_manifest.xml";
13
static LPCWSTR wzSingleMsiManifestFileName = L"BasicFunctionality_BundleA_manifest.xml";
14
+static LPCWSTR wzSlipstreamManifestFileName = L"Slipstream_BundleA_manifest.xml";
15
16
namespace Microsoft
17
{
@@ -650,6 +651,210 @@ namespace Bootstrapper
651
ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_IGNORED, BURN_PACKAGE_REGISTRATION_STATE_IGNORED);
652
}
653
654
+ [Fact]
655
+ void SlipstreamInstallTest()
656
+ {
657
+ HRESULT hr = S_OK;
658
+ BURN_ENGINE_STATE engineState = { };
659
+ BURN_ENGINE_STATE* pEngineState = &engineState;
660
+ BURN_PLAN* pPlan = &engineState.plan;
661
+
662
+ InitializeEngineStateForCorePlan(wzSlipstreamManifestFileName, pEngineState);
663
+ DetectPermanentPackagesAsPresentAndCached(pEngineState);
664
+ PlanTestDetectPatchInitialize(pEngineState);
665
+
666
+ hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
667
+ NativeAssert::Succeeded(hr, "CorePlan failed");
668
+
669
+ Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
670
+ Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
671
+ Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
672
+
673
+ BOOL fRollback = FALSE;
674
+ DWORD dwIndex = 0;
675
+ DWORD dwPackageStart = 0;
676
+ ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
677
+ dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PatchA", 4, 1, 20480, FALSE);
678
+ ValidateCacheAcquirePayload(pPlan, fRollback, dwIndex++, L"PatchA", L"PatchA", FALSE);
679
+ ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PatchA", L"PatchA", TRUE, FALSE, dwPackageStart);
680
+ ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PatchA", FALSE);
681
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
682
+ ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2);
683
+ dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 10, 1, 32768, FALSE);
684
+ ValidateCacheAcquirePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", FALSE);
685
+ ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
686
+ ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
687
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
688
+ Assert::Equal(dwIndex, pPlan->cCacheActions);
689
+
690
+ fRollback = TRUE;
691
+ dwIndex = 0;
692
+ ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2);
693
+ ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
694
+ Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
695
+
696
+ Assert::Equal(3055111ull, pPlan->qwEstimatedSize);
697
+ Assert::Equal(53248ull, pPlan->qwCacheSizeTotal);
698
+
699
+ fRollback = FALSE;
700
+ dwIndex = 0;
701
+ DWORD dwExecuteCheckpointId = 3;
702
+ BURN_EXECUTE_ACTION* pExecuteAction = NULL;
703
+ ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
704
+ ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[11].syncpoint.hEvent);
705
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
706
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
707
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
708
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
709
+ ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
710
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
711
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER);
712
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
713
+ ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[5].syncpoint.hEvent);
714
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
715
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
716
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_REGISTER);
717
+ pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_INSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE);
718
+ ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
719
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
720
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER);
721
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
722
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
723
+ Assert::Equal(dwIndex, pPlan->cExecuteActions);
724
+
725
+ fRollback = TRUE;
726
+ dwIndex = 0;
727
+ dwExecuteCheckpointId = 3;
728
+ ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
729
+ ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
730
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
731
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
732
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
733
+ ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
734
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
735
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_UNREGISTER);
736
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
737
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
738
+ ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
739
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
740
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_UNREGISTER);
741
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
742
+ pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE);
743
+ ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
744
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_UNREGISTER);
745
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
746
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
747
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
748
+ Assert::Equal(dwIndex, pPlan->cRollbackActions);
749
+
750
+ Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
751
+ Assert::Equal(4ul, pPlan->cOverallProgressTicksTotal);
752
+
753
+ dwIndex = 0;
754
+ Assert::Equal(dwIndex, pPlan->cCleanActions);
755
+
756
+ UINT uIndex = 0;
757
+ ValidatePlannedProvider(pPlan, uIndex++, L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", NULL);
758
+ Assert::Equal(uIndex, pPlan->cPlannedProviders);
759
+
760
+ Assert::Equal(3ul, pEngineState->packages.cPackages);
761
+ ValidatePermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"NetFx48Web");
762
+ ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[1], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT);
763
+ ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[2], L"PatchA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT);
764
+ }
765
+
766
+ [Fact]
767
+ void SlipstreamUninstallTest()
768
+ {
769
+ HRESULT hr = S_OK;
770
+ BURN_ENGINE_STATE engineState = { };
771
+ BURN_ENGINE_STATE* pEngineState = &engineState;
772
+ BURN_PLAN* pPlan = &engineState.plan;
773
+
774
+ InitializeEngineStateForCorePlan(wzSlipstreamManifestFileName, pEngineState);
775
+ DetectPackagesAsPresentAndCached(pEngineState);
776
+
777
+ hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL);
778
+ NativeAssert::Succeeded(hr, "CorePlan failed");
779
+
780
+ Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
781
+ Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
782
+ Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
783
+
784
+ BOOL fRollback = FALSE;
785
+ DWORD dwIndex = 0;
786
+ Assert::Equal(dwIndex, pPlan->cCacheActions);
787
+
788
+ fRollback = TRUE;
789
+ dwIndex = 0;
790
+ Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
791
+
792
+ Assert::Equal(0ull, pPlan->qwEstimatedSize);
793
+ Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
794
+
795
+ fRollback = FALSE;
796
+ dwIndex = 0;
797
+ DWORD dwExecuteCheckpointId = 1;
798
+ BURN_EXECUTE_ACTION* pExecuteAction = NULL;
799
+ ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
800
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
801
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_UNREGISTER);
802
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
803
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_UNREGISTER);
804
+ pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE);
805
+ ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
806
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
807
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
808
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_UNREGISTER);
809
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
810
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
811
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
812
+ ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
813
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
814
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
815
+ Assert::Equal(dwIndex, pPlan->cExecuteActions);
816
+
817
+ fRollback = TRUE;
818
+ dwIndex = 0;
819
+ dwExecuteCheckpointId = 1;
820
+ ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
821
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER);
822
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
823
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_REGISTER);
824
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
825
+ pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_INSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, TRUE);
826
+ ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
827
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
828
+ ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER);
829
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
830
+ ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
831
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
832
+ ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
833
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
834
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
835
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
836
+ Assert::Equal(dwIndex, pPlan->cRollbackActions);
837
+
838
+ Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
839
+ Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
840
+
841
+ dwIndex = 0;
842
+ ValidateCleanAction(pPlan, dwIndex++, L"PatchA");
843
+ ValidateCleanAction(pPlan, dwIndex++, L"PackageA");
844
+ Assert::Equal(dwIndex, pPlan->cCleanActions);
845
+
846
+ UINT uIndex = 0;
847
+ ValidatePlannedProvider(pPlan, uIndex++, L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", NULL);
848
+ ValidatePlannedProvider(pPlan, uIndex++, L"{0A5113E3-06A5-4CE0-8E83-9EB42F6764A6}", NULL);
849
+ ValidatePlannedProvider(pPlan, uIndex++, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", NULL);
850
+ Assert::Equal(uIndex, pPlan->cPlannedProviders);
851
+
852
+ Assert::Equal(3ul, pEngineState->packages.cPackages);
853
+ ValidatePermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"NetFx48Web");
854
+ ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[1], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
855
+ ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[2], L"PatchA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
856
+ }
857
+
858
private:
859
// This doesn't initialize everything, just enough for CorePlan to work.
860
void InitializeEngineStateForCorePlan(LPCWSTR wzManifestFileName, BURN_ENGINE_STATE* pEngineState)
@@ -700,6 +905,30 @@ namespace Bootstrapper
905
pEngineState->fDetected = TRUE;
906
}
907
908
+ void PlanTestDetectPatchInitialize(BURN_ENGINE_STATE* pEngineState)
909
+ {
910
+ HRESULT hr = MsiEngineDetectInitialize(&pEngineState->packages);
911
+ NativeAssert::Succeeded(hr, "MsiEngineDetectInitialize failed");
912
+
913
+ for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
914
+ {
915
+ BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
916
+
917
+ if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
918
+ {
919
+ for (DWORD j = 0; j < pPackage->Msp.cTargetProductCodes; ++j)
920
+ {
921
+ BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + j;
922
+
923
+ if (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN == pTargetProduct->patchPackageState)
924
+ {
925
+ pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
926
+ }
927
+ }
928
+ }
929
+ }
930
+ }
931
+
932
void DetectAttachedContainerAsAttached(BURN_ENGINE_STATE* pEngineState)
933
{
934
for (DWORD i = 0; i < pEngineState->containers.cContainers; ++i)
@@ -773,6 +1002,21 @@ namespace Bootstrapper
1002
BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
1003
DetectPackageAsPresentAndCached(pPackage);
1004
DetectPackageDependent(pPackage, pEngineState->registration.sczId);
1005
+
1006
+ if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
1007
+ {
1008
+ for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j)
1009
+ {
1010
+ pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
1011
+
1012
+ BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[j].pMspPackage;
1013
+ MspEngineAddDetectedTargetProduct(&pEngineState->packages, pMspPackage, j, pPackage->Msi.sczProductCode, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED);
1014
+
1015
+ BURN_MSPTARGETPRODUCT* pTargetProduct = pMspPackage->Msp.rgTargetProducts + (pMspPackage->Msp.cTargetProductCodes - 1);
1016
+ pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
1017
+ pTargetProduct->registrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1018
+ }
1019
+ }
1020
}
1021
}
1022
@@ -862,7 +1106,23 @@ namespace Bootstrapper
1106
{
1107
BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1108
Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, pAction->type);
865
- NativeAssert::StringEqual(wzContainerId, pAction->extractContainer.pContainer->sczId);
1109
+ NativeAssert::StringEqual(wzContainerId, pAction->resolveContainer.pContainer->sczId);
1110
+ Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1111
+ }
1112
+
1113
+ void ValidateCacheAcquirePayload(
1114
+ __in BURN_PLAN* pPlan,
1115
+ __in BOOL fRollback,
1116
+ __in DWORD dwIndex,
1117
+ __in LPCWSTR wzPackageId,
1118
+ __in LPCWSTR wzPayloadId,
1119
+ __in BOOL fSkipUntilRetried
1120
+ )
1121
+ {
1122
+ BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1123
+ Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD, pAction->type);
1124
+ NativeAssert::StringEqual(wzPackageId, pAction->resolvePayload.pPackage->sczId);
1125
+ NativeAssert::StringEqual(wzPayloadId, pAction->resolvePayload.pPayload->sczKey);
1126
Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1127
}
1128
@@ -1063,7 +1323,7 @@ namespace Bootstrapper
1323
__in BURN_PLAN* pPlan,
1324
__in BOOL fRollback,
1325
__in DWORD dwIndex,
1066
- __in LPCWSTR wzPackageId,
1326
+ __in_z LPCWSTR wzPackageId,
1327
__in BOOTSTRAPPER_ACTION_STATE action,
1328
__in BURN_MSI_PROPERTY actionMsiProperty,
1329
__in DWORD uiLevel,
@@ -1083,6 +1343,45 @@ namespace Bootstrapper
1343
Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1344
}
1345
1346
+ BURN_EXECUTE_ACTION* ValidateDeletedExecuteMspTarget(
1347
+ __in BURN_PLAN* pPlan,
1348
+ __in BOOL fRollback,
1349
+ __in DWORD dwIndex,
1350
+ __in_z LPCWSTR wzPackageId,
1351
+ __in BOOTSTRAPPER_ACTION_STATE action,
1352
+ __in_z LPCWSTR wzTargetProductCode,
1353
+ __in BOOL fPerMachineTarget,
1354
+ __in BURN_MSI_PROPERTY actionMsiProperty,
1355
+ __in DWORD uiLevel,
1356
+ __in BOOL fDisableExternalUiHandler,
1357
+ __in BOOL fDeleted
1358
+ )
1359
+ {
1360
+ BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1361
+ Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_MSP_TARGET, pAction->type);
1362
+ NativeAssert::StringEqual(wzPackageId, pAction->mspTarget.pPackage->sczId);
1363
+ Assert::Equal<DWORD>(action, pAction->mspTarget.action);
1364
+ NativeAssert::StringEqual(wzTargetProductCode, pAction->mspTarget.sczTargetProductCode);
1365
+ Assert::Equal<BOOL>(fPerMachineTarget, pAction->mspTarget.fPerMachineTarget);
1366
+ Assert::Equal<DWORD>(actionMsiProperty, pAction->mspTarget.actionMsiProperty);
1367
+ Assert::Equal<DWORD>(uiLevel, pAction->mspTarget.uiLevel);
1368
+ Assert::Equal<BOOL>(fDisableExternalUiHandler, pAction->mspTarget.fDisableExternalUiHandler);
1369
+ NativeAssert::NotNull(pAction->mspTarget.sczLogPath);
1370
+ Assert::Equal<BOOL>(fDeleted, pAction->fDeleted);
1371
+ return pAction;
1372
+ }
1373
+
1374
+ void ValidateExecuteMspTargetPatch(
1375
+ __in BURN_EXECUTE_ACTION* pAction,
1376
+ __in DWORD dwIndex,
1377
+ __in_z LPCWSTR wzPackageId
1378
+ )
1379
+ {
1380
+ Assert::InRange(dwIndex + 1ul, 1ul, pAction->mspTarget.cOrderedPatches);
1381
+ BURN_ORDERED_PATCHES* pOrderedPatch = pAction->mspTarget.rgOrderedPatches + dwIndex;
1382
+ NativeAssert::StringEqual(wzPackageId, pOrderedPatch->pPackage->sczId);
1383
+ }
1384
+
1385
void ValidateExecutePackageDependency(
1386
__in BURN_PLAN* pPlan,
1387
__in BOOL fRollback,
src/test/BurnUnitTest/TestData/PlanTest/Slipstream_BundleA_manifest.xml
new
+1
@@ -0,0 +1 @@
1
+<?xml version="1.0" encoding="utf-8"?><BurnManifest xmlns="http://wixtoolset.org/schemas/v4/2008/Burn"><Log PathVariable="WixBundleLog" Prefix="~SlipstreamTests_BundleA" Extension=".log" /><RelatedBundle Id="{62C28DAF-A13E-4F55-ACA1-FB843630789C}" Action="Upgrade" /><Variable Id="TestGroupName" Value="SlipstreamTests" Type="string" Hidden="no" Persisted="no" /><Variable Id="WixBundleName" Hidden="no" Persisted="yes" /><Variable Id="WixBundleOriginalSource" Hidden="no" Persisted="yes" /><Variable Id="WixBundleOriginalSourceFolder" Hidden="no" Persisted="yes" /><Variable Id="WixBundleLastUsedSource" Hidden="no" Persisted="yes" /><RegistrySearch Id="NETFRAMEWORK45" Variable="NETFRAMEWORK45" Root="HKLM" Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Value="Release" Type="value" VariableType="string" /><UX><Payload Id="WixManagedBootstrapperApplicationHost" FilePath="mbahost.dll" FileSize="140288" Hash="4569C53566B1025E243E0C29A96C608BD4019979" Packaging="embedded" SourcePath="u30" /><Payload Id="payO60IVK4ATGzPpMz3rwVbUWl6DyU" FilePath="WixToolset.Mba.Host.config" FileSize="783" Hash="B5BDD5E7179A94C2C817069913CA8C099DF811B9" Packaging="embedded" SourcePath="u0" /><Payload Id="payxj4zDAKL2NVlz4ohp0GvwFHepyI" FilePath="TestBA.dll" FileSize="25088" Hash="DB12DB6565CDBC4E9705204830E421ACEB710129" Packaging="embedded" SourcePath="u1" /><Payload Id="pay1hOSAUC8_D633cD2TXpIXCL30OU" FilePath="mbanative.dll" FileSize="118272" Hash="3A7A20D97B0546A23A025EE5774BE237C14D2957" Packaging="embedded" SourcePath="u2" /><Payload Id="payujy6Izl_BlUNfHt2eI.ADfjYAv4" FilePath="WixToolset.Mba.Core.dll" FileSize="114688" Hash="56BA3EA94BEBF8EB562C914495E1594E74F05DBE" Packaging="embedded" SourcePath="u3" /><Payload Id="payR4EbR4OTDZpPEycWaSSM_gZRBWM" FilePath="mbapreq.thm" FileSize="3599" Hash="8D9797C1E1A50AECB8B85FFCEA6A2A2EF611BD7F" Packaging="embedded" SourcePath="u4" /><Payload Id="paylVCy2Ecl8pHPdJTCQZryUG4T9us" FilePath="mbapreq.png" FileSize="797" Hash="75AE41181581FD6376CA9CA88147011E48BF9A30" Packaging="embedded" SourcePath="u5" /><Payload Id="payTaG4B_lob1aLcKFaOqSSG3MPMpU" FilePath="mbapreq.wxl" FileSize="2237" Hash="068B3C5E27AECE7987EABAA2802C9EB07B39EAF8" Packaging="embedded" SourcePath="u6" /><Payload Id="payZwIGuiezVTitZOoZKxyh2DdRSGs" FilePath="1028\mbapreq.wxl" FileSize="1998" Hash="A989D9B892F497215D81F903591ECB6CD50CFFFC" Packaging="embedded" SourcePath="u7" /><Payload Id="pay.herBWX.LlOh8jLsx24aWdunV_0" FilePath="1029\mbapreq.wxl" FileSize="2428" Hash="E6B8E4B1AA89430EB6A5A1E997CA3D1D2F968285" Packaging="embedded" SourcePath="u8" /><Payload Id="pay8DkMszYsoxxdgX14huLDMYXylQg" FilePath="1030\mbapreq.wxl" FileSize="2256" Hash="612CD2FD0CF3800639385C0BF4D805B24507D356" Packaging="embedded" SourcePath="u9" /><Payload Id="payPaHpoTeOdkW.TK99IDwktNLhTAg" FilePath="1031\mbapreq.wxl" FileSize="2409" Hash="E59A8F11D95AC17FC70BD718706EE36BFA50EF02" Packaging="embedded" SourcePath="u10" /><Payload Id="pay45AtAzterLTMzZgdxxtuYvaiXwU" FilePath="1032\mbapreq.wxl" FileSize="3368" Hash="154E0A658BA7EE59889224A231423634A9725547" Packaging="embedded" SourcePath="u11" /><Payload Id="payA2VEKIqhePyNIEmr14eyH3JoVLc" FilePath="1035\mbapreq.wxl" FileSize="2205" Hash="6AAE55269E42F99A5D88ADD18C433384DEB9E956" Packaging="embedded" SourcePath="u12" /><Payload Id="payvre23ObscjzhcaFIifUAkXMdPa8" FilePath="1036\mbapreq.wxl" FileSize="2276" Hash="7DC74874357F50AE8C4871D8F4DC06B337CF6352" Packaging="embedded" SourcePath="u13" /><Payload Id="paytxUV3vuBbG2c.a9c.d_sZX2x6wA" FilePath="1038\mbapreq.wxl" FileSize="2362" Hash="B60C34DE38E6E48BA0841E8A962C17179FC1B69A" Packaging="embedded" SourcePath="u14" /><Payload Id="payYvMWRK9xelo5.sQn7jRkJIaBp9A" FilePath="1040\mbapreq.wxl" FileSize="2273" Hash="902D231AD6306087F215DEABB7F2AB2F8072C401" Packaging="embedded" SourcePath="u15" /><Payload Id="pay68KKSApyQimbA25t6kSbqhdeH10" FilePath="1041\mbapreq.wxl" FileSize="2518" Hash="4095A1AFCF18C01F7DA51A1A389C2FBBB1A82A12" Packaging="embedded" SourcePath="u16" /><Payload Id="paypiqxaHpYZqx.9eDVjQrj1igLbRY" FilePath="1042\mbapreq.wxl" FileSize="2209" Hash="99CE8B42300EF656E6BD44F01766DC638CB0496F" Packaging="embedded" SourcePath="u17" /><Payload Id="payTO0YwZzxKpbqdrBVUcVRTu3BFe8" FilePath="1043\mbapreq.wxl" FileSize="2282" Hash="87117EE32E0004E25DDCEB1A7D417F3A02856A50" Packaging="embedded" SourcePath="u18" /><Payload Id="payIXg2ldBJukRzhqWolJVOEbTmF34" FilePath="1044\mbapreq.wxl" FileSize="2141" Hash="5AED841C6A870C3A8BAF8A10D00F887A781D0CF0" Packaging="embedded" SourcePath="u19" /><Payload Id="payOHIZbSkIvrpwKkkXI173tv3u3B4" FilePath="1045\mbapreq.wxl" FileSize="2338" Hash="07E37CBC59298F24A5C8C3B8FEB7A45DADF8CD07" Packaging="embedded" SourcePath="u20" /><Payload Id="payQRQ_UZl_R2UtV0xDXB2yeH2bg3E" FilePath="1046\mbapreq.wxl" FileSize="2118" Hash="AEC0CE51E8E335E9B86F1AC7E39CCD172B896582" Packaging="embedded" SourcePath="u21" /><Payload Id="payhrejLLBfc1i27iN._QPhQ4K337I" FilePath="1049\mbapreq.wxl" FileSize="2851" Hash="9628BADB173B171ED85D902634D9AA5D91FE9721" Packaging="embedded" SourcePath="u22" /><Payload Id="payqEzaDNzxB68vGp29jgDcCos6dvg" FilePath="1051\mbapreq.wxl" FileSize="2304" Hash="B584E8C0D7F9B7A1BB70BC00E42BFD35BED5D81D" Packaging="embedded" SourcePath="u23" /><Payload Id="paydz8Vk8xSTyYohgGXTSIxWGXL5.Q" FilePath="1053\mbapreq.wxl" FileSize="2102" Hash="67E93F555DBFEF8508E79F7CA8CE76B881308760" Packaging="embedded" SourcePath="u24" /><Payload Id="pay0HRUZTlbC3taSOffJBsEj92Br8Y" FilePath="1055\mbapreq.wxl" FileSize="2273" Hash="AEB8C90D66942A5CD73EA52A6F2ADD4F7D518A0D" Packaging="embedded" SourcePath="u25" /><Payload Id="payIvUOkc_EMH7laMFehefNolV8hZo" FilePath="1060\mbapreq.wxl" FileSize="2170" Hash="B1D4B71907B8BD82DD8B047404AF10FDBBE5CBA0" Packaging="embedded" SourcePath="u26" /><Payload Id="payLFhOb.rHuk4sW5CYAPMShG0NjGI" FilePath="2052\mbapreq.wxl" FileSize="1953" Hash="C8FB8982EC71C48D6EA021ADD9AAA7BCB0656281" Packaging="embedded" SourcePath="u27" /><Payload Id="payqIKCmERK7Nhxx_nNXvRxdKqKDbI" FilePath="2070\mbapreq.wxl" FileSize="2182" Hash="825F27A543907ED27E815EC67DFD48AF7BF5831E" Packaging="embedded" SourcePath="u28" /><Payload Id="payqeWUzIVaEqjuRXN0z8ECC3Y4tCc" FilePath="3082\mbapreq.wxl" FileSize="2369" Hash="39C07C31077AAFDC0DD208273AA41654CAD80FDD" Packaging="embedded" SourcePath="u29" /><Payload Id="paylfeHEjJSSTnNzY9QMZM2Ye3Ipy4" FilePath="mbapreq.dll" FileSize="245760" Hash="6499FA21D178131DDE13A4EF44ABEC32E91D65D4" Packaging="embedded" SourcePath="u31" /><Payload Id="payDPxs6uy8nbky.R7zhir2RRAfc.c" FilePath="WixToolset.Mba.Host.dll" FileSize="11264" Hash="9E6452891E401EB211DD41550A09FDF98EC0992F" Packaging="embedded" SourcePath="u32" /><Payload Id="uxTxMXPVMXwQrPTMIGa5WGt93w0Ns" FilePath="BootstrapperApplicationData.xml" FileSize="14292" Hash="CDF09A0723F4F33C13670BBAFCFFA7E660E15DFC" Packaging="embedded" SourcePath="u33" /><Payload Id="uxYRbgitOs0K878jn5L_z7LdJ21KI" FilePath="BundleExtensionData.xml" FileSize="252" Hash="86688B13D3364ADB90BBA552F544D4D546AFD63D" Packaging="embedded" SourcePath="u34" /></UX><Payload Id="NetFx48Web" FilePath="redist\ndp48-web.exe" FileSize="1479400" Hash="5A84A8E612E270E27D0061D58DB6B470153BE1F9" DownloadUrl="https://go.microsoft.com/fwlink/?LinkId=2085155" Packaging="external" SourcePath="redist\ndp48-web.exe" /><Payload Id="PackageA" FilePath="PackageAv1.msi" FileSize="32768" Hash="2369B16B7219B3C834DFBC5D2AF8B2EF8803D43D" Packaging="external" SourcePath="PackageAv1.msi" /><Payload Id="PatchA" FilePath="PatchA.msp" FileSize="20480" Hash="FABC6C18E4A778E127E84CDF67F93A291CAEC8BB" Packaging="external" SourcePath="PatchA.msp" /><RollbackBoundary Id="WixDefaultBoundary" Vital="yes" Transaction="no" /><Registration Id="{22D1DDBA-284D-40A7-BD14-95EA07906F21}" ExecutableName="BundleA.exe" PerMachine="yes" Tag="" Version="1.0.0.0" ProviderKey="{22D1DDBA-284D-40A7-BD14-95EA07906F21}"><Arp Register="yes" DisplayName="~SlipstreamTests - BundleA" DisplayVersion="1.0.0.0" /></Registration><Chain><ExePackage Id="NetFx48Web" Cache="yes" CacheId="5A84A8E612E270E27D0061D58DB6B470153BE1F9" InstallSize="1479400" Size="1479400" PerMachine="yes" Permanent="yes" Vital="yes" RollbackBoundaryForward="WixDefaultBoundary" LogPathVariable="NetFx48WebLog" RollbackLogPathVariable="WixBundleRollbackLog_NetFx48Web" DetectCondition="NETFRAMEWORK45 >= 528040" InstallArguments="/q /norestart /ChainingPackage "[WixBundleName]" /log "[NetFx48WebLog].html"" UninstallArguments="/uninstall /q /norestart /ChainingPackage "[WixBundleName]" /log "[NetFx48WebLog].html"" RepairArguments="/q /norestart /repair /ChainingPackage "[WixBundleName]" /log "[NetFx48WebLog].html"" Repairable="yes" Protocol="netfx4"><PayloadRef Id="NetFx48Web" /></ExePackage><MsiPackage Id="PackageA" Cache="yes" CacheId="{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}v1.0.0.0" InstallSize="2103" Size="32768" PerMachine="yes" Permanent="no" Vital="yes" LogPathVariable="WixBundleLog_PackageA" RollbackLogPathVariable="WixBundleRollbackLog_PackageA" ProductCode="{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}" Language="1033" Version="1.0.0.0" UpgradeCode="{DB87BB66-FE5D-4293-81AC-EE313D3F864B}"><MsiProperty Id="ARPSYSTEMCOMPONENT" Value="1" /><MsiProperty Id="MSIFASTINSTALL" Value="7" /><SlipstreamMsp Id="PatchA" /><Provides Key="{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}" Version="1.0.0.0" DisplayName="~SlipstreamTests - PackageA" /><RelatedPackage Id="{DB87BB66-FE5D-4293-81AC-EE313D3F864B}" MaxVersion="1.0.0.0" MaxInclusive="no" OnlyDetect="no" LangInclusive="no"><Language Id="1033" /></RelatedPackage><RelatedPackage Id="{DB87BB66-FE5D-4293-81AC-EE313D3F864B}" MinVersion="1.0.0.0" MinInclusive="no" OnlyDetect="yes" LangInclusive="no"><Language Id="1033" /></RelatedPackage><PayloadRef Id="PackageA" /></MsiPackage><MspPackage Id="PatchA" Cache="yes" CacheId="{0A5113E3-06A5-4CE0-8E83-9EB42F6764A6}" InstallSize="20480" Size="20480" PerMachine="yes" Permanent="no" Vital="yes" RollbackBoundaryBackward="WixDefaultBoundary" LogPathVariable="WixBundleLog_PatchA" RollbackLogPathVariable="WixBundleRollbackLog_PatchA" PatchCode="{0A5113E3-06A5-4CE0-8E83-9EB42F6764A6}" PatchXml="<?xml version="1.0" encoding="utf-16"?><MsiPatch xmlns="http://www.microsoft.com/msi/patch_applicability.xsd" SchemaVersion="1.0.0.0" PatchGUID="{0A5113E3-06A5-4CE0-8E83-9EB42F6764A6}" MinMsiVersion="5" TargetsRTM="true"><TargetProduct MinMsiVersion="500"><TargetProductCode Validate="true">{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}</TargetProductCode><TargetVersion Validate="true" ComparisonType="Equal" ComparisonFilter="MajorMinorUpdate">1.0.0.0</TargetVersion><UpdatedVersion>1.0.1.0</UpdatedVersion><TargetLanguage Validate="false">1033</TargetLanguage><UpdatedLanguages>1033</UpdatedLanguages><UpgradeCode Validate="true">{DB87BB66-FE5D-4293-81AC-EE313D3F864B}</UpgradeCode></TargetProduct><TargetProductCode>{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}</TargetProductCode></MsiPatch>"><Provides Key="{0A5113E3-06A5-4CE0-8E83-9EB42F6764A6}" DisplayName="SlipstreamTests - Patch A" /><PayloadRef Id="PatchA" /></MspPackage></Chain><PatchTargetCode TargetCode="{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}" Product="yes" /></BurnManifest>
\ No newline at end of file