From 22fb11c03329380fcffff253c7b2d4d1fccd23b4 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 16 Apr 2021 10:52:26 -0500 Subject: Add BURN_PAYLOAD_GROUP_ITEM to be able to move payloads during caching. --- src/engine/apply.cpp | 61 ++++++++++++++++++++++++++++++++------------ src/engine/core.cpp | 4 +-- src/engine/exeengine.cpp | 2 +- src/engine/msiengine.cpp | 4 +-- src/engine/mspengine.cpp | 2 +- src/engine/msuengine.cpp | 2 +- src/engine/package.cpp | 14 +++++----- src/engine/payload.cpp | 8 +++--- src/engine/payload.h | 13 ++++++++-- src/engine/plan.cpp | 16 +++++++++--- src/engine/pseudobundle.cpp | 18 ++++++------- src/engine/relatedbundle.cpp | 4 +-- 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( static HRESULT ApplyProcessPayload( __in BURN_CACHE_CONTEXT* pContext, __in_opt BURN_PACKAGE* pPackage, - __in BURN_PAYLOAD* pPayload + __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem ); static HRESULT ApplyCacheVerifyContainerOrPayload( __in BURN_CACHE_CONTEXT* pContext, @@ -132,8 +132,7 @@ static HRESULT LayoutOrCacheContainerOrPayload( __in BURN_CACHE_CONTEXT* pContext, __in_opt BURN_CONTAINER* pContainer, __in_opt BURN_PACKAGE* pPackage, - __in_opt BURN_PAYLOAD* pPayload, - __in BOOL fMove, + __in_opt BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem, __in DWORD cTryAgainAttempts, __out BOOL* pfRetry ); @@ -805,14 +804,14 @@ static HRESULT ApplyCachePackage( for (;;) { - hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cPayloads, pPackage->payloads.qwTotalSize); + hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cItems, pPackage->payloads.qwTotalSize); LogExitOnFailure(hr, MSG_USER_CANCELED, "Cancel during cache: %ls: %ls", L"begin cache package", pPackage->sczId); - for (DWORD i = 0; i < pPackage->payloads.cPayloads; ++i) + for (DWORD i = 0; i < pPackage->payloads.cItems; ++i) { - BURN_PAYLOAD* pPayload = pPackage->payloads.rgpPayloads[i]; + BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i; - hr = ApplyProcessPayload(pContext, pPackage, pPayload); + hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem); if (FAILED(hr)) { break; @@ -831,6 +830,16 @@ static HRESULT ApplyCachePackage( if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY == cachePackageCompleteAction) { // TODO: the progress needs to account for the payloads (potentially) being recached. + for (DWORD i = 0; i < pPackage->payloads.cItems; ++i) + { + BURN_PAYLOAD_GROUP_ITEM* pItem = pPackage->payloads.rgItems + i; + if (pItem->fCached) + { + pItem->pPayload->cRemainingInstances += 1; + pItem->fCached = FALSE; + } + } + LogErrorId(hr, MSG_APPLY_RETRYING_PACKAGE, pPackage->sczId, NULL, NULL); continue; @@ -891,12 +900,12 @@ static HRESULT ApplyLayoutBundle( hr = LayoutBundle(pContext, wzExecutableName, wzUnverifiedPath, qwBundleSize); ExitOnFailure(hr, "Failed to layout bundle."); - for (DWORD i = 0; i < pPayloads->cPayloads; ++i) + for (DWORD i = 0; i < pPayloads->cItems; ++i) { - BURN_PAYLOAD* pPayload = pPayloads->rgpPayloads[i]; + BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i; - hr = ApplyProcessPayload(pContext, NULL, pPayload); - ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayload->sczKey); + hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem); + ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey); } LExit: @@ -927,7 +936,7 @@ static HRESULT ApplyLayoutContainer( hr = ApplyAcquireContainerOrPayload(pContext, pContainer, NULL, NULL); LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath); - hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, TRUE, cTryAgainAttempts, &fRetry); + hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, cTryAgainAttempts, &fRetry); if (SUCCEEDED(hr)) { break; @@ -957,12 +966,13 @@ LExit: static HRESULT ApplyProcessPayload( __in BURN_CACHE_CONTEXT* pContext, __in_opt BURN_PACKAGE* pPackage, - __in BURN_PAYLOAD* pPayload + __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem ) { HRESULT hr = S_OK; DWORD cTryAgainAttempts = 0; BOOL fRetry = FALSE; + BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload; Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory); @@ -984,8 +994,7 @@ static HRESULT ApplyProcessPayload( hr = ApplyAcquireContainerOrPayload(pContext, NULL, pPackage, pPayload); LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath); - // TODO: set fMove to TRUE appropriately - hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayload, FALSE, cTryAgainAttempts, &fRetry); + hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayloadGroupItem, cTryAgainAttempts, &fRetry); if (SUCCEEDED(hr)) { break; @@ -1426,18 +1435,30 @@ static HRESULT LayoutOrCacheContainerOrPayload( __in BURN_CACHE_CONTEXT* pContext, __in_opt BURN_CONTAINER* pContainer, __in_opt BURN_PACKAGE* pPackage, - __in_opt BURN_PAYLOAD* pPayload, - __in BOOL fMove, + __in_opt BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem, __in DWORD cTryAgainAttempts, __out BOOL* pfRetry ) { HRESULT hr = S_OK; + BURN_PAYLOAD* pPayload = pPayloadGroupItem ? pPayloadGroupItem->pPayload : NULL; LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L""; LPCWSTR wzUnverifiedPath = pContainer ? pContainer->sczUnverifiedPath : pPayload->sczUnverifiedPath; LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L""; BOOL fCanAffectRegistration = FALSE; BURN_CACHE_PROGRESS_CONTEXT progress = { }; + BOOL fMove = !pPayload || 1 == pPayload->cRemainingInstances; + + if (pContainer) + { + Assert(!pPayloadGroupItem); + } + else + { + Assert(pPayload); + AssertSz(0 < pPayload->cRemainingInstances, "Laying out payload more times than planned."); + AssertSz(!pPayloadGroupItem->fCached, "Laying out payload group item that was already cached."); + } if (!pContext->wzLayoutDirectory) { @@ -1501,6 +1522,12 @@ static HRESULT LayoutOrCacheContainerOrPayload( } } while (S_FALSE == hr); + if (SUCCEEDED(hr) && pPayloadGroupItem) + { + pPayload->cRemainingInstances -= 1; + pPayloadGroupItem->fCached = TRUE; + } + LExit: return hr; } 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( if (DirExists(sczCachePath, NULL)) { // Check all payloads to see if any exist. - for (DWORD i = 0; i < pPackage->payloads.cPayloads; ++i) + for (DWORD i = 0; i < pPackage->payloads.cItems; ++i) { - BURN_PAYLOAD* pPayload = pPackage->payloads.rgpPayloads[i]; + BURN_PAYLOAD* pPayload = pPackage->payloads.rgItems[i].pPayload; hr = PathConcat(sczCachePath, pPayload->sczFilePath, &sczPayloadCachePath); 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( DWORD dwExitCode = 0; GENERIC_EXECUTE_MESSAGE message = { }; BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; - BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0]; + BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; // get cached executable path 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( LPWSTR sczProperties = NULL; LPWSTR sczObfuscatedProperties = NULL; BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage; - BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0]; + BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; // During rollback, if the package is already in the rollback state we expect don't // touch it again. @@ -1981,7 +1981,7 @@ static HRESULT ConcatPatchProperty( { BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + i; BURN_PACKAGE* pMspPackage = pSlipstreamMsp->pMspPackage; - BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgpPayloads[0]; + BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgItems[0].pPayload; BOOTSTRAPPER_ACTION_STATE patchExecuteAction = fRollback ? pSlipstreamMsp->rollback : pSlipstreamMsp->execute; 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( { LPCWSTR wzAppend = NULL; BURN_PACKAGE* pMspPackage = pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage; - BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgpPayloads[0]; + BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgItems[0].pPayload; AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Invalid package type added to ordered patches."); 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( DWORD dwExitCode = 0; BOOL fUseSysNativePath = FALSE; BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage; - BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0]; + BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; #if !defined(_WIN64) 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( MemFree(pPackage->rgDependencyProviders); } - ReleaseMem(pPackage->payloads.rgpPayloads); + ReleaseMem(pPackage->payloads.rgItems); switch (pPackage->type) { @@ -567,14 +567,16 @@ static HRESULT ParsePayloadRefsFromXml( } // allocate memory for payload pointers - pPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*) * cNodes, TRUE); - ExitOnNull(pPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for package payloads."); + pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM) * cNodes, TRUE); + ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate memory for package payloads."); - pPackage->payloads.cPayloads = cNodes; + pPackage->payloads.cItems = cNodes; // parse package elements for (DWORD i = 0; i < cNodes; ++i) { + BURN_PAYLOAD_GROUP_ITEM* pPackagePayload = pPackage->payloads.rgItems + i; + hr = XmlNextElement(pixnNodes, &pixnNode, NULL); ExitOnFailure(hr, "Failed to get next node."); @@ -583,10 +585,10 @@ static HRESULT ParsePayloadRefsFromXml( ExitOnFailure(hr, "Failed to get Id attribute."); // find payload - hr = PayloadFindById(pPayloads, sczId, &pPackage->payloads.rgpPayloads[i]); + hr = PayloadFindById(pPayloads, sczId, &pPackagePayload->pPayload); ExitOnFailure(hr, "Failed to find payload."); - pPackage->payloads.qwTotalSize += pPackage->payloads.rgpPayloads[i]->qwFileSize; + pPackage->payloads.qwTotalSize += pPackagePayload->pPayload->qwFileSize; // prepare next iteration 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( if (pPayload->fLayoutOnly && pLayoutPayloads) { - hr = MemEnsureArraySize(reinterpret_cast(&pLayoutPayloads->rgpPayloads), pLayoutPayloads->cPayloads + 1, sizeof(BURN_PAYLOAD*), 5); - ExitOnNull(pPayloads->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for layout payloads."); + hr = MemEnsureArraySize(reinterpret_cast(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5); + ExitOnFailure(hr, "Failed to allocate memory for layout payloads."); - pLayoutPayloads->rgpPayloads[pLayoutPayloads->cPayloads] = pPayload; - ++pLayoutPayloads->cPayloads; + pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload; + ++pLayoutPayloads->cItems; pLayoutPayloads->qwTotalSize += pPayload->qwFileSize; } 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 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy LPWSTR sczUnverifiedPath; + DWORD cRemainingInstances; } BURN_PAYLOAD; typedef struct _BURN_PAYLOADS @@ -55,10 +56,18 @@ typedef struct _BURN_PAYLOADS DWORD cPayloads; } BURN_PAYLOADS; +typedef struct _BURN_PAYLOAD_GROUP_ITEM +{ + BURN_PAYLOAD* pPayload; + + // mutable members + BOOL fCached; +} BURN_PAYLOAD_GROUP_ITEM; + typedef struct _BURN_PAYLOAD_GROUP { - BURN_PAYLOAD** rgpPayloads; - DWORD cPayloads; + BURN_PAYLOAD_GROUP_ITEM* rgItems; + DWORD cItems; DWORD64 qwTotalSize; } BURN_PAYLOAD_GROUP; 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( { BURN_PAYLOAD* pPayload = pPayloads->rgPayloads + i; + pPayload->cRemainingInstances = 0; pPayload->state = BURN_PAYLOAD_STATE_NONE; ReleaseNullStr(pPayload->sczLocalFilePath); } } static void ResetPlannedPayloadGroupState( - __in BURN_PAYLOAD_GROUP* /*pPayloadGroup*/ + __in BURN_PAYLOAD_GROUP* pPayloadGroup ) { + for (DWORD i = 0; i < pPayloadGroup->cItems; ++i) + { + BURN_PAYLOAD_GROUP_ITEM* pItem = pPayloadGroup->rgItems + i; + + pItem->fCached = FALSE; + } } static void ResetPlannedPackageState( @@ -2223,9 +2230,12 @@ static HRESULT ProcessPayloadGroup( { HRESULT hr = S_OK; - for (DWORD i = 0; i < pPayloadGroup->cPayloads; ++i) + for (DWORD i = 0; i < pPayloadGroup->cItems; ++i) { - BURN_PAYLOAD* pPayload = pPayloadGroup->rgpPayloads[i]; + BURN_PAYLOAD_GROUP_ITEM* pItem = pPayloadGroup->rgItems + i; + BURN_PAYLOAD* pPayload = pItem->pPayload; + + pPayload->cRemainingInstances += 1; if (pPayload->pContainer && !pPayload->pContainer->fPlanned) { 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( } // Initialize the single payload, and fill out all the necessary fields - pPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*), TRUE); - ExitOnNull(pPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of related bundle struct"); - pPackage->payloads.cPayloads = 1; + pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE); + ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of related bundle struct"); + pPackage->payloads.cItems = 1; pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE); ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct"); - pPackage->payloads.rgpPayloads[0] = pPayload; + pPackage->payloads.rgItems[0].pPayload = pPayload; pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; pPayload->qwFileSize = qwSize; @@ -171,13 +171,13 @@ extern "C" HRESULT PseudoBundleInitializePassthrough( LPWSTR sczArguments = NULL; // Initialize the payloads, and copy the necessary fields. - pPassthroughPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*) * pPackage->payloads.cPayloads, TRUE); - ExitOnNull(pPassthroughPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle."); - pPassthroughPackage->payloads.cPayloads = pPackage->payloads.cPayloads; + pPassthroughPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM) * pPackage->payloads.cItems, TRUE); + ExitOnNull(pPassthroughPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle."); + pPassthroughPackage->payloads.cItems = pPackage->payloads.cItems; - for (DWORD iPayload = 0; iPayload < pPackage->payloads.cPayloads; ++iPayload) + for (DWORD iPayload = 0; iPayload < pPackage->payloads.cItems; ++iPayload) { - pPassthroughPackage->payloads.rgpPayloads[iPayload] = pPackage->payloads.rgpPayloads[iPayload]; + pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload; } 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( { BURN_PACKAGE* pPackage = &pRelatedBundles->rgRelatedBundles[i].package; - for (DWORD j = 0; j < pPackage->payloads.cPayloads; ++j) + for (DWORD j = 0; j < pPackage->payloads.cItems; ++j) { - PayloadUninitialize(pPackage->payloads.rgpPayloads[j]); + PayloadUninitialize(pPackage->payloads.rgItems[j].pPayload); } PackageUninitialize(pPackage); -- cgit v1.2.3-55-g6feb