aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-04-16 10:52:26 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-04-19 23:12:55 -0500
commit22fb11c03329380fcffff253c7b2d4d1fccd23b4 (patch)
tree1a4fee8d61e2efafa24c90c8db1e8d2f5396e02d
parent8c77de737aaea1b4857c724c730446bca8da2dd0 (diff)
downloadwix-22fb11c03329380fcffff253c7b2d4d1fccd23b4.tar.gz
wix-22fb11c03329380fcffff253c7b2d4d1fccd23b4.tar.bz2
wix-22fb11c03329380fcffff253c7b2d4d1fccd23b4.zip
Add BURN_PAYLOAD_GROUP_ITEM to be able to move payloads during caching.
-rw-r--r--src/engine/apply.cpp61
-rw-r--r--src/engine/core.cpp4
-rw-r--r--src/engine/exeengine.cpp2
-rw-r--r--src/engine/msiengine.cpp4
-rw-r--r--src/engine/mspengine.cpp2
-rw-r--r--src/engine/msuengine.cpp2
-rw-r--r--src/engine/package.cpp14
-rw-r--r--src/engine/payload.cpp8
-rw-r--r--src/engine/payload.h13
-rw-r--r--src/engine/plan.cpp16
-rw-r--r--src/engine/pseudobundle.cpp18
-rw-r--r--src/engine/relatedbundle.cpp4
12 files changed, 98 insertions, 50 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 0eb8a710..bd294dfa 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -100,7 +100,7 @@ static HRESULT ApplyLayoutContainer(
100static HRESULT ApplyProcessPayload( 100static HRESULT ApplyProcessPayload(
101 __in BURN_CACHE_CONTEXT* pContext, 101 __in BURN_CACHE_CONTEXT* pContext,
102 __in_opt BURN_PACKAGE* pPackage, 102 __in_opt BURN_PACKAGE* pPackage,
103 __in BURN_PAYLOAD* pPayload 103 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem
104 ); 104 );
105static HRESULT ApplyCacheVerifyContainerOrPayload( 105static HRESULT ApplyCacheVerifyContainerOrPayload(
106 __in BURN_CACHE_CONTEXT* pContext, 106 __in BURN_CACHE_CONTEXT* pContext,
@@ -132,8 +132,7 @@ static HRESULT LayoutOrCacheContainerOrPayload(
132 __in BURN_CACHE_CONTEXT* pContext, 132 __in BURN_CACHE_CONTEXT* pContext,
133 __in_opt BURN_CONTAINER* pContainer, 133 __in_opt BURN_CONTAINER* pContainer,
134 __in_opt BURN_PACKAGE* pPackage, 134 __in_opt BURN_PACKAGE* pPackage,
135 __in_opt BURN_PAYLOAD* pPayload, 135 __in_opt BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
136 __in BOOL fMove,
137 __in DWORD cTryAgainAttempts, 136 __in DWORD cTryAgainAttempts,
138 __out BOOL* pfRetry 137 __out BOOL* pfRetry
139 ); 138 );
@@ -805,14 +804,14 @@ static HRESULT ApplyCachePackage(
805 804
806 for (;;) 805 for (;;)
807 { 806 {
808 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cPayloads, pPackage->payloads.qwTotalSize); 807 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cItems, pPackage->payloads.qwTotalSize);
809 LogExitOnFailure(hr, MSG_USER_CANCELED, "Cancel during cache: %ls: %ls", L"begin cache package", pPackage->sczId); 808 LogExitOnFailure(hr, MSG_USER_CANCELED, "Cancel during cache: %ls: %ls", L"begin cache package", pPackage->sczId);
810 809
811 for (DWORD i = 0; i < pPackage->payloads.cPayloads; ++i) 810 for (DWORD i = 0; i < pPackage->payloads.cItems; ++i)
812 { 811 {
813 BURN_PAYLOAD* pPayload = pPackage->payloads.rgpPayloads[i]; 812 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i;
814 813
815 hr = ApplyProcessPayload(pContext, pPackage, pPayload); 814 hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem);
816 if (FAILED(hr)) 815 if (FAILED(hr))
817 { 816 {
818 break; 817 break;
@@ -831,6 +830,16 @@ static HRESULT ApplyCachePackage(
831 if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY == cachePackageCompleteAction) 830 if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY == cachePackageCompleteAction)
832 { 831 {
833 // TODO: the progress needs to account for the payloads (potentially) being recached. 832 // TODO: the progress needs to account for the payloads (potentially) being recached.
833 for (DWORD i = 0; i < pPackage->payloads.cItems; ++i)
834 {
835 BURN_PAYLOAD_GROUP_ITEM* pItem = pPackage->payloads.rgItems + i;
836 if (pItem->fCached)
837 {
838 pItem->pPayload->cRemainingInstances += 1;
839 pItem->fCached = FALSE;
840 }
841 }
842
834 LogErrorId(hr, MSG_APPLY_RETRYING_PACKAGE, pPackage->sczId, NULL, NULL); 843 LogErrorId(hr, MSG_APPLY_RETRYING_PACKAGE, pPackage->sczId, NULL, NULL);
835 844
836 continue; 845 continue;
@@ -891,12 +900,12 @@ static HRESULT ApplyLayoutBundle(
891 hr = LayoutBundle(pContext, wzExecutableName, wzUnverifiedPath, qwBundleSize); 900 hr = LayoutBundle(pContext, wzExecutableName, wzUnverifiedPath, qwBundleSize);
892 ExitOnFailure(hr, "Failed to layout bundle."); 901 ExitOnFailure(hr, "Failed to layout bundle.");
893 902
894 for (DWORD i = 0; i < pPayloads->cPayloads; ++i) 903 for (DWORD i = 0; i < pPayloads->cItems; ++i)
895 { 904 {
896 BURN_PAYLOAD* pPayload = pPayloads->rgpPayloads[i]; 905 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i;
897 906
898 hr = ApplyProcessPayload(pContext, NULL, pPayload); 907 hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem);
899 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayload->sczKey); 908 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey);
900 } 909 }
901 910
902LExit: 911LExit:
@@ -927,7 +936,7 @@ static HRESULT ApplyLayoutContainer(
927 hr = ApplyAcquireContainerOrPayload(pContext, pContainer, NULL, NULL); 936 hr = ApplyAcquireContainerOrPayload(pContext, pContainer, NULL, NULL);
928 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath); 937 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
929 938
930 hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, TRUE, cTryAgainAttempts, &fRetry); 939 hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, cTryAgainAttempts, &fRetry);
931 if (SUCCEEDED(hr)) 940 if (SUCCEEDED(hr))
932 { 941 {
933 break; 942 break;
@@ -957,12 +966,13 @@ LExit:
957static HRESULT ApplyProcessPayload( 966static HRESULT ApplyProcessPayload(
958 __in BURN_CACHE_CONTEXT* pContext, 967 __in BURN_CACHE_CONTEXT* pContext,
959 __in_opt BURN_PACKAGE* pPackage, 968 __in_opt BURN_PACKAGE* pPackage,
960 __in BURN_PAYLOAD* pPayload 969 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem
961 ) 970 )
962{ 971{
963 HRESULT hr = S_OK; 972 HRESULT hr = S_OK;
964 DWORD cTryAgainAttempts = 0; 973 DWORD cTryAgainAttempts = 0;
965 BOOL fRetry = FALSE; 974 BOOL fRetry = FALSE;
975 BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload;
966 976
967 Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory); 977 Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory);
968 978
@@ -984,8 +994,7 @@ static HRESULT ApplyProcessPayload(
984 hr = ApplyAcquireContainerOrPayload(pContext, NULL, pPackage, pPayload); 994 hr = ApplyAcquireContainerOrPayload(pContext, NULL, pPackage, pPayload);
985 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath); 995 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath);
986 996
987 // TODO: set fMove to TRUE appropriately 997 hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayloadGroupItem, cTryAgainAttempts, &fRetry);
988 hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayload, FALSE, cTryAgainAttempts, &fRetry);
989 if (SUCCEEDED(hr)) 998 if (SUCCEEDED(hr))
990 { 999 {
991 break; 1000 break;
@@ -1426,18 +1435,30 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1426 __in BURN_CACHE_CONTEXT* pContext, 1435 __in BURN_CACHE_CONTEXT* pContext,
1427 __in_opt BURN_CONTAINER* pContainer, 1436 __in_opt BURN_CONTAINER* pContainer,
1428 __in_opt BURN_PACKAGE* pPackage, 1437 __in_opt BURN_PACKAGE* pPackage,
1429 __in_opt BURN_PAYLOAD* pPayload, 1438 __in_opt BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
1430 __in BOOL fMove,
1431 __in DWORD cTryAgainAttempts, 1439 __in DWORD cTryAgainAttempts,
1432 __out BOOL* pfRetry 1440 __out BOOL* pfRetry
1433 ) 1441 )
1434{ 1442{
1435 HRESULT hr = S_OK; 1443 HRESULT hr = S_OK;
1444 BURN_PAYLOAD* pPayload = pPayloadGroupItem ? pPayloadGroupItem->pPayload : NULL;
1436 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L""; 1445 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L"";
1437 LPCWSTR wzUnverifiedPath = pContainer ? pContainer->sczUnverifiedPath : pPayload->sczUnverifiedPath; 1446 LPCWSTR wzUnverifiedPath = pContainer ? pContainer->sczUnverifiedPath : pPayload->sczUnverifiedPath;
1438 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L""; 1447 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L"";
1439 BOOL fCanAffectRegistration = FALSE; 1448 BOOL fCanAffectRegistration = FALSE;
1440 BURN_CACHE_PROGRESS_CONTEXT progress = { }; 1449 BURN_CACHE_PROGRESS_CONTEXT progress = { };
1450 BOOL fMove = !pPayload || 1 == pPayload->cRemainingInstances;
1451
1452 if (pContainer)
1453 {
1454 Assert(!pPayloadGroupItem);
1455 }
1456 else
1457 {
1458 Assert(pPayload);
1459 AssertSz(0 < pPayload->cRemainingInstances, "Laying out payload more times than planned.");
1460 AssertSz(!pPayloadGroupItem->fCached, "Laying out payload group item that was already cached.");
1461 }
1441 1462
1442 if (!pContext->wzLayoutDirectory) 1463 if (!pContext->wzLayoutDirectory)
1443 { 1464 {
@@ -1501,6 +1522,12 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1501 } 1522 }
1502 } while (S_FALSE == hr); 1523 } while (S_FALSE == hr);
1503 1524
1525 if (SUCCEEDED(hr) && pPayloadGroupItem)
1526 {
1527 pPayload->cRemainingInstances -= 1;
1528 pPayloadGroupItem->fCached = TRUE;
1529 }
1530
1504LExit: 1531LExit:
1505 return hr; 1532 return hr;
1506} 1533}
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index 98aa943e..baba55f6 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -1679,9 +1679,9 @@ static HRESULT DetectPackagePayloadsCached(
1679 if (DirExists(sczCachePath, NULL)) 1679 if (DirExists(sczCachePath, NULL))
1680 { 1680 {
1681 // Check all payloads to see if any exist. 1681 // Check all payloads to see if any exist.
1682 for (DWORD i = 0; i < pPackage->payloads.cPayloads; ++i) 1682 for (DWORD i = 0; i < pPackage->payloads.cItems; ++i)
1683 { 1683 {
1684 BURN_PAYLOAD* pPayload = pPackage->payloads.rgpPayloads[i]; 1684 BURN_PAYLOAD* pPayload = pPackage->payloads.rgItems[i].pPayload;
1685 1685
1686 hr = PathConcat(sczCachePath, pPayload->sczFilePath, &sczPayloadCachePath); 1686 hr = PathConcat(sczCachePath, pPayload->sczFilePath, &sczPayloadCachePath);
1687 ExitOnFailure(hr, "Failed to concat payload cache path."); 1687 ExitOnFailure(hr, "Failed to concat payload cache path.");
diff --git a/src/engine/exeengine.cpp b/src/engine/exeengine.cpp
index 9b1b6973..0b53e266 100644
--- a/src/engine/exeengine.cpp
+++ b/src/engine/exeengine.cpp
@@ -373,7 +373,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
373 DWORD dwExitCode = 0; 373 DWORD dwExitCode = 0;
374 GENERIC_EXECUTE_MESSAGE message = { }; 374 GENERIC_EXECUTE_MESSAGE message = { };
375 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; 375 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage;
376 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0]; 376 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
377 377
378 // get cached executable path 378 // get cached executable path
379 hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory); 379 hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index b081b9ca..e3dc4671 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -1100,7 +1100,7 @@ extern "C" HRESULT MsiEngineExecutePackage(
1100 LPWSTR sczProperties = NULL; 1100 LPWSTR sczProperties = NULL;
1101 LPWSTR sczObfuscatedProperties = NULL; 1101 LPWSTR sczObfuscatedProperties = NULL;
1102 BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage; 1102 BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage;
1103 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0]; 1103 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
1104 1104
1105 // During rollback, if the package is already in the rollback state we expect don't 1105 // During rollback, if the package is already in the rollback state we expect don't
1106 // touch it again. 1106 // touch it again.
@@ -1981,7 +1981,7 @@ static HRESULT ConcatPatchProperty(
1981 { 1981 {
1982 BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + i; 1982 BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + i;
1983 BURN_PACKAGE* pMspPackage = pSlipstreamMsp->pMspPackage; 1983 BURN_PACKAGE* pMspPackage = pSlipstreamMsp->pMspPackage;
1984 BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgpPayloads[0]; 1984 BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgItems[0].pPayload;
1985 BOOTSTRAPPER_ACTION_STATE patchExecuteAction = fRollback ? pSlipstreamMsp->rollback : pSlipstreamMsp->execute; 1985 BOOTSTRAPPER_ACTION_STATE patchExecuteAction = fRollback ? pSlipstreamMsp->rollback : pSlipstreamMsp->execute;
1986 1986
1987 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < patchExecuteAction) 1987 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < patchExecuteAction)
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp
index 6addfa90..d5673700 100644
--- a/src/engine/mspengine.cpp
+++ b/src/engine/mspengine.cpp
@@ -581,7 +581,7 @@ extern "C" HRESULT MspEngineExecutePackage(
581 { 581 {
582 LPCWSTR wzAppend = NULL; 582 LPCWSTR wzAppend = NULL;
583 BURN_PACKAGE* pMspPackage = pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage; 583 BURN_PACKAGE* pMspPackage = pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage;
584 BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgpPayloads[0]; 584 BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgItems[0].pPayload;
585 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Invalid package type added to ordered patches."); 585 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Invalid package type added to ordered patches.");
586 586
587 if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->mspTarget.action) 587 if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->mspTarget.action)
diff --git a/src/engine/msuengine.cpp b/src/engine/msuengine.cpp
index 02ceb0c6..f807bf6b 100644
--- a/src/engine/msuengine.cpp
+++ b/src/engine/msuengine.cpp
@@ -265,7 +265,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
265 DWORD dwExitCode = 0; 265 DWORD dwExitCode = 0;
266 BOOL fUseSysNativePath = FALSE; 266 BOOL fUseSysNativePath = FALSE;
267 BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage; 267 BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage;
268 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0]; 268 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
269 269
270#if !defined(_WIN64) 270#if !defined(_WIN64)
271 hr = ProcWow64(::GetCurrentProcess(), &fUseSysNativePath); 271 hr = ProcWow64(::GetCurrentProcess(), &fUseSysNativePath);
diff --git a/src/engine/package.cpp b/src/engine/package.cpp
index ecf1488b..dd4e498a 100644
--- a/src/engine/package.cpp
+++ b/src/engine/package.cpp
@@ -349,7 +349,7 @@ extern "C" void PackageUninitialize(
349 MemFree(pPackage->rgDependencyProviders); 349 MemFree(pPackage->rgDependencyProviders);
350 } 350 }
351 351
352 ReleaseMem(pPackage->payloads.rgpPayloads); 352 ReleaseMem(pPackage->payloads.rgItems);
353 353
354 switch (pPackage->type) 354 switch (pPackage->type)
355 { 355 {
@@ -567,14 +567,16 @@ static HRESULT ParsePayloadRefsFromXml(
567 } 567 }
568 568
569 // allocate memory for payload pointers 569 // allocate memory for payload pointers
570 pPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*) * cNodes, TRUE); 570 pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM) * cNodes, TRUE);
571 ExitOnNull(pPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for package payloads."); 571 ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate memory for package payloads.");
572 572
573 pPackage->payloads.cPayloads = cNodes; 573 pPackage->payloads.cItems = cNodes;
574 574
575 // parse package elements 575 // parse package elements
576 for (DWORD i = 0; i < cNodes; ++i) 576 for (DWORD i = 0; i < cNodes; ++i)
577 { 577 {
578 BURN_PAYLOAD_GROUP_ITEM* pPackagePayload = pPackage->payloads.rgItems + i;
579
578 hr = XmlNextElement(pixnNodes, &pixnNode, NULL); 580 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
579 ExitOnFailure(hr, "Failed to get next node."); 581 ExitOnFailure(hr, "Failed to get next node.");
580 582
@@ -583,10 +585,10 @@ static HRESULT ParsePayloadRefsFromXml(
583 ExitOnFailure(hr, "Failed to get Id attribute."); 585 ExitOnFailure(hr, "Failed to get Id attribute.");
584 586
585 // find payload 587 // find payload
586 hr = PayloadFindById(pPayloads, sczId, &pPackage->payloads.rgpPayloads[i]); 588 hr = PayloadFindById(pPayloads, sczId, &pPackagePayload->pPayload);
587 ExitOnFailure(hr, "Failed to find payload."); 589 ExitOnFailure(hr, "Failed to find payload.");
588 590
589 pPackage->payloads.qwTotalSize += pPackage->payloads.rgpPayloads[i]->qwFileSize; 591 pPackage->payloads.qwTotalSize += pPackagePayload->pPayload->qwFileSize;
590 592
591 // prepare next iteration 593 // prepare next iteration
592 ReleaseNullObject(pixnNode); 594 ReleaseNullObject(pixnNode);
diff --git a/src/engine/payload.cpp b/src/engine/payload.cpp
index 2be39b23..28ab6f45 100644
--- a/src/engine/payload.cpp
+++ b/src/engine/payload.cpp
@@ -139,11 +139,11 @@ extern "C" HRESULT PayloadsParseFromXml(
139 139
140 if (pPayload->fLayoutOnly && pLayoutPayloads) 140 if (pPayload->fLayoutOnly && pLayoutPayloads)
141 { 141 {
142 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgpPayloads), pLayoutPayloads->cPayloads + 1, sizeof(BURN_PAYLOAD*), 5); 142 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5);
143 ExitOnNull(pPayloads->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for layout payloads."); 143 ExitOnFailure(hr, "Failed to allocate memory for layout payloads.");
144 144
145 pLayoutPayloads->rgpPayloads[pLayoutPayloads->cPayloads] = pPayload; 145 pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload;
146 ++pLayoutPayloads->cPayloads; 146 ++pLayoutPayloads->cItems;
147 147
148 pLayoutPayloads->qwTotalSize += pPayload->qwFileSize; 148 pLayoutPayloads->qwTotalSize += pPayload->qwFileSize;
149 } 149 }
diff --git a/src/engine/payload.h b/src/engine/payload.h
index ba555766..75132269 100644
--- a/src/engine/payload.h
+++ b/src/engine/payload.h
@@ -47,6 +47,7 @@ typedef struct _BURN_PAYLOAD
47 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy 47 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy
48 48
49 LPWSTR sczUnverifiedPath; 49 LPWSTR sczUnverifiedPath;
50 DWORD cRemainingInstances;
50} BURN_PAYLOAD; 51} BURN_PAYLOAD;
51 52
52typedef struct _BURN_PAYLOADS 53typedef struct _BURN_PAYLOADS
@@ -55,10 +56,18 @@ typedef struct _BURN_PAYLOADS
55 DWORD cPayloads; 56 DWORD cPayloads;
56} BURN_PAYLOADS; 57} BURN_PAYLOADS;
57 58
59typedef struct _BURN_PAYLOAD_GROUP_ITEM
60{
61 BURN_PAYLOAD* pPayload;
62
63 // mutable members
64 BOOL fCached;
65} BURN_PAYLOAD_GROUP_ITEM;
66
58typedef struct _BURN_PAYLOAD_GROUP 67typedef struct _BURN_PAYLOAD_GROUP
59{ 68{
60 BURN_PAYLOAD** rgpPayloads; 69 BURN_PAYLOAD_GROUP_ITEM* rgItems;
61 DWORD cPayloads; 70 DWORD cItems;
62 DWORD64 qwTotalSize; 71 DWORD64 qwTotalSize;
63} BURN_PAYLOAD_GROUP; 72} BURN_PAYLOAD_GROUP;
64 73
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index a37dcc89..f7434216 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -1839,15 +1839,22 @@ static void ResetPlannedPayloadsState(
1839 { 1839 {
1840 BURN_PAYLOAD* pPayload = pPayloads->rgPayloads + i; 1840 BURN_PAYLOAD* pPayload = pPayloads->rgPayloads + i;
1841 1841
1842 pPayload->cRemainingInstances = 0;
1842 pPayload->state = BURN_PAYLOAD_STATE_NONE; 1843 pPayload->state = BURN_PAYLOAD_STATE_NONE;
1843 ReleaseNullStr(pPayload->sczLocalFilePath); 1844 ReleaseNullStr(pPayload->sczLocalFilePath);
1844 } 1845 }
1845} 1846}
1846 1847
1847static void ResetPlannedPayloadGroupState( 1848static void ResetPlannedPayloadGroupState(
1848 __in BURN_PAYLOAD_GROUP* /*pPayloadGroup*/ 1849 __in BURN_PAYLOAD_GROUP* pPayloadGroup
1849 ) 1850 )
1850{ 1851{
1852 for (DWORD i = 0; i < pPayloadGroup->cItems; ++i)
1853 {
1854 BURN_PAYLOAD_GROUP_ITEM* pItem = pPayloadGroup->rgItems + i;
1855
1856 pItem->fCached = FALSE;
1857 }
1851} 1858}
1852 1859
1853static void ResetPlannedPackageState( 1860static void ResetPlannedPackageState(
@@ -2223,9 +2230,12 @@ static HRESULT ProcessPayloadGroup(
2223{ 2230{
2224 HRESULT hr = S_OK; 2231 HRESULT hr = S_OK;
2225 2232
2226 for (DWORD i = 0; i < pPayloadGroup->cPayloads; ++i) 2233 for (DWORD i = 0; i < pPayloadGroup->cItems; ++i)
2227 { 2234 {
2228 BURN_PAYLOAD* pPayload = pPayloadGroup->rgpPayloads[i]; 2235 BURN_PAYLOAD_GROUP_ITEM* pItem = pPayloadGroup->rgItems + i;
2236 BURN_PAYLOAD* pPayload = pItem->pPayload;
2237
2238 pPayload->cRemainingInstances += 1;
2229 2239
2230 if (pPayload->pContainer && !pPayload->pContainer->fPlanned) 2240 if (pPayload->pContainer && !pPayload->pContainer->fPlanned)
2231 { 2241 {
diff --git a/src/engine/pseudobundle.cpp b/src/engine/pseudobundle.cpp
index db25096b..180cc621 100644
--- a/src/engine/pseudobundle.cpp
+++ b/src/engine/pseudobundle.cpp
@@ -35,13 +35,13 @@ extern "C" HRESULT PseudoBundleInitialize(
35 } 35 }
36 36
37 // Initialize the single payload, and fill out all the necessary fields 37 // Initialize the single payload, and fill out all the necessary fields
38 pPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*), TRUE); 38 pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE);
39 ExitOnNull(pPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of related bundle struct"); 39 ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of related bundle struct");
40 pPackage->payloads.cPayloads = 1; 40 pPackage->payloads.cItems = 1;
41 41
42 pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE); 42 pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE);
43 ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct"); 43 ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct");
44 pPackage->payloads.rgpPayloads[0] = pPayload; 44 pPackage->payloads.rgItems[0].pPayload = pPayload;
45 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; 45 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
46 pPayload->qwFileSize = qwSize; 46 pPayload->qwFileSize = qwSize;
47 47
@@ -171,13 +171,13 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
171 LPWSTR sczArguments = NULL; 171 LPWSTR sczArguments = NULL;
172 172
173 // Initialize the payloads, and copy the necessary fields. 173 // Initialize the payloads, and copy the necessary fields.
174 pPassthroughPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*) * pPackage->payloads.cPayloads, TRUE); 174 pPassthroughPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM) * pPackage->payloads.cItems, TRUE);
175 ExitOnNull(pPassthroughPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle."); 175 ExitOnNull(pPassthroughPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle.");
176 pPassthroughPackage->payloads.cPayloads = pPackage->payloads.cPayloads; 176 pPassthroughPackage->payloads.cItems = pPackage->payloads.cItems;
177 177
178 for (DWORD iPayload = 0; iPayload < pPackage->payloads.cPayloads; ++iPayload) 178 for (DWORD iPayload = 0; iPayload < pPackage->payloads.cItems; ++iPayload)
179 { 179 {
180 pPassthroughPackage->payloads.rgpPayloads[iPayload] = pPackage->payloads.rgpPayloads[iPayload]; 180 pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload;
181 } 181 }
182 182
183 pPassthroughPackage->Exe.fPseudoBundle = TRUE; 183 pPassthroughPackage->Exe.fPseudoBundle = TRUE;
diff --git a/src/engine/relatedbundle.cpp b/src/engine/relatedbundle.cpp
index a79be020..d3c856a6 100644
--- a/src/engine/relatedbundle.cpp
+++ b/src/engine/relatedbundle.cpp
@@ -82,9 +82,9 @@ extern "C" void RelatedBundlesUninitialize(
82 { 82 {
83 BURN_PACKAGE* pPackage = &pRelatedBundles->rgRelatedBundles[i].package; 83 BURN_PACKAGE* pPackage = &pRelatedBundles->rgRelatedBundles[i].package;
84 84
85 for (DWORD j = 0; j < pPackage->payloads.cPayloads; ++j) 85 for (DWORD j = 0; j < pPackage->payloads.cItems; ++j)
86 { 86 {
87 PayloadUninitialize(pPackage->payloads.rgpPayloads[j]); 87 PayloadUninitialize(pPackage->payloads.rgItems[j].pPayload);
88 } 88 }
89 89
90 PackageUninitialize(pPackage); 90 PackageUninitialize(pPackage);