diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-02-22 16:16:12 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-02-22 20:25:06 -0600 |
commit | 4f4c85ed66f1b2dfb1bec76d54d7b50c637d5bfa (patch) | |
tree | 6de8e63ad46626ec457af256d481e81d726f3860 /src/engine | |
parent | d0d93beac0b79fa9c3d43398813954988afda18f (diff) | |
download | wix-4f4c85ed66f1b2dfb1bec76d54d7b50c637d5bfa.tar.gz wix-4f4c85ed66f1b2dfb1bec76d54d7b50c637d5bfa.tar.bz2 wix-4f4c85ed66f1b2dfb1bec76d54d7b50c637d5bfa.zip |
Add patch target for slipstream MSI package even if not installed.
Fixes #3897
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/core.cpp | 3 | ||||
-rw-r--r-- | src/engine/detect.cpp | 10 | ||||
-rw-r--r-- | src/engine/msiengine.cpp | 56 | ||||
-rw-r--r-- | src/engine/msiengine.h | 3 | ||||
-rw-r--r-- | src/engine/mspengine.cpp | 196 | ||||
-rw-r--r-- | src/engine/mspengine.h | 16 | ||||
-rw-r--r-- | src/engine/package.cpp | 23 | ||||
-rw-r--r-- | src/engine/package.h | 21 | ||||
-rw-r--r-- | src/engine/plan.cpp | 4 |
9 files changed, 243 insertions, 89 deletions
diff --git a/src/engine/core.cpp b/src/engine/core.cpp index 1a079973..cb7ebbfd 100644 --- a/src/engine/core.cpp +++ b/src/engine/core.cpp | |||
@@ -351,6 +351,9 @@ extern "C" HRESULT CoreDetect( | |||
351 | { | 351 | { |
352 | hr = MspEngineDetectInitialize(&pEngineState->packages); | 352 | hr = MspEngineDetectInitialize(&pEngineState->packages); |
353 | ExitOnFailure(hr, "Failed to initialize MSP engine detection."); | 353 | ExitOnFailure(hr, "Failed to initialize MSP engine detection."); |
354 | |||
355 | hr = MsiEngineDetectInitialize(&pEngineState->packages); | ||
356 | ExitOnFailure(hr, "Failed to initialize MSI engine detection."); | ||
354 | } | 357 | } |
355 | 358 | ||
356 | for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) | 359 | for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) |
diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp index b702306e..9bb58487 100644 --- a/src/engine/detect.cpp +++ b/src/engine/detect.cpp | |||
@@ -82,6 +82,16 @@ extern "C" void DetectReset( | |||
82 | 82 | ||
83 | pFeature->currentState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; | 83 | pFeature->currentState = BOOTSTRAPPER_FEATURE_STATE_UNKNOWN; |
84 | } | 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; | ||
85 | } | 95 | } |
86 | else if (BURN_PACKAGE_TYPE_MSP == pPackage->type) | 96 | else if (BURN_PACKAGE_TYPE_MSP == pPackage->type) |
87 | { | 97 | { |
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp index 801bf9a8..ae105155 100644 --- a/src/engine/msiengine.cpp +++ b/src/engine/msiengine.cpp | |||
@@ -213,8 +213,8 @@ extern "C" HRESULT MsiEngineParsePackageFromXml( | |||
213 | 213 | ||
214 | if (cNodes) | 214 | if (cNodes) |
215 | { | 215 | { |
216 | pPackage->Msi.rgpSlipstreamMspPackages = reinterpret_cast<BURN_PACKAGE**>(MemAlloc(sizeof(BURN_PACKAGE*) * cNodes, TRUE)); | 216 | pPackage->Msi.rgSlipstreamMsps = reinterpret_cast<BURN_SLIPSTREAM_MSP*>(MemAlloc(sizeof(BURN_SLIPSTREAM_MSP) * cNodes, TRUE)); |
217 | ExitOnNull(pPackage->Msi.rgpSlipstreamMspPackages, hr, E_OUTOFMEMORY, "Failed to allocate memory for slipstream MSP packages."); | 217 | ExitOnNull(pPackage->Msi.rgSlipstreamMsps, hr, E_OUTOFMEMORY, "Failed to allocate memory for slipstream MSP packages."); |
218 | 218 | ||
219 | pPackage->Msi.rgsczSlipstreamMspPackageIds = reinterpret_cast<LPWSTR*>(MemAlloc(sizeof(LPWSTR*) * cNodes, TRUE)); | 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."); | 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); | 383 | MemFree(pPackage->Msi.rgsczSlipstreamMspPackageIds); |
384 | } | 384 | } |
385 | 385 | ||
386 | if (pPackage->Msi.rgpSlipstreamMspPackages) | 386 | if (pPackage->Msi.rgSlipstreamMsps) |
387 | { | 387 | { |
388 | MemFree(pPackage->Msi.rgpSlipstreamMspPackages); | 388 | MemFree(pPackage->Msi.rgSlipstreamMsps); |
389 | } | ||
390 | |||
391 | if (pPackage->Msi.rgChainedPatches) | ||
392 | { | ||
393 | MemFree(pPackage->Msi.rgChainedPatches); | ||
389 | } | 394 | } |
390 | 395 | ||
391 | // clear struct | 396 | // clear struct |
392 | memset(&pPackage->Msi, 0, sizeof(pPackage->Msi)); | 397 | memset(&pPackage->Msi, 0, sizeof(pPackage->Msi)); |
393 | } | 398 | } |
394 | 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 | |||
395 | extern "C" HRESULT MsiEngineDetectPackage( | 432 | extern "C" HRESULT MsiEngineDetectPackage( |
396 | __in BURN_PACKAGE* pPackage, | 433 | __in BURN_PACKAGE* pPackage, |
397 | __in BURN_USER_EXPERIENCE* pUserExperience | 434 | __in BURN_USER_EXPERIENCE* pUserExperience |
@@ -971,15 +1008,6 @@ extern "C" HRESULT MsiEnginePlanAddPackage( | |||
971 | pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes; | 1008 | pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes; |
972 | } | 1009 | } |
973 | 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 | |||
983 | LExit: | 1011 | LExit: |
984 | ReleaseMem(rgFeatureActions); | 1012 | ReleaseMem(rgFeatureActions); |
985 | ReleaseMem(rgRollbackFeatureActions); | 1013 | ReleaseMem(rgRollbackFeatureActions); |
@@ -1897,7 +1925,7 @@ static HRESULT ConcatPatchProperty( | |||
1897 | { | 1925 | { |
1898 | for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i) | 1926 | for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i) |
1899 | { | 1927 | { |
1900 | BURN_PACKAGE* pMspPackage = pPackage->Msi.rgpSlipstreamMspPackages[i]; | 1928 | BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage; |
1901 | AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); | 1929 | AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); |
1902 | 1930 | ||
1903 | BOOTSTRAPPER_ACTION_STATE patchExecuteAction = rgSlipstreamPatchActions[i]; | 1931 | BOOTSTRAPPER_ACTION_STATE patchExecuteAction = rgSlipstreamPatchActions[i]; |
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h index fe742a16..6c7c83e5 100644 --- a/src/engine/msiengine.h +++ b/src/engine/msiengine.h | |||
@@ -27,6 +27,9 @@ HRESULT MsiEngineParsePropertiesFromXml( | |||
27 | void MsiEnginePackageUninitialize( | 27 | void MsiEnginePackageUninitialize( |
28 | __in BURN_PACKAGE* pPackage | 28 | __in BURN_PACKAGE* pPackage |
29 | ); | 29 | ); |
30 | HRESULT MsiEngineDetectInitialize( | ||
31 | __in BURN_PACKAGES* pPackages | ||
32 | ); | ||
30 | HRESULT MsiEngineDetectPackage( | 33 | HRESULT MsiEngineDetectPackage( |
31 | __in BURN_PACKAGE* pPackage, | 34 | __in BURN_PACKAGE* pPackage, |
32 | __in BURN_USER_EXPERIENCE* pUserExperience | 35 | __in BURN_USER_EXPERIENCE* pUserExperience |
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp index 14db27a6..4b7f9a0a 100644 --- a/src/engine/mspengine.cpp +++ b/src/engine/mspengine.cpp | |||
@@ -30,18 +30,23 @@ static HRESULT AddPossibleTargetProduct( | |||
30 | __inout DWORD* pcPossibleTargetProducts | 30 | __inout DWORD* pcPossibleTargetProducts |
31 | ); | 31 | ); |
32 | static HRESULT AddDetectedTargetProduct( | 32 | static HRESULT AddDetectedTargetProduct( |
33 | __in BURN_PACKAGES* pPackages, | ||
34 | __in BURN_PACKAGE* pPackage, | 33 | __in BURN_PACKAGE* pPackage, |
35 | __in DWORD dwOrder, | 34 | __in DWORD dwOrder, |
36 | __in_z LPCWSTR wzProductCode, | 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 | ||
38 | ); | 44 | ); |
39 | static void DeterminePatchChainedTarget( | 45 | static HRESULT DeterminePatchChainedTarget( |
40 | __in BURN_PACKAGES* pPackages, | 46 | __in BURN_PACKAGES* pPackages, |
41 | __in BURN_PACKAGE* pMspPackage, | 47 | __in BURN_PACKAGE* pMspPackage, |
42 | __in LPCWSTR wzTargetProductCode, | 48 | __in LPCWSTR wzTargetProductCode, |
43 | __out BURN_PACKAGE** ppChainedTargetPackage, | 49 | __in DWORD dwMspTargetProductIndex |
44 | __out BOOL* pfSlipstreamed | ||
45 | ); | 50 | ); |
46 | static HRESULT PlanTargetProduct( | 51 | static HRESULT PlanTargetProduct( |
47 | __in BOOTSTRAPPER_DISPLAY display, | 52 | __in BOOTSTRAPPER_DISPLAY display, |
@@ -159,16 +164,20 @@ extern "C" HRESULT MspEngineDetectInitialize( | |||
159 | { | 164 | { |
160 | for (DWORD iPatchInfo = 0; iPatchInfo < pPackages->cPatchInfo; ++iPatchInfo) | 165 | for (DWORD iPatchInfo = 0; iPatchInfo < pPackages->cPatchInfo; ++iPatchInfo) |
161 | { | 166 | { |
162 | if (ERROR_SUCCESS == pPackages->rgPatchInfo[iPatchInfo].uStatus) | 167 | hr = HRESULT_FROM_WIN32(pPackages->rgPatchInfo[iPatchInfo].uStatus); |
163 | { | 168 | BURN_PACKAGE* pMspPackage = pPackages->rgPatchInfoToPackage[iPatchInfo]; |
164 | BURN_PACKAGE* pMspPackage = pPackages->rgPatchInfoToPackage[iPatchInfo]; | 169 | Assert(BURN_PACKAGE_TYPE_MSP == pMspPackage->type); |
165 | Assert(BURN_PACKAGE_TYPE_MSP == pMspPackage->type); | ||
166 | 170 | ||
171 | if (S_OK == hr) | ||
172 | { | ||
167 | // Note that we do add superseded and obsolete MSP packages. Package Detect and Plan will sort them out later. | 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); |
169 | ExitOnFailure(hr, "Failed to add target product code to package: %ls", pMspPackage->sczId); | 175 | ExitOnFailure(hr, "Failed to add target product code to package: %ls", pMspPackage->sczId); |
170 | } | 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 | } | ||
172 | } | 181 | } |
173 | } | 182 | } |
174 | else | 183 | else |
@@ -192,6 +201,54 @@ LExit: | |||
192 | return hr; | 201 | return hr; |
193 | } | 202 | } |
194 | 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 | |||
195 | extern "C" HRESULT MspEngineDetectPackage( | 252 | extern "C" HRESULT MspEngineDetectPackage( |
196 | __in BURN_PACKAGE* pPackage, | 253 | __in BURN_PACKAGE* pPackage, |
197 | __in BURN_USER_EXPERIENCE* pUserExperience | 254 | __in BURN_USER_EXPERIENCE* pUserExperience |
@@ -219,7 +276,6 @@ extern "C" HRESULT MspEngineDetectPackage( | |||
219 | for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) | 276 | for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) |
220 | { | 277 | { |
221 | BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; | 278 | BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; |
222 | BOOL fInstalled = FALSE; | ||
223 | 279 | ||
224 | hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState); | 280 | hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState); |
225 | if (SUCCEEDED(hr)) | 281 | if (SUCCEEDED(hr)) |
@@ -227,17 +283,17 @@ extern "C" HRESULT MspEngineDetectPackage( | |||
227 | switch (*sczState) | 283 | switch (*sczState) |
228 | { | 284 | { |
229 | case '1': | 285 | case '1': |
230 | fInstalled = TRUE; | 286 | pTargetProduct->fInstalled = TRUE; |
231 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; | 287 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; |
232 | break; | 288 | break; |
233 | 289 | ||
234 | case '2': | 290 | case '2': |
235 | fInstalled = TRUE; | 291 | pTargetProduct->fInstalled = TRUE; |
236 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; | 292 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; |
237 | break; | 293 | break; |
238 | 294 | ||
239 | case '4': | 295 | case '4': |
240 | fInstalled = TRUE; | 296 | pTargetProduct->fInstalled = TRUE; |
241 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE; | 297 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE; |
242 | break; | 298 | break; |
243 | 299 | ||
@@ -246,7 +302,7 @@ extern "C" HRESULT MspEngineDetectPackage( | |||
246 | break; | 302 | break; |
247 | } | 303 | } |
248 | } | 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) |
250 | { | 306 | { |
251 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; | 307 | pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; |
252 | hr = S_OK; | 308 | hr = S_OK; |
@@ -260,9 +316,9 @@ extern "C" HRESULT MspEngineDetectPackage( | |||
260 | 316 | ||
261 | if (pPackage->fCanAffectRegistration) | 317 | if (pPackage->fCanAffectRegistration) |
262 | { | 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; |
264 | 320 | ||
265 | if (fInstalled) | 321 | if (pTargetProduct->fInstalled) |
266 | { | 322 | { |
267 | pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; | 323 | pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; |
268 | } | 324 | } |
@@ -290,6 +346,13 @@ extern "C" HRESULT MspEnginePlanInitializePackage( | |||
290 | { | 346 | { |
291 | BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; | 347 | BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; |
292 | 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 | |||
293 | pTargetProduct->defaultRequested = pTargetProduct->requested = pPackage->requested; | 356 | pTargetProduct->defaultRequested = pTargetProduct->requested = pPackage->requested; |
294 | 357 | ||
295 | hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &pTargetProduct->requested); | 358 | hr = UserExperienceOnPlanPatchTarget(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, &pTargetProduct->requested); |
@@ -637,32 +700,6 @@ LExit: | |||
637 | return hr; | 700 | return hr; |
638 | } | 701 | } |
639 | 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 | |||
666 | extern "C" void MspEngineUpdateInstallRegistrationState( | 703 | extern "C" void MspEngineUpdateInstallRegistrationState( |
667 | __in BURN_EXECUTE_ACTION* pAction, | 704 | __in BURN_EXECUTE_ACTION* pAction, |
668 | __in HRESULT hrExecute, | 705 | __in HRESULT hrExecute, |
@@ -926,43 +963,68 @@ LExit: | |||
926 | } | 963 | } |
927 | 964 | ||
928 | static HRESULT AddDetectedTargetProduct( | 965 | static HRESULT AddDetectedTargetProduct( |
929 | __in BURN_PACKAGES* pPackages, | ||
930 | __in BURN_PACKAGE* pPackage, | 966 | __in BURN_PACKAGE* pPackage, |
931 | __in DWORD dwOrder, | 967 | __in DWORD dwOrder, |
932 | __in_z LPCWSTR wzProductCode, | 968 | __in_z LPCWSTR wzProductCode, |
933 | __in MSIINSTALLCONTEXT context | 969 | __in MSIINSTALLCONTEXT context, |
970 | __out DWORD* pdwTargetProductIndex | ||
934 | ) | 971 | ) |
935 | { | 972 | { |
936 | HRESULT hr = S_OK; | 973 | HRESULT hr = S_OK; |
974 | BURN_MSPTARGETPRODUCT* pTargetProduct = NULL; | ||
975 | |||
976 | *pdwTargetProductIndex = BURN_PACKAGE_INVALID_PATCH_INDEX; | ||
937 | 977 | ||
938 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPackage->Msp.rgTargetProducts), pPackage->Msp.cTargetProductCodes + 1, sizeof(BURN_MSPTARGETPRODUCT), 5); | 978 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPackage->Msp.rgTargetProducts), pPackage->Msp.cTargetProductCodes + 1, sizeof(BURN_MSPTARGETPRODUCT), 5); |
939 | ExitOnFailure(hr, "Failed to ensure enough target product codes were allocated."); | 979 | ExitOnFailure(hr, "Failed to ensure enough target product codes were allocated."); |
940 | 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); | ||
942 | ExitOnFailure(hr, "Failed to copy target product code."); | 984 | ExitOnFailure(hr, "Failed to copy target product code."); |
943 | 985 | ||
944 | DeterminePatchChainedTarget(pPackages, pPackage, wzProductCode, | 986 | pTargetProduct->context = context; |
945 | &pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].pChainedTargetPackage, | 987 | pTargetProduct->dwOrder = dwOrder; |
946 | &pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].fSlipstream); | ||
947 | 988 | ||
948 | pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].context = context; | 989 | *pdwTargetProductIndex = pPackage->Msp.cTargetProductCodes; |
949 | pPackage->Msp.rgTargetProducts[pPackage->Msp.cTargetProductCodes].dwOrder = dwOrder; | ||
950 | ++pPackage->Msp.cTargetProductCodes; | 990 | ++pPackage->Msp.cTargetProductCodes; |
951 | 991 | ||
952 | LExit: | 992 | LExit: |
953 | return hr; | 993 | return hr; |
954 | } | 994 | } |
955 | 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( | ||
957 | __in BURN_PACKAGES* pPackages, | 1019 | __in BURN_PACKAGES* pPackages, |
958 | __in BURN_PACKAGE* pMspPackage, | 1020 | __in BURN_PACKAGE* pMspPackage, |
959 | __in LPCWSTR wzTargetProductCode, | 1021 | __in LPCWSTR wzTargetProductCode, |
960 | __out BURN_PACKAGE** ppChainedTargetPackage, | 1022 | __in DWORD dwMspTargetProductIndex |
961 | __out BOOL* pfSlipstreamed | ||
962 | ) | 1023 | ) |
963 | { | 1024 | { |
964 | BURN_PACKAGE* pTargetMsiPackage = NULL; | 1025 | HRESULT hr = S_OK; |
965 | BOOL fSlipstreamed = FALSE; | 1026 | DWORD dwChainedPatchIndex = 0; |
1027 | BURN_MSPTARGETPRODUCT* pTargetProduct = pMspPackage->Msp.rgTargetProducts + dwMspTargetProductIndex; | ||
966 | 1028 | ||
967 | for (DWORD iPackage = 0; iPackage < pPackages->cPackages; ++iPackage) | 1029 | for (DWORD iPackage = 0; iPackage < pPackages->cPackages; ++iPackage) |
968 | { | 1030 | { |
@@ -970,15 +1032,19 @@ static void DeterminePatchChainedTarget( | |||
970 | 1032 | ||
971 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzTargetProductCode, -1, pPackage->Msi.sczProductCode, -1)) | 1033 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzTargetProductCode, -1, pPackage->Msi.sczProductCode, -1)) |
972 | { | 1034 | { |
973 | pTargetMsiPackage = pPackage; | 1035 | pTargetProduct->pChainedTargetPackage = pPackage; |
1036 | |||
1037 | hr = AddMsiChainedPatch(pPackage, pMspPackage, dwMspTargetProductIndex, &dwChainedPatchIndex); | ||
1038 | ExitOnFailure(hr, "Failed to add chained patch."); | ||
974 | 1039 | ||
975 | for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j) | 1040 | for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j) |
976 | { | 1041 | { |
977 | BURN_PACKAGE* pSlipstreamMsp = pPackage->Msi.rgpSlipstreamMspPackages[j]; | 1042 | BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + j; |
978 | if (pSlipstreamMsp == pMspPackage) | 1043 | if (pSlipstreamMsp->pMspPackage == pMspPackage) |
979 | { | 1044 | { |
980 | AssertSz(!fSlipstreamed, "An MSP should only show up as a slipstreamed patch in an MSI once."); | 1045 | AssertSz(BURN_PACKAGE_INVALID_PATCH_INDEX == pSlipstreamMsp->dwMsiChainedPatchIndex, "An MSP should only show up as a slipstreamed patch in an MSI once."); |
981 | fSlipstreamed = TRUE; | 1046 | pTargetProduct->fSlipstream = TRUE; |
1047 | pSlipstreamMsp->dwMsiChainedPatchIndex = dwChainedPatchIndex; | ||
982 | break; | 1048 | break; |
983 | } | 1049 | } |
984 | } | 1050 | } |
@@ -987,10 +1053,8 @@ static void DeterminePatchChainedTarget( | |||
987 | } | 1053 | } |
988 | } | 1054 | } |
989 | 1055 | ||
990 | *ppChainedTargetPackage = pTargetMsiPackage; | 1056 | LExit: |
991 | *pfSlipstreamed = fSlipstreamed; | 1057 | return hr; |
992 | |||
993 | return; | ||
994 | } | 1058 | } |
995 | 1059 | ||
996 | static HRESULT PlanTargetProduct( | 1060 | static HRESULT PlanTargetProduct( |
diff --git a/src/engine/mspengine.h b/src/engine/mspengine.h index 28682169..1530954b 100644 --- a/src/engine/mspengine.h +++ b/src/engine/mspengine.h | |||
@@ -28,6 +28,17 @@ void MspEnginePackageUninitialize( | |||
28 | HRESULT MspEngineDetectInitialize( | 28 | HRESULT MspEngineDetectInitialize( |
29 | __in BURN_PACKAGES* pPackages | 29 | __in BURN_PACKAGES* pPackages |
30 | ); | 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 | ); | ||
31 | HRESULT MspEngineDetectPackage( | 42 | HRESULT MspEngineDetectPackage( |
32 | __in BURN_PACKAGE* pPackage, | 43 | __in BURN_PACKAGE* pPackage, |
33 | __in BURN_USER_EXPERIENCE* pUserExperience | 44 | __in BURN_USER_EXPERIENCE* pUserExperience |
@@ -59,11 +70,6 @@ HRESULT MspEngineExecutePackage( | |||
59 | __in LPVOID pvContext, | 70 | __in LPVOID pvContext, |
60 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | 71 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart |
61 | ); | 72 | ); |
62 | void MspEngineSlipstreamUpdateState( | ||
63 | __in BURN_PACKAGE* pMspPackage, | ||
64 | __in BOOTSTRAPPER_ACTION_STATE execute, | ||
65 | __in BOOTSTRAPPER_ACTION_STATE rollback | ||
66 | ); | ||
67 | void MspEngineUpdateInstallRegistrationState( | 73 | void MspEngineUpdateInstallRegistrationState( |
68 | __in BURN_EXECUTE_ACTION* pAction, | 74 | __in BURN_EXECUTE_ACTION* pAction, |
69 | __in HRESULT hrExecute, | 75 | __in HRESULT hrExecute, |
diff --git a/src/engine/package.cpp b/src/engine/package.cpp index bb61cdcd..115866f3 100644 --- a/src/engine/package.cpp +++ b/src/engine/package.cpp | |||
@@ -282,7 +282,9 @@ extern "C" HRESULT PackagesParseFromXml( | |||
282 | { | 282 | { |
283 | if (pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k] && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k], -1)) | 283 | if (pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k] && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k], -1)) |
284 | { | 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; | ||
286 | 288 | ||
287 | ReleaseNullStr(pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k]); // we don't need the slipstream package id any longer so free it. | 289 | ReleaseNullStr(pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k]); // we don't need the slipstream package id any longer so free it. |
288 | } | 290 | } |
@@ -295,6 +297,25 @@ extern "C" HRESULT PackagesParseFromXml( | |||
295 | 297 | ||
296 | AssertSz(pPackages->cPatchInfo == cMspPackages, "Count of packages patch info should be equal to the number of MSP packages."); | 298 | AssertSz(pPackages->cPatchInfo == cMspPackages, "Count of packages patch info should be equal to the number of MSP packages."); |
297 | 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 | |||
298 | hr = ParsePatchTargetCode(pPackages, pixnBundle); | 319 | hr = ParsePatchTargetCode(pPackages, pixnBundle); |
299 | ExitOnFailure(hr, "Failed to parse target product codes."); | 320 | ExitOnFailure(hr, "Failed to parse target product codes."); |
300 | 321 | ||
diff --git a/src/engine/package.h b/src/engine/package.h index 3a243c7d..283afa57 100644 --- a/src/engine/package.h +++ b/src/engine/package.h | |||
@@ -14,6 +14,8 @@ typedef _BURN_PACKAGE BURN_PACKAGE; | |||
14 | 14 | ||
15 | // constants | 15 | // constants |
16 | 16 | ||
17 | const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000; | ||
18 | |||
17 | enum BURN_EXE_EXIT_CODE_TYPE | 19 | enum BURN_EXE_EXIT_CODE_TYPE |
18 | { | 20 | { |
19 | BURN_EXE_EXIT_CODE_TYPE_NONE, | 21 | BURN_EXE_EXIT_CODE_TYPE_NONE, |
@@ -116,7 +118,9 @@ typedef struct _BURN_MSPTARGETPRODUCT | |||
116 | DWORD dwOrder; | 118 | DWORD dwOrder; |
117 | WCHAR wzTargetProductCode[39]; | 119 | WCHAR wzTargetProductCode[39]; |
118 | BURN_PACKAGE* pChainedTargetPackage; | 120 | BURN_PACKAGE* pChainedTargetPackage; |
121 | BOOL fInstalled; | ||
119 | BOOL fSlipstream; | 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. | ||
120 | 124 | ||
121 | BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect. | 125 | BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect. |
122 | BOOTSTRAPPER_REQUEST_STATE defaultRequested; // only valid during Plan. | 126 | BOOTSTRAPPER_REQUEST_STATE defaultRequested; // only valid during Plan. |
@@ -172,6 +176,18 @@ typedef struct _BURN_RELATED_MSI | |||
172 | DWORD cLanguages; | 176 | DWORD cLanguages; |
173 | } BURN_RELATED_MSI; | 177 | } BURN_RELATED_MSI; |
174 | 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 | |||
175 | typedef struct _BURN_PACKAGE_PAYLOAD | 191 | typedef struct _BURN_PACKAGE_PAYLOAD |
176 | { | 192 | { |
177 | BURN_PAYLOAD* pPayload; | 193 | BURN_PAYLOAD* pPayload; |
@@ -295,9 +311,12 @@ typedef struct _BURN_PACKAGE | |||
295 | BURN_RELATED_MSI* rgRelatedMsis; | 311 | BURN_RELATED_MSI* rgRelatedMsis; |
296 | DWORD cRelatedMsis; | 312 | DWORD cRelatedMsis; |
297 | 313 | ||
298 | _BURN_PACKAGE** rgpSlipstreamMspPackages; | 314 | BURN_SLIPSTREAM_MSP* rgSlipstreamMsps; |
299 | LPWSTR* rgsczSlipstreamMspPackageIds; | 315 | LPWSTR* rgsczSlipstreamMspPackageIds; |
300 | DWORD cSlipstreamMspPackages; | 316 | DWORD cSlipstreamMspPackages; |
317 | |||
318 | BURN_CHAINED_PATCH* rgChainedPatches; | ||
319 | DWORD cChainedPatches; | ||
301 | } Msi; | 320 | } Msi; |
302 | struct | 321 | struct |
303 | { | 322 | { |
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 95ea0b05..86a07dfb 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp | |||
@@ -2168,7 +2168,7 @@ static HRESULT AddCacheSlipstreamMsps( | |||
2168 | 2168 | ||
2169 | for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i) | 2169 | for (DWORD i = 0; i < pPackage->Msi.cSlipstreamMspPackages; ++i) |
2170 | { | 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."); | 2172 | AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); |
2173 | 2173 | ||
2174 | hr = AddCachePackageHelper(pPlan, pMspPackage, &hIgnored); | 2174 | hr = AddCachePackageHelper(pPlan, pMspPackage, &hIgnored); |
@@ -2791,7 +2791,7 @@ static HRESULT FinalizeSlipstreamPatchActions( | |||
2791 | { | 2791 | { |
2792 | for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j) | 2792 | for (DWORD j = 0; j < pPackage->Msi.cSlipstreamMspPackages; ++j) |
2793 | { | 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."); | 2795 | AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); |
2796 | 2796 | ||
2797 | pAction->msiPackage.rgSlipstreamPatches[j] = fExecute ? pMspPackage->execute : pMspPackage->rollback; | 2797 | pAction->msiPackage.rgSlipstreamPatches[j] = fExecute ? pMspPackage->execute : pMspPackage->rollback; |