Skip to content

Commit

Permalink
Support opening attached container directly from the bundle file
Browse files Browse the repository at this point in the history
  • Loading branch information
nirbar committed Feb 19, 2024
1 parent f017ac6 commit 7bf34a3
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum BUNDLE_EXTENSION_MESSAGE
{
BUNDLE_EXTENSION_MESSAGE_SEARCH,
BUNDLE_EXTENSION_MESSAGE_CONTAINER_OPEN,
BUNDLE_EXTENSION_MESSAGE_CONTAINER_OPEN_ATTACHED,
BUNDLE_EXTENSION_MESSAGE_CONTAINER_NEXT_STREAM,
BUNDLE_EXTENSION_MESSAGE_CONTAINER_STREAM_TO_FILE,
BUNDLE_EXTENSION_MESSAGE_CONTAINER_STREAM_TO_BUFFER,
Expand Down Expand Up @@ -44,6 +45,21 @@ typedef struct _BUNDLE_EXTENSION_CONTAINER_OPEN_RESULTS
LPVOID pContext;
} BUNDLE_EXTENSION_CONTAINER_OPEN_RESULTS;

typedef struct _BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_ARGS
{
DWORD cbSize;
LPCWSTR wzContainerId;
HANDLE hBundle;
DWORD64 qwContainerStartPos;
DWORD64 qwContainerSize;
} BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_ARGS;

typedef struct _BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_RESULTS
{
DWORD cbSize;
LPVOID pContext;
} BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_RESULTS;

typedef struct _BUNDLE_EXTENSION_CONTAINER_NEXT_STREAM_ARGS
{
DWORD cbSize;
Expand Down
11 changes: 11 additions & 0 deletions src/api/burn/bextutil/inc/BextBaseBundleExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ class CBextBaseBundleExtension : public IBundleExtension
return E_NOTIMPL;
}

virtual STDMETHODIMP ContainerOpenAttached(
__in LPCWSTR /*wzContainerId*/,
__in HANDLE /*hBundle*/,
__in DWORD64 /*qwContainerStartPos*/,
__in DWORD64 /*qwContainerSize*/,
__out LPVOID* /*ppContext*/
)
{
return E_NOTIMPL;
}

