From 846f5a033d346c1bac51c56d4936cd3118ebea7a Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sun, 15 Nov 2020 20:23:44 -0600 Subject: Clean up the elevation code for MSI transactions. --- src/engine/apply.cpp | 232 +++++++++++++++++------------------------------ src/engine/elevation.cpp | 178 ++++++++++++++++-------------------- src/engine/elevation.h | 17 ++-- src/engine/msiengine.cpp | 42 +++++++++ src/engine/msiengine.h | 5 + 5 files changed, 213 insertions(+), 261 deletions(-) diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp index 9a0f64e1..909fb159 100644 --- a/src/engine/apply.cpp +++ b/src/engine/apply.cpp @@ -198,6 +198,19 @@ static HRESULT ExecuteCompatiblePackageAction( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pAction ); +static HRESULT ExecuteMsiBeginTransaction( + __in BURN_ENGINE_STATE* pEngineState, + __in LPCWSTR wzName, + __in BURN_EXECUTE_CONTEXT* pContext + ); +static HRESULT ExecuteMsiCommitTransaction( + __in BURN_ENGINE_STATE* pEngineState, + __in BURN_EXECUTE_CONTEXT* pContext + ); +static HRESULT ExecuteMsiRollbackTransaction( + __in BURN_ENGINE_STATE* pEngineState, + __in BURN_EXECUTE_CONTEXT* pContext + ); static HRESULT CleanPackage( __in HANDLE hElevatedPipe, __in BURN_PACKAGE* pPackage @@ -228,30 +241,6 @@ static HRESULT ExecutePackageComplete( __out BOOL* pfSuspend ); -static HRESULT DoMsiBeginTransaction( - __in BURN_EXECUTE_CONTEXT *context - , __in BURN_ENGINE_STATE* pEngineState -); -static HRESULT DoMsiCommitTransaction( - __in BURN_EXECUTE_CONTEXT *context - , __in BURN_ENGINE_STATE* pEngineState -); -static HRESULT DoMsiRollbackTransaction( - __in BURN_EXECUTE_CONTEXT *context - , __in BURN_ENGINE_STATE* pEngineState -); -static HRESULT ExecuteMsiBeginTransaction( - __in BURN_EXECUTE_CONTEXT* pContext - , __in BURN_ENGINE_STATE* pEngineState -); -static HRESULT ExecuteMsiCommitTransaction( - __in BURN_EXECUTE_CONTEXT* pContext - , __in BURN_ENGINE_STATE* pEngineState -); -static HRESULT ExecuteMsiRollbackTransaction( - __in BURN_EXECUTE_CONTEXT* pContext - , __in BURN_ENGINE_STATE* pEngineState -); // function definitions @@ -773,7 +762,7 @@ extern "C" HRESULT ApplyExecute( if (fInTransaction) { LogString(REPORT_STANDARD, "Committing MSI transaction\n"); - hr = DoMsiCommitTransaction(&context, pEngineState); + hr = ExecuteMsiCommitTransaction(pEngineState, &context); ExitOnFailure(hr, "Failed committing an MSI transaction"); fInTransaction = FALSE; } @@ -789,7 +778,7 @@ extern "C" HRESULT ApplyExecute( else { LogString(REPORT_STANDARD, "Starting a new MSI transaction\n"); - hr = DoMsiBeginTransaction(&context, pEngineState); + hr = ExecuteMsiBeginTransaction(pEngineState, pExecuteAction->rollbackBoundary.pRollbackBoundary->sczId, &context); ExitOnFailure(hr, "Failed beginning an MSI transaction"); fInTransaction = TRUE; } @@ -855,7 +844,7 @@ extern "C" HRESULT ApplyExecute( if (fInTransaction) { LogString(REPORT_STANDARD, "Committing an MSI transaction\n"); - hr = DoMsiCommitTransaction(&context, pEngineState); + hr = ExecuteMsiCommitTransaction(pEngineState, &context); ExitOnFailure(hr, "Failed committing an MSI transaction"); fInTransaction = FALSE; } @@ -1658,127 +1647,6 @@ static void DoRollbackCache( } } -/* MSI Transactions: - * All MSI/MSP/MSU packages wrapped in MsiBeginTranasaction-MsiEndTransaction pair are installed or uninstalled together. -*/ -static HRESULT ExecuteMsiBeginTransaction( - __in BURN_EXECUTE_CONTEXT* pContext - , __in BURN_ENGINE_STATE* pEngineState -) -{ - HRESULT hr = S_OK; - UINT uResult = ERROR_SUCCESS; - - // Per user/machine context - if (pEngineState->plan.fPerMachine) - { - hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pContext); - ExitOnFailure(hr, "Failed to begin an MSI transaction."); - } - else - { - MSIHANDLE hMsiTrns = NULL; - HANDLE hMsiTrnsEvent = NULL; - uResult = MsiBeginTransaction(L"WiX", 0, &hMsiTrns, &hMsiTrnsEvent); - ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction"); - } - -LExit: - return hr; -} - -static HRESULT ExecuteMsiCommitTransaction( - __in BURN_EXECUTE_CONTEXT* pContext - , __in BURN_ENGINE_STATE* pEngineState -) -{ - HRESULT hr = S_OK; - UINT uResult = ERROR_SUCCESS; - - // Per user/machine context - if (pEngineState->plan.fPerMachine) - { - hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pContext); - ExitOnFailure(hr, "Failed to commit an MSI transaction."); - } - else - { - uResult = MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT); - ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction"); - } - -LExit: - return hr; -} - -static HRESULT ExecuteMsiRollbackTransaction( - __in BURN_EXECUTE_CONTEXT* pContext - , __in BURN_ENGINE_STATE* pEngineState -) -{ - HRESULT hr = S_OK; - UINT uResult = ERROR_SUCCESS; - - // Per user/machine context - if (pEngineState->plan.fPerMachine) - { - hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pContext); - ExitOnFailure(hr, "Failed to rollback an MSI transaction."); - } - else - { - uResult = MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK); - ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction"); - } - -LExit: - return hr; -} - -// Currently, supporting only elevated transactions. -static HRESULT DoMsiBeginTransaction( - __in BURN_EXECUTE_CONTEXT *pContext - , __in BURN_ENGINE_STATE* pEngineState -) -{ - HRESULT hr = S_OK; - - hr = ExecuteMsiBeginTransaction(pContext, pEngineState); - ExitOnFailure(hr, "Failed to execute EXE package."); - -LExit: - return hr; -} - -static HRESULT DoMsiCommitTransaction( - __in BURN_EXECUTE_CONTEXT *pContext - , __in BURN_ENGINE_STATE* pEngineState -) -{ - HRESULT hr = S_OK; - - hr = ExecuteMsiCommitTransaction(pContext, pEngineState); - ExitOnFailure(hr, "Failed to execute EXE package."); - -LExit: - return hr; -} - -static HRESULT DoMsiRollbackTransaction( - __in BURN_EXECUTE_CONTEXT *pContext - , __in BURN_ENGINE_STATE* pEngineState -) -{ - HRESULT hr = S_OK; - - hr = ExecuteMsiRollbackTransaction(pContext, pEngineState); - ExitOnFailure(hr, "Failed to execute EXE package."); - -LExit: - return hr; -} - - static HRESULT DoExecuteAction( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, @@ -1904,7 +1772,7 @@ static HRESULT DoRollbackActions( __in BOOL fInTransaction, __out BOOL* pfKeepRegistration, __out BOOTSTRAPPER_APPLY_RESTART* pRestart -) + ) { HRESULT hr = S_OK; DWORD iCheckpoint = 0; @@ -1916,7 +1784,7 @@ static HRESULT DoRollbackActions( // Rollback MSI transaction if (fInTransaction) { - hr = DoMsiRollbackTransaction(pContext, pEngineState); + hr = ExecuteMsiRollbackTransaction(pEngineState, pContext); ExitOnFailure(hr, "Failed rolling back transaction"); } @@ -2364,6 +2232,70 @@ LExit: return hr; } +static HRESULT ExecuteMsiBeginTransaction( + __in BURN_ENGINE_STATE* pEngineState, + __in LPCWSTR wzName, + __in BURN_EXECUTE_CONTEXT* /*pContext*/ + ) +{ + HRESULT hr = S_OK; + + if (pEngineState->plan.fPerMachine) + { + hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, wzName); + ExitOnFailure(hr, "Failed to begin an elevated MSI transaction."); + } + else + { + hr = MsiEngineBeginTransaction(wzName); + } + +LExit: + return hr; +} + +static HRESULT ExecuteMsiCommitTransaction( + __in BURN_ENGINE_STATE* pEngineState, + __in BURN_EXECUTE_CONTEXT* /*pContext*/ + ) +{ + HRESULT hr = S_OK; + + if (pEngineState->plan.fPerMachine) + { + hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe); + ExitOnFailure(hr, "Failed to commit an elevated MSI transaction."); + } + else + { + hr = MsiEngineCommitTransaction(); + } + +LExit: + return hr; +} + +static HRESULT ExecuteMsiRollbackTransaction( + __in BURN_ENGINE_STATE* pEngineState, + __in BURN_EXECUTE_CONTEXT* /*pContext*/ + ) +{ + HRESULT hr = S_OK; + + if (pEngineState->plan.fPerMachine) + { + hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe); + ExitOnFailure(hr, "Failed to rollback an elevated MSI transaction."); + } + else + { + hr = MsiEngineRollbackTransaction(); + } + +LExit: + return hr; +} + static HRESULT CleanPackage( __in HANDLE hElevatedPipe, __in BURN_PACKAGE* pPackage diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp index 9ce04630..81a48316 100644 --- a/src/engine/elevation.cpp +++ b/src/engine/elevation.cpp @@ -28,17 +28,15 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_EMBEDDED_CHILD, BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE, + BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, + BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, + BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, - - BURN_ELEVATION_TRANSACTION_BEGIN, - BURN_ELEVATION_TRANSACTION_COMMIT, - BURN_ELEVATION_TRANSACTION_ROLLBACK - } BURN_ELEVATION_MESSAGE_TYPE; @@ -74,24 +72,11 @@ typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT BURN_VARIABLES* pVariables; BURN_REGISTRATION* pRegistration; BURN_USER_EXPERIENCE* pUserExperience; - - MSIHANDLE hMsiTrns; - HANDLE hMsiTrnsEvent; } BURN_ELEVATION_CHILD_MESSAGE_CONTEXT; // internal function declarations -static HRESULT OnMsiBeginTransaction( - __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext -); -static HRESULT OnMsiCommitTransaction( - __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext -); -static HRESULT OnMsiRollbackTransaction( - __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext -); - static DWORD WINAPI ElevatedChildCacheThreadProc( __in LPVOID lpThreadParameter ); @@ -248,6 +233,13 @@ static HRESULT OnLaunchApprovedExe( __in BYTE* pbData, __in DWORD cbData ); +static HRESULT OnMsiBeginTransaction( + __in BYTE* pbData, + __in DWORD cbData + ); +static HRESULT OnMsiCommitTransaction(); +static HRESULT OnMsiRollbackTransaction(); + // function definitions @@ -726,62 +718,56 @@ LExit: extern "C" HRESULT ElevationMsiBeginTransaction( __in HANDLE hPipe, - __in_opt HWND hwndParent, - __in LPVOID pvContext -) + __in LPCWSTR wzName + ) { - UNREFERENCED_PARAMETER(hwndParent); HRESULT hr = S_OK; - BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; + BYTE* pbData = NULL; + SIZE_T cbData = 0; DWORD dwResult = ERROR_SUCCESS; - context.pvContext = pvContext; + // serialize message data + hr = BuffWriteString(&pbData, &cbData, wzName); + ExitOnFailure(hr, "Failed to write transaction name to message buffer."); - hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_BEGIN, NULL, 0, NULL, &context, &dwResult); - ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); - ExitOnWin32Error(dwResult, hr, "Failed beginning an elevated MSI transaction"); + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult); + ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION message to per-machine process."); + + hr = static_cast(dwResult); LExit: + ReleaseBuffer(pbData); + return hr; } extern "C" HRESULT ElevationMsiCommitTransaction( - __in HANDLE hPipe, - __in_opt HWND hwndParent, - __in LPVOID pvContext -) + __in HANDLE hPipe + ) { - UNREFERENCED_PARAMETER(hwndParent); HRESULT hr = S_OK; - BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; DWORD dwResult = ERROR_SUCCESS; - context.pvContext = pvContext; + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult); + ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION message to per-machine process."); - hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_COMMIT, NULL, 0, NULL, &context, &dwResult); - ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); - ExitOnWin32Error(dwResult, hr, "Failed committing an elevated MSI transaction"); + hr = static_cast(dwResult); LExit: return hr; } extern "C" HRESULT ElevationMsiRollbackTransaction( - __in HANDLE hPipe, - __in_opt HWND hwndParent, - __in LPVOID pvContext -) + __in HANDLE hPipe + ) { - UNREFERENCED_PARAMETER(hwndParent); HRESULT hr = S_OK; - BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; DWORD dwResult = ERROR_SUCCESS; - context.pvContext = pvContext; + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult); + ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION message to per-machine process."); - hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_ROLLBACK, NULL, 0, NULL, &context, &dwResult); - ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); - ExitOnWin32Error(dwResult, hr, "Failed rolling back an elevated MSI transaction"); + hr = static_cast(dwResult); LExit: return hr; @@ -1543,16 +1529,16 @@ static HRESULT ProcessElevatedChildMessage( switch (pMsg->dwMessage) { - case BURN_ELEVATION_TRANSACTION_BEGIN: - hrResult = OnMsiBeginTransaction(pContext); + case BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION: + hrResult = OnMsiBeginTransaction((BYTE*)pMsg->pvData, pMsg->cbData); break; - case BURN_ELEVATION_TRANSACTION_COMMIT: - hrResult = OnMsiCommitTransaction(pContext); + case BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION: + hrResult = OnMsiCommitTransaction(); break; - case BURN_ELEVATION_TRANSACTION_ROLLBACK: - hrResult = OnMsiRollbackTransaction(pContext); + case BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION: + hrResult = OnMsiRollbackTransaction(); break; case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE: @@ -1690,53 +1676,6 @@ static HRESULT ProcessResult( return hr; } -static HRESULT OnMsiBeginTransaction( - __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext -) -{ - UINT uResult = ERROR_SUCCESS; - HRESULT hr = S_OK; - - pContext->hMsiTrns = NULL; - pContext->hMsiTrnsEvent = NULL; - uResult = MsiBeginTransaction(L"WiX", 0, &pContext->hMsiTrns, &pContext->hMsiTrnsEvent); - ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction"); - -LExit: - return hr; -} - -static HRESULT OnMsiCommitTransaction( - __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext -) -{ - UINT uResult = ERROR_SUCCESS; - HRESULT hr = S_OK; - - uResult = MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT); - ExitOnWin32Error(uResult, hr, "Failed committing an MSI transaction"); - -LExit: - pContext->hMsiTrns = NULL; - pContext->hMsiTrnsEvent = NULL; - return hr; -} - -static HRESULT OnMsiRollbackTransaction( - __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext -) { - UINT uResult = ERROR_SUCCESS; - HRESULT hr = S_OK; - - uResult = MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK); - ExitOnWin32Error(uResult, hr, "Failed rolling back an MSI transaction"); - -LExit: - pContext->hMsiTrns = NULL; - pContext->hMsiTrnsEvent = NULL; - return hr; -} - static HRESULT OnApplyInitialize( __in BURN_VARIABLES* pVariables, __in BURN_REGISTRATION* pRegistration, @@ -2845,3 +2784,42 @@ LExit: ApprovedExesUninitializeLaunch(pLaunchApprovedExe); return hr; } + +static HRESULT OnMsiBeginTransaction( + __in BYTE* pbData, + __in DWORD cbData + ) +{ + HRESULT hr = S_OK; + SIZE_T iData = 0; + LPWSTR sczName = NULL; + + // Deserialize message data. + hr = BuffReadString(pbData, cbData, &iData, &sczName); + ExitOnFailure(hr, "Failed to read transaction name."); + + hr = MsiEngineBeginTransaction(sczName); + +LExit: + ReleaseStr(sczName); + + return hr; +} + +static HRESULT OnMsiCommitTransaction() +{ + HRESULT hr = S_OK; + + hr = MsiEngineCommitTransaction(); + + return hr; +} + +static HRESULT OnMsiRollbackTransaction() +{ + HRESULT hr = S_OK; + + hr = MsiEngineRollbackTransaction(); + + return hr; +} diff --git a/src/engine/elevation.h b/src/engine/elevation.h index d82d9b1c..975981da 100644 --- a/src/engine/elevation.h +++ b/src/engine/elevation.h @@ -159,19 +159,14 @@ HRESULT ElevationChildResumeAutomaticUpdates(); HRESULT ElevationMsiBeginTransaction( __in HANDLE hPipe, - __in_opt HWND hwndParent, - __in LPVOID pvContext -); + __in LPCWSTR wzName + ); HRESULT ElevationMsiCommitTransaction( - __in HANDLE hPipe, - __in_opt HWND hwndParent, - __in LPVOID pvContext -); + __in HANDLE hPipe + ); HRESULT ElevationMsiRollbackTransaction( - __in HANDLE hPipe, - __in_opt HWND hwndParent, - __in LPVOID pvContext -); + __in HANDLE hPipe + ); #ifdef __cplusplus } diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp index c20e2ef8..fcd8817d 100644 --- a/src/engine/msiengine.cpp +++ b/src/engine/msiengine.cpp @@ -1137,6 +1137,48 @@ LExit: return hr; } +extern "C" HRESULT MsiEngineBeginTransaction( + __in LPCWSTR wzName + ) +{ + HRESULT hr = S_OK; + UINT uResult = ERROR_SUCCESS; + MSIHANDLE hTransactionHandle = NULL; + HANDLE hChangeOfOwnerEvent = NULL; + + uResult = ::MsiBeginTransaction(wzName, 0, &hTransactionHandle, &hChangeOfOwnerEvent); + ExitOnWin32Error(uResult, hr, "Failed to begin an MSI transaction"); + +LExit: + return hr; +} + +extern "C" HRESULT MsiEngineCommitTransaction() +{ + HRESULT hr = S_OK; + UINT uResult = ERROR_SUCCESS; + + uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT); + ExitOnWin32Error(uResult, hr, "Failed to commit the MSI transaction"); + +LExit: + + return hr; +} + +extern "C" HRESULT MsiEngineRollbackTransaction() +{ + HRESULT hr = S_OK; + UINT uResult = ERROR_SUCCESS; + + uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK); + ExitOnWin32Error(uResult, hr, "Failed to rollback the MSI transaction"); + +LExit: + + return hr; +} + extern "C" HRESULT MsiEngineExecutePackage( __in_opt HWND hwndParent, __in BURN_EXECUTE_ACTION* pExecuteAction, diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h index 64bddcf0..63393006 100644 --- a/src/engine/msiengine.h +++ b/src/engine/msiengine.h @@ -52,6 +52,11 @@ HRESULT MsiEngineAddCompatiblePackage( __in const BURN_PACKAGE* pPackage, __out_opt BURN_PACKAGE** ppCompatiblePackage ); +HRESULT MsiEngineBeginTransaction( + __in LPCWSTR wzName + ); +HRESULT MsiEngineCommitTransaction(); +HRESULT MsiEngineRollbackTransaction(); HRESULT MsiEngineExecutePackage( __in_opt HWND hwndParent, __in BURN_EXECUTE_ACTION* pExecuteAction, -- cgit v1.2.3-55-g6feb