From c294fb860ed7710c80fc004af6c9ebb09779c70c Mon Sep 17 00:00:00 2001 From: Nir Bar Date: Mon, 11 Jan 2021 20:07:38 +0200 Subject: Add functions to start/end MSI transactions and check whether or not it is supported on the target machine (#22) * Add functions to start/end MSI transactions and check whether or not it is supported on the target machine * Add log mode parameter to MSI transaction functions. * No default log mode for WiuEndTransaction --- src/dutil/inc/wiutil.h | 24 ++++++++++++++++ src/dutil/wiutil.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) (limited to 'src') diff --git a/src/dutil/inc/wiutil.h b/src/dutil/inc/wiutil.h index 07f6b56c..10d003b0 100644 --- a/src/dutil/inc/wiutil.h +++ b/src/dutil/inc/wiutil.h @@ -226,6 +226,15 @@ typedef UINT (WINAPI *PFN_MSISOURCELISTADDSOURCEEXW)( __in LPCWSTR szSource, __in_opt DWORD dwIndex ); +typedef UINT(WINAPI* PFN_MSIBEGINTRANSACTIONW)( + __in LPCWSTR szName, + __in DWORD dwTransactionAttributes, + __out MSIHANDLE* phTransactionHandle, + __out HANDLE* phChangeOfOwnerEvent + ); +typedef UINT(WINAPI* PFN_MSIENDTRANSACTION)( + __in DWORD dwTransactionState + ); HRESULT DAPI WiuInitialize( @@ -372,6 +381,21 @@ HRESULT DAPI WiuSourceListAddSourceEx( __in_z LPCWSTR wzSource, __in_opt DWORD dwIndex ); +HRESULT DAPI WiuBeginTransaction( + __in_z LPCWSTR szName, + __in DWORD dwTransactionAttributes, + __out MSIHANDLE* phTransactionHandle, + __out HANDLE* phChangeOfOwnerEvent, + __in DWORD dwLogMode, + __in_z LPCWSTR szLogPath + ); +HRESULT DAPI WiuEndTransaction( + __in DWORD dwTransactionState, + __in DWORD dwLogMode, + __in_z LPCWSTR szLogPath + ); +BOOL DAPI WiuIsMsiTransactionSupported( + ); #ifdef __cplusplus } diff --git a/src/dutil/wiutil.cpp b/src/dutil/wiutil.cpp index 1b3dd317..7336d685 100644 --- a/src/dutil/wiutil.cpp +++ b/src/dutil/wiutil.cpp @@ -42,6 +42,11 @@ static PFN_MSIGETPATCHINFOEXW vpfnMsiGetPatchInfoExWFromLibrary = NULL; static PFN_MSIGETPRODUCTINFOEXW vpfnMsiGetProductInfoExWFromLibrary = NULL; static PFN_MSISETEXTERNALUIRECORD vpfnMsiSetExternalUIRecordFromLibrary = NULL; static PFN_MSISOURCELISTADDSOURCEEXW vpfnMsiSourceListAddSourceExWFromLibrary = NULL; + +// MSI Transactions v4.5+ +static PFN_MSIBEGINTRANSACTIONW vpfnMsiBeginTransaction = NULL; +static PFN_MSIENDTRANSACTION vpfnMsiEndTransaction = NULL; + static BOOL vfWiuInitialized = FALSE; // globals @@ -176,6 +181,17 @@ extern "C" HRESULT DAPI WiuInitialize( vpfnMsiSourceListAddSourceExW = vpfnMsiSourceListAddSourceExWFromLibrary; } + // MSI Transaction functions + if (NULL == vpfnMsiBeginTransaction) + { + vpfnMsiBeginTransaction = reinterpret_cast(::GetProcAddress(vhMsiDll, "MsiBeginTransactionW")); + } + + if (NULL == vpfnMsiEndTransaction) + { + vpfnMsiEndTransaction = reinterpret_cast(::GetProcAddress(vhMsiDll, "MsiEndTransaction")); + } + vfWiuInitialized = TRUE; LExit: @@ -202,6 +218,8 @@ extern "C" void DAPI WiuUninitialize( vpfnMsiDetermineApplicablePatchesWFromLibrary = NULL; vpfnMsiDeterminePatchSequenceWFromLibrary = NULL; vpfnMsiSourceListAddSourceExWFromLibrary = NULL; + vpfnMsiBeginTransaction = NULL; + vpfnMsiEndTransaction = NULL; } vfWiuInitialized = FALSE; @@ -886,6 +904,63 @@ LExit: return hr; } +extern "C" BOOL DAPI WiuIsMsiTransactionSupported( + ) +{ + return vpfnMsiBeginTransaction && vpfnMsiEndTransaction; +} + +extern "C" HRESULT DAPI WiuBeginTransaction( + __in_z LPCWSTR szName, + __in DWORD dwTransactionAttributes, + __out MSIHANDLE * phTransactionHandle, + __out HANDLE * phChangeOfOwnerEvent, + __in DWORD dwLogMode, + __in_z LPCWSTR szLogPath + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + if (!WiuIsMsiTransactionSupported()) + { + ExitOnFailure(hr = E_NOTIMPL, "Msi transactions are not supported"); + } + + hr = WiuEnableLog(dwLogMode, szLogPath, INSTALLLOGATTRIBUTES_APPEND); + ExitOnFailure(hr, "Failed to enable logging for MSI transaction"); + + er = vpfnMsiBeginTransaction(szName, dwTransactionAttributes, phTransactionHandle, phChangeOfOwnerEvent); + ExitOnWin32Error(er, hr, "Failed to begin transaction."); + +LExit: + return hr; +} + +extern "C" HRESULT DAPI WiuEndTransaction( + __in DWORD dwTransactionState, + __in DWORD dwLogMode, + __in_z LPCWSTR szLogPath + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + if (!WiuIsMsiTransactionSupported()) + { + ExitOnFailure(hr = E_NOTIMPL, "Msi transactions are not supported"); + } + + hr = WiuEnableLog(dwLogMode, szLogPath, INSTALLLOGATTRIBUTES_APPEND); + ExitOnFailure(hr, "Failed to enable logging for MSI transaction"); + + er = vpfnMsiEndTransaction(dwTransactionState); + ExitOnWin32Error(er, hr, "Failed to end transaction."); + +LExit: + return hr; +} + static DWORD CheckForRestartErrorCode( -- cgit v1.2.3-55-g6feb