From 47bca2dc51525fcad86f325278b14953ac5b137e Mon Sep 17 00:00:00 2001 From: Bob Arnson Date: Sat, 15 Jan 2022 21:40:54 -0500 Subject: Fix 32/64-bit bitness handling in Burn and BUtil. - Take advantage of RegOpenEx. - Always look for related bundles in both 32 and 64 hives. - BundleEnumRelatedBundle requires caller to specify bitness. --- src/libs/dutil/WixToolset.DUtil/butil.cpp | 232 +++++++++++--------------- src/libs/dutil/WixToolset.DUtil/inc/butil.h | 7 +- src/libs/dutil/WixToolset.DUtil/inc/regutil.h | 9 + src/libs/dutil/WixToolset.DUtil/monutil.cpp | 13 +- src/libs/dutil/WixToolset.DUtil/precomp.h | 2 +- src/libs/dutil/WixToolset.DUtil/regutil.cpp | 19 +-- 6 files changed, 121 insertions(+), 161 deletions(-) (limited to 'src/libs/dutil') diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp index 4262d573..2f45da56 100644 --- a/src/libs/dutil/WixToolset.DUtil/butil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp @@ -63,13 +63,6 @@ static HRESULT CopyStringToBuffer( __in_z_opt LPWSTR wzBuffer, __inout SIZE_T* pcchBuffer ); -static HRESULT DoBundleEnumRelatedBundle( - __in HKEY hkRoot, - __in REG_KEY_BITNESS kbKeyBitness, - __in_z LPCWSTR wzUpgradeCode, - __inout PDWORD pdwStartIndex, - __deref_out_z LPWSTR* psczBundleId - ); DAPI_(HRESULT) BundleGetBundleInfo( @@ -156,11 +149,21 @@ LExit: DAPI_(HRESULT) BundleEnumRelatedBundle( __in_z LPCWSTR wzUpgradeCode, __in BUNDLE_INSTALL_CONTEXT context, + __in REG_KEY_BITNESS kbKeyBitness, __inout PDWORD pdwStartIndex, __deref_out_z LPWSTR* psczBundleId ) { HRESULT hr = S_OK; + BOOL fUpgradeCodeFound = FALSE; + HKEY hkUninstall = NULL; + HKEY hkBundle = NULL; + LPWSTR sczUninstallSubKey = NULL; + LPWSTR sczUninstallSubKeyPath = NULL; + LPWSTR sczValue = NULL; + DWORD dwType = 0; + LPWSTR* rgsczBundleUpgradeCodes = NULL; + DWORD cBundleUpgradeCodes = 0; HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; if (!wzUpgradeCode || !pdwStartIndex) @@ -168,27 +171,105 @@ DAPI_(HRESULT) BundleEnumRelatedBundle( ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); } - hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_DEFAULT, wzUpgradeCode, pdwStartIndex, psczBundleId); - ButilExitOnFailure(hr, "Failed to enumerate default-bitness bundles."); - if (S_FALSE == hr) + hr = RegOpenEx(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, kbKeyBitness, &hkUninstall); + ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); + + for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++) { -#if defined(_WIN64) - hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_32BIT, wzUpgradeCode, pdwStartIndex, psczBundleId); - ButilExitOnFailure(hr, "Failed to enumerate 32-bit bundles."); -#else - hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_64BIT, wzUpgradeCode, pdwStartIndex, psczBundleId); - ButilExitOnFailure(hr, "Failed to enumerate 64-bit bundles."); -#endif + hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey); + ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path."); + + hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey); + ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); + + hr = RegOpenEx(hkRoot, sczUninstallSubKeyPath, KEY_READ, kbKeyBitness, &hkBundle); + ButilExitOnFailure(hr, "Failed to open uninstall key path."); + + // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ + hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType); + if (FAILED(hr)) + { + ReleaseRegKey(hkBundle); + ReleaseNullStr(sczUninstallSubKey); + ReleaseNullStr(sczUninstallSubKeyPath); + // Not a bundle + continue; + } + + switch (dwType) + { + case REG_SZ: + hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue); + ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property."); + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1)) + { + *pdwStartIndex = dwIndex; + fUpgradeCodeFound = TRUE; + break; + } + + ReleaseNullStr(sczValue); + + break; + case REG_MULTI_SZ: + hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes); + ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property."); + + for (DWORD i = 0; i < cBundleUpgradeCodes; i++) + { + LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i]; + if (wzBundleUpgradeCode && *wzBundleUpgradeCode) + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1)) + { + *pdwStartIndex = dwIndex; + fUpgradeCodeFound = TRUE; + break; + } + } + } + ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes); + + break; + + default: + ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType); + } + + if (fUpgradeCodeFound) + { + if (psczBundleId) + { + *psczBundleId = sczUninstallSubKey; + sczUninstallSubKey = NULL; + } + + break; + } + + // Cleanup before next iteration + ReleaseRegKey(hkBundle); + ReleaseNullStr(sczUninstallSubKey); + ReleaseNullStr(sczUninstallSubKeyPath); } LExit: - return hr; + ReleaseStr(sczValue); + ReleaseStr(sczUninstallSubKey); + ReleaseStr(sczUninstallSubKeyPath); + ReleaseRegKey(hkBundle); + ReleaseRegKey(hkUninstall); + ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes); + + return FAILED(hr) ? hr : fUpgradeCodeFound ? S_OK : S_FALSE; } DAPI_(HRESULT) BundleEnumRelatedBundleFixed( __in_z LPCWSTR wzUpgradeCode, __in BUNDLE_INSTALL_CONTEXT context, + __in REG_KEY_BITNESS kbKeyBitness, __inout PDWORD pdwStartIndex, __out_ecount(MAX_GUID_CHARS+1) LPWSTR wzBundleId ) @@ -197,7 +278,7 @@ DAPI_(HRESULT) BundleEnumRelatedBundleFixed( LPWSTR sczValue = NULL; size_t cchValue = 0; - hr = BundleEnumRelatedBundle(wzUpgradeCode, context, pdwStartIndex, &sczValue); + hr = BundleEnumRelatedBundle(wzUpgradeCode, context, kbKeyBitness, pdwStartIndex, &sczValue); if (S_OK == hr && wzBundleId) { hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchValue); @@ -396,116 +477,3 @@ static HRESULT CopyStringToBuffer( return hr; } - -static HRESULT DoBundleEnumRelatedBundle( - __in HKEY hkRoot, - __in REG_KEY_BITNESS kbKeyBitness, - __in_z LPCWSTR wzUpgradeCode, - __inout PDWORD pdwStartIndex, - __deref_out_z LPWSTR* psczBundleId -) -{ - HRESULT hr = S_OK; - BOOL fUpgradeCodeFound = FALSE; - HKEY hkUninstall = NULL; - HKEY hkBundle = NULL; - LPWSTR sczUninstallSubKey = NULL; - LPWSTR sczUninstallSubKeyPath = NULL; - LPWSTR sczValue = NULL; - DWORD dwType = 0; - LPWSTR* rgsczBundleUpgradeCodes = NULL; - DWORD cBundleUpgradeCodes = 0; - - hr = RegOpenEx(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, kbKeyBitness, &hkUninstall); - ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); - - for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++) - { - hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey); - ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path."); - - hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey); - ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); - - hr = RegOpenEx(hkRoot, sczUninstallSubKeyPath, KEY_READ, kbKeyBitness, &hkBundle); - ButilExitOnFailure(hr, "Failed to open uninstall key path."); - - // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ - hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType); - if (FAILED(hr)) - { - ReleaseRegKey(hkBundle); - ReleaseNullStr(sczUninstallSubKey); - ReleaseNullStr(sczUninstallSubKeyPath); - // Not a bundle - continue; - } - - switch (dwType) - { - case REG_SZ: - hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue); - ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property."); - - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1)) - { - *pdwStartIndex = dwIndex; - fUpgradeCodeFound = TRUE; - break; - } - - ReleaseNullStr(sczValue); - - break; - case REG_MULTI_SZ: - hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes); - ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property."); - - for (DWORD i = 0; i < cBundleUpgradeCodes; i++) - { - LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i]; - if (wzBundleUpgradeCode && *wzBundleUpgradeCode) - { - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1)) - { - *pdwStartIndex = dwIndex; - fUpgradeCodeFound = TRUE; - break; - } - } - } - ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes); - - break; - - default: - ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType); - } - - if (fUpgradeCodeFound) - { - if (psczBundleId) - { - *psczBundleId = sczUninstallSubKey; - sczUninstallSubKey = NULL; - } - - break; - } - - // Cleanup before next iteration - ReleaseRegKey(hkBundle); - ReleaseNullStr(sczUninstallSubKey); - ReleaseNullStr(sczUninstallSubKeyPath); - } - -LExit: - ReleaseStr(sczValue); - ReleaseStr(sczUninstallSubKey); - ReleaseStr(sczUninstallSubKeyPath); - ReleaseRegKey(hkBundle); - ReleaseRegKey(hkUninstall); - ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes); - - return FAILED(hr) ? hr : fUpgradeCodeFound ? S_OK : S_FALSE; -} diff --git a/src/libs/dutil/WixToolset.DUtil/inc/butil.h b/src/libs/dutil/WixToolset.DUtil/inc/butil.h index 3b316e66..9c2010ee 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/butil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/butil.h @@ -60,7 +60,9 @@ HRESULT DAPI BundleGetBundleInfoFixed( ); /******************************************************************** -BundleEnumRelatedBundle - Queries the bundle installation metadata for installs with the given upgrade code +BundleEnumRelatedBundle - Queries the bundle installation metadata for installs with the given upgrade code. +Enumerate 32-bit and 64-bit in two passes. + RETURNS: E_INVALIDARG An invalid parameter was passed to the function. @@ -74,12 +76,14 @@ RETURNS: HRESULT DAPI BundleEnumRelatedBundle( __in_z LPCWSTR wzUpgradeCode, __in BUNDLE_INSTALL_CONTEXT context, + __in REG_KEY_BITNESS kbKeyBitness, __inout PDWORD pdwStartIndex, __deref_out_z LPWSTR* psczBundleId ); /******************************************************************** BundleEnumRelatedBundleFixed - Queries the bundle installation metadata for installs with the given upgrade code +Enumerate 32-bit and 64-bit in two passes. NOTE: lpBundleIdBuff is a buffer to receive the bundle GUID. This buffer must be 39 characters long. The first 38 characters are for the GUID, and the last character is for the terminating null character. @@ -96,6 +100,7 @@ RETURNS: HRESULT DAPI BundleEnumRelatedBundleFixed( __in_z LPCWSTR wzUpgradeCode, __in BUNDLE_INSTALL_CONTEXT context, + __in REG_KEY_BITNESS kbKeyBitness, __inout PDWORD pdwStartIndex, __out_ecount(MAX_GUID_CHARS+1) LPWSTR wzBundleId ); diff --git a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h index db8e0c5c..3cbb53b0 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h @@ -408,6 +408,15 @@ BOOL DAPI RegValueExists( __in REG_KEY_BITNESS kbKeyBitness ); +/******************************************************************** +RegTranslateKeyBitness - Converts from REG_KEY_BITNESS values to +REGSAM-compatible values. + +*********************************************************************/ +REGSAM DAPI RegTranslateKeyBitness( + __in REG_KEY_BITNESS kbKeyBitness + ); + #ifdef __cplusplus } #endif diff --git a/src/libs/dutil/WixToolset.DUtil/monutil.cpp b/src/libs/dutil/WixToolset.DUtil/monutil.cpp index 6a7f0596..6ad75b56 100644 --- a/src/libs/dutil/WixToolset.DUtil/monutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/monutil.cpp @@ -1677,18 +1677,7 @@ static REGSAM GetRegKeyBitness( __in MON_REQUEST *pRequest ) { - if (REG_KEY_32BIT == pRequest->regkey.kbKeyBitness) - { - return KEY_WOW64_32KEY; - } - else if (REG_KEY_64BIT == pRequest->regkey.kbKeyBitness) - { - return KEY_WOW64_64KEY; - } - else - { - return 0; - } + return RegTranslateKeyBitness(pRequest->regkey.kbKeyBitness); } static HRESULT DuplicateRemoveMessage( diff --git a/src/libs/dutil/WixToolset.DUtil/precomp.h b/src/libs/dutil/WixToolset.DUtil/precomp.h index 093c16a2..902fe3e3 100644 --- a/src/libs/dutil/WixToolset.DUtil/precomp.h +++ b/src/libs/dutil/WixToolset.DUtil/precomp.h @@ -48,7 +48,6 @@ #include "apputil.h" #include "atomutil.h" #include "buffutil.h" -#include "butil.h" #include "cabcutil.h" #include "cabutil.h" #include "conutil.h" @@ -76,6 +75,7 @@ #include "polcutil.h" #include "procutil.h" #include "regutil.h" +#include "butil.h" // NOTE: Butil must come after Regutil. #include "resrutil.h" #include "reswutil.h" #include "rmutil.h" diff --git a/src/libs/dutil/WixToolset.DUtil/regutil.cpp b/src/libs/dutil/WixToolset.DUtil/regutil.cpp index f4719466..219a6c11 100644 --- a/src/libs/dutil/WixToolset.DUtil/regutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/regutil.cpp @@ -32,9 +32,6 @@ static PFN_REGDELETEVALUEW vpfnRegDeleteValueW = ::RegDeleteValueW; static HMODULE vhAdvApi32Dll = NULL; static BOOL vfRegInitialized = FALSE; -static REGSAM TranslateKeyBitness( - __in REG_KEY_BITNESS kbKeyBitness -); static HRESULT WriteStringToRegistry( __in HKEY hk, __in_z_opt LPCWSTR wzName, @@ -135,7 +132,7 @@ DAPI_(HRESULT) RegCreateEx( DWORD er = ERROR_SUCCESS; DWORD dwDisposition; - REGSAM samDesired = TranslateKeyBitness(kbKeyBitness); + REGSAM samDesired = RegTranslateKeyBitness(kbKeyBitness); er = vpfnRegCreateKeyExW(hkRoot, wzSubKey, 0, NULL, fVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE, dwAccess | samDesired, pSecurityAttributes, phk, &dwDisposition); RegExitOnWin32Error(er, hr, "Failed to create registry key."); @@ -171,7 +168,7 @@ DAPI_(HRESULT) RegOpenEx( HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; - REGSAM samDesired = TranslateKeyBitness(kbKeyBitness); + REGSAM samDesired = RegTranslateKeyBitness(kbKeyBitness); er = vpfnRegOpenKeyExW(hkRoot, wzSubKey, 0, dwAccess | samDesired, phk); if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) { @@ -229,7 +226,7 @@ DAPI_(HRESULT) RegDelete( if (NULL != vpfnRegDeleteKeyExW) { - REGSAM samDesired = TranslateKeyBitness(kbKeyBitness); + REGSAM samDesired = RegTranslateKeyBitness(kbKeyBitness); er = vpfnRegDeleteKeyExW(hkRoot, wzSubKey, samDesired, 0); if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) { @@ -912,11 +909,6 @@ LExit: return hr; } -/******************************************************************** -RegValueExists - determines whether a named value exists in a -specified subkey. - -*********************************************************************/ DAPI_(BOOL) RegValueExists( __in HKEY hk, __in_z LPCWSTR wzSubKey, @@ -940,7 +932,7 @@ LExit: return SUCCEEDED(hr); } -static REGSAM TranslateKeyBitness( +DAPI_(REGSAM) RegTranslateKeyBitness( __in REG_KEY_BITNESS kbKeyBitness ) { @@ -948,14 +940,11 @@ static REGSAM TranslateKeyBitness( { case REG_KEY_32BIT: return KEY_WOW64_32KEY; - break; case REG_KEY_64BIT: return KEY_WOW64_64KEY; - break; case REG_KEY_DEFAULT: default: return 0; - break; } } -- cgit v1.2.3-55-g6feb