// Implementor should keep the stream name in the contex, to release it when done
virtual STDMETHODIMP ContainerNextStream(
__in LPVOID /*pContext*/,
Expand Down
12 changes: 12 additions & 0 deletions src/api/burn/bextutil/inc/BextBaseBundleExtensionProc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ static HRESULT BextBaseBEProcContainerOpen(
return pBE->ContainerOpen(pArgs->wzContainerId, pArgs->wzFilePath, &pResults->pContext);
}

static HRESULT BextBaseBEProcContainerOpenAttached(
__in IBundleExtension* pBE,
__in BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_ARGS* pArgs,
__inout BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_RESULTS* pResults
)
{
return pBE->ContainerOpenAttached(pArgs->wzContainerId, pArgs->hBundle, pArgs->qwContainerStartPos, pArgs->qwContainerSize, &pResults->pContext);
}

static HRESULT BextBaseBEProcContainerNextStream(
__in IBundleExtension* pBE,
__in BUNDLE_EXTENSION_CONTAINER_NEXT_STREAM_ARGS* pArgs,
Expand Down Expand Up @@ -98,6 +107,9 @@ static HRESULT WINAPI BextBaseBundleExtensionProc(
case BUNDLE_EXTENSION_MESSAGE_CONTAINER_OPEN:
hr = BextBaseBEProcContainerOpen(pBE, reinterpret_cast<BUNDLE_EXTENSION_CONTAINER_OPEN_ARGS*>(pvArgs), reinterpret_cast<BUNDLE_EXTENSION_CONTAINER_OPEN_RESULTS*>(pvResults));
break;
case BUNDLE_EXTENSION_MESSAGE_CONTAINER_OPEN_ATTACHED:
hr = BextBaseBEProcContainerOpenAttached(pBE, reinterpret_cast<BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_ARGS*>(pvArgs), reinterpret_cast<BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_RESULTS*>(pvResults));
break;
case BUNDLE_EXTENSION_MESSAGE_CONTAINER_NEXT_STREAM:
hr = BextBaseBEProcContainerNextStream(pBE, reinterpret_cast<BUNDLE_EXTENSION_CONTAINER_NEXT_STREAM_ARGS*>(pvArgs), reinterpret_cast<BUNDLE_EXTENSION_CONTAINER_NEXT_STREAM_RESULTS*>(pvResults));
break;
Expand Down
30 changes: 30 additions & 0 deletions src/api/burn/bextutil/inc/IBundleExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,62 @@ DECLARE_INTERFACE_IID_(IBundleExtension, IUnknown, "93123C9D-796B-4FCD-A507-6EDE
__in LPCWSTR wzVariable
) = 0;

/* ContainerOpen
Open a container file
*/
STDMETHOD(ContainerOpen)(
__in LPCWSTR wzContainerId,
__in LPCWSTR wzFilePath,
__out LPVOID *ppContext
) = 0;

/* ContainerOpenAttached
Open an attached container
If not implemented, return E_NOTIMPL. In that case, burn will extract the container to a temporary file and call ContainerOpen(). Note that, this may come with substantial performance penalty
*/
STDMETHOD(ContainerOpenAttached)(
__in LPCWSTR wzContainerId,
__in HANDLE hBundle,
__in DWORD64 qwContainerStartPos,
__in DWORD64 qwContainerSize,
__out LPVOID *ppContext
) = 0;

/* ContainerNextStream
Return the file name of the subsequent stream
*/
STDMETHOD(ContainerNextStream)(
__in LPVOID pContext,
__inout_z LPWSTR* psczStreamName
) = 0;

/* ContainerStreamToFile
Extract the current stream to a file. May be implemented a-synchronically. All extractions must be completed before the call to ContainerClose returns.
*/
STDMETHOD(ContainerStreamToFile)(
__in LPVOID pContext,
__in_z LPCWSTR wzFileName
) = 0;

/* ContainerStreamToBuffer
Extract the current stream to a buffer. May not be implemented a-synchronically
*/
STDMETHOD(ContainerStreamToBuffer)(
__in LPVOID pContext,
__out BYTE** ppbBuffer,
__out SIZE_T* pcbBuffer
) = 0;

/* ContainerSkipStream
Notifies that the current stream is not needed
*/
STDMETHOD(ContainerSkipStream)(
__in LPVOID pContext
) = 0;

/* ContainerClose
Complete all pending file extractions and release the container.
*/
STDMETHOD(ContainerClose)(
__in LPVOID pContext
) = 0;
Expand Down
30 changes: 30 additions & 0 deletions src/burn/engine/burnextension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,36 @@ EXTERN_C BEEAPI BurnExtensionContainerOpen(
return hr;
}

EXTERN_C BEEAPI BurnExtensionContainerOpenAttached(
__in BURN_EXTENSION* pExtension,
__in LPCWSTR wzContainerId,
__in HANDLE hBundle,
__in DWORD64 qwContainerStartPos,
__in DWORD64 qwContainerSize,
__in BURN_CONTAINER_CONTEXT* pContext
)
{
HRESULT hr = S_OK;
BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_ARGS args = { };
BUNDLE_EXTENSION_CONTAINER_OPEN_ATTACHED_RESULTS results = { };

args.cbSize = sizeof(args);
args.wzContainerId = wzContainerId;
args.hBundle = hBundle;
args.qwContainerStartPos = qwContainerStartPos;
args.qwContainerSize = qwContainerSize;

results.cbSize = sizeof(results);

hr = SendRequiredBextMessage(pExtension, BUNDLE_EXTENSION_MESSAGE_CONTAINER_OPEN_ATTACHED, &args, &results);
ExitOnFailure(hr, "BundleExtension '%ls' open attached container failed.", pExtension->sczId);

pContext->Bex.pExtensionContext = results.pContext;

LExit:
return hr;
}

BEEAPI BurnExtensionContainerNextStream(
__in BURN_EXTENSION* pExtension,
__in BURN_CONTAINER_CONTEXT* pContext,
Expand Down
8 changes: 8 additions & 0 deletions src/burn/engine/burnextension.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ BEEAPI BurnExtensionContainerOpen(
__in LPCWSTR wzFilePath,
__in BURN_CONTAINER_CONTEXT* pContext
);
BEEAPI BurnExtensionContainerOpenAttached(
__in BURN_EXTENSION* pExtension,
__in LPCWSTR wzContainerId,
__in HANDLE hBundle,
__in DWORD64 qwContainerStartPos,
__in DWORD64 qwContainerSize,
__in BURN_CONTAINER_CONTEXT* pContext
);
BEEAPI BurnExtensionContainerNextStream(
__in BURN_EXTENSION* pExtension,
__in BURN_CONTAINER_CONTEXT* pContext,
Expand Down
31 changes: 21 additions & 10 deletions src/burn/engine/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,20 +298,31 @@ extern "C" HRESULT ContainerOpen(
break;
case BURN_CONTAINER_TYPE_EXTENSION:

if (pContainer->fAttached)
pContext->Bex.pExtension = pContainer->pExtension;

if (pContainer->fActuallyAttached)
{
hr = FileCreateTemp(L"CNTNR", L"dat", &szTempFile, NULL);
ExitOnFailure(hr, "Failed to create temporary container file");
hr = BurnExtensionContainerOpenAttached(pContainer->pExtension, pContainer->sczId, pContext->hFile, pContext->qwOffset, pContext->qwSize, pContext);
if (FAILED(hr))
{
LogId(REPORT_STANDARD, MSG_EXT_ATTACHED_CONTAINER_FAILED, pContainer->sczId);

hr = FileCopyPartial(pContext->hFile, pContext->qwOffset, pContext->qwSize, szTempFile);
ExitOnFailure(hr, "Failed to write to temporary container file");
hr = FileCreateTemp(L"CNTNR", L"dat", &szTempFile, NULL);
ExitOnFailure(hr, "Failed to create temporary container file");

pContext->Bex.szTempContainerPath = szTempFile;
szTempFile = NULL;
}
hr = FileCopyPartial(pContext->hFile, pContext->qwOffset, pContext->qwSize, szTempFile);
ExitOnFailure(hr, "Failed to write to temporary container file");

pContext->Bex.pExtension = pContainer->pExtension;
hr = BurnExtensionContainerOpen(pContainer->pExtension, pContainer->sczId, pContext->Bex.szTempContainerPath ? pContext->Bex.szTempContainerPath : wzFilePath, pContext);
pContext->Bex.szTempContainerPath = szTempFile;
szTempFile = NULL;

hr = BurnExtensionContainerOpen(pContainer->pExtension, pContainer->sczId, pContext->Bex.szTempContainerPath, pContext);
}
}
else
{
hr = BurnExtensionContainerOpen(pContainer->pExtension, pContainer->sczId, wzFilePath, pContext);
}
break;
}
ExitOnFailure(hr, "Failed to open container.");
Expand Down
7 changes: 6 additions & 1 deletion src/burn/engine/engine.mc
Original file line number Diff line number Diff line change
Expand Up @@ -1282,11 +1282,16 @@ Language=English
Planned MSI transaction: '%1!ls!', planned: %2!hs!
.
MessageId=702
Severity=Success
SymbolicName=MSG_PLAN_CANCEL_MSI_TRANSACTION
Language=English
Canceling planned MSI transaction '%1!ls!' because it contains %2!lu! packages.
.
MessageId=703
Severity=Warning
SymbolicName=MSG_EXT_ATTACHED_CONTAINER_FAILED
Language=English
Container extension can not open attached container '%1!ls!'. Unloading the container and retrying.
.

0 comments on commit 7bf34a3

Please sign in to comment.