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/burn/engine/elevation.cpp | 8 +- src/burn/engine/relatedbundle.cpp | 24 +-- src/burn/engine/search.cpp | 16 +- src/burn/engine/variable.cpp | 2 +- src/burn/test/BurnUnitTest/RegistrationTest.cpp | 2 +- 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 +- .../BundleAv1x64/BundleAv1x64.wixproj | 16 ++ .../BundleAv1x64/BundleAv1x64.wxs | 10 + .../UpgradeRelatedBundleTests.cs | 17 ++ 14 files changed, 180 insertions(+), 197 deletions(-) create mode 100644 src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wixproj create mode 100644 src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wxs diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 355b4a34..221d8b6d 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp @@ -3299,7 +3299,6 @@ static HRESULT OnLaunchApprovedExe( SIZE_T iData = 0; BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = NULL; BURN_APPROVED_EXE* pApprovedExe = NULL; - REGSAM samDesired = KEY_QUERY_VALUE; HKEY hKey = NULL; DWORD dwProcessId = 0; BYTE* pbSendData = NULL; @@ -3323,12 +3322,7 @@ static HRESULT OnLaunchApprovedExe( LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_SEARCH, pApprovedExe->sczKey, pApprovedExe->sczValueName ? pApprovedExe->sczValueName : L"", pApprovedExe->fWin64 ? L"yes" : L"no"); - if (pApprovedExe->fWin64) - { - samDesired |= KEY_WOW64_64KEY; - } - - hr = RegOpen(HKEY_LOCAL_MACHINE, pApprovedExe->sczKey, samDesired, &hKey); + hr = RegOpenEx(HKEY_LOCAL_MACHINE, pApprovedExe->sczKey, KEY_QUERY_VALUE, pApprovedExe->fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey); ExitOnFailure(hr, "Failed to open the registry key for the approved exe path."); hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp index 99ed8553..619fa8dd 100644 --- a/src/burn/engine/relatedbundle.cpp +++ b/src/burn/engine/relatedbundle.cpp @@ -11,13 +11,13 @@ static __callback int __cdecl CompareRelatedBundles( ); static HRESULT InitializeForScopeAndBitness( __in BOOL fPerMachine, - __in BOOL fWow6432, + __in REG_KEY_BITNESS regBitness, __in BURN_REGISTRATION* pRegistration, __in BURN_RELATED_BUNDLES* pRelatedBundles ); static HRESULT LoadIfRelatedBundle( __in BOOL fPerMachine, - __in BOOL fWow6432, + __in REG_KEY_BITNESS regBitness, __in HKEY hkUninstallKey, __in_z LPCWSTR sczRelatedBundleId, __in BURN_REGISTRATION* pRegistration, @@ -47,13 +47,11 @@ extern "C" HRESULT RelatedBundlesInitializeForScope( { HRESULT hr = S_OK; - hr = InitializeForScopeAndBitness(fPerMachine, /*fWow6432*/FALSE, pRegistration, pRelatedBundles); - ExitOnFailure(hr, "Failed to open platform-native uninstall registry key."); - -#if defined(_WIN64) - hr = InitializeForScopeAndBitness(fPerMachine, /*fWow6432*/TRUE, pRegistration, pRelatedBundles); + hr = InitializeForScopeAndBitness(fPerMachine, REG_KEY_32BIT, pRegistration, pRelatedBundles); ExitOnFailure(hr, "Failed to open 32-bit uninstall registry key."); -#endif + + hr = InitializeForScopeAndBitness(fPerMachine, REG_KEY_64BIT, pRegistration, pRelatedBundles); + ExitOnFailure(hr, "Failed to open 64-bit uninstall registry key."); LExit: return hr; @@ -170,7 +168,7 @@ static __callback int __cdecl CompareRelatedBundles( static HRESULT InitializeForScopeAndBitness( __in BOOL fPerMachine, - __in BOOL fWow6432, + __in REG_KEY_BITNESS regBitness, __in BURN_REGISTRATION * pRegistration, __in BURN_RELATED_BUNDLES * pRelatedBundles ) @@ -180,7 +178,7 @@ static HRESULT InitializeForScopeAndBitness( HKEY hkUninstallKey = NULL; LPWSTR sczRelatedBundleId = NULL; - hr = RegOpen(hkRoot, BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ | (fWow6432 ? KEY_WOW64_32KEY : 0), &hkUninstallKey); + hr = RegOpenEx(hkRoot, BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, regBitness, &hkUninstallKey); if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { ExitFunction1(hr = S_OK); @@ -202,7 +200,7 @@ static HRESULT InitializeForScopeAndBitness( { // Ignore failures here since we'll often find products that aren't actually // related bundles (or even bundles at all). - HRESULT hrRelatedBundle = LoadIfRelatedBundle(fPerMachine, fWow6432, hkUninstallKey, sczRelatedBundleId, pRegistration, pRelatedBundles); + HRESULT hrRelatedBundle = LoadIfRelatedBundle(fPerMachine, regBitness, hkUninstallKey, sczRelatedBundleId, pRegistration, pRelatedBundles); UNREFERENCED_PARAMETER(hrRelatedBundle); } } @@ -216,7 +214,7 @@ LExit: static HRESULT LoadIfRelatedBundle( __in BOOL fPerMachine, - __in BOOL fWow6432, + __in REG_KEY_BITNESS regBitness, __in HKEY hkUninstallKey, __in_z LPCWSTR sczRelatedBundleId, __in BURN_REGISTRATION* pRegistration, @@ -227,7 +225,7 @@ static HRESULT LoadIfRelatedBundle( HKEY hkBundleId = NULL; BOOTSTRAPPER_RELATION_TYPE relationType = BOOTSTRAPPER_RELATION_NONE; - hr = RegOpen(hkUninstallKey, sczRelatedBundleId, KEY_READ | (fWow6432 ? KEY_WOW64_32KEY : 0), &hkBundleId); + hr = RegOpenEx(hkUninstallKey, sczRelatedBundleId, KEY_READ, regBitness, &hkBundleId); ExitOnFailure(hr, "Failed to open uninstall key for potential related bundle: %ls", sczRelatedBundleId); hr = DetermineRelationType(hkBundleId, pRegistration, &relationType); diff --git a/src/burn/engine/search.cpp b/src/burn/engine/search.cpp index 6d5f8d49..4505e1a2 100644 --- a/src/burn/engine/search.cpp +++ b/src/burn/engine/search.cpp @@ -836,19 +836,13 @@ static HRESULT RegistrySearchExists( HKEY hKey = NULL; DWORD dwType = 0; BOOL fExists = FALSE; - REGSAM samDesired = KEY_QUERY_VALUE; - - if (pSearch->RegistrySearch.fWin64) - { - samDesired = samDesired | KEY_WOW64_64KEY; - } // format key string hr = VariableFormatString(pVariables, pSearch->RegistrySearch.sczKey, &sczKey, NULL); ExitOnFailure(hr, "Failed to format key string."); // open key - hr = RegOpen(pSearch->RegistrySearch.hRoot, sczKey, samDesired, &hKey); + hr = RegOpenEx(pSearch->RegistrySearch.hRoot, sczKey, KEY_QUERY_VALUE, pSearch->RegistrySearch.fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey); if (SUCCEEDED(hr)) { fExists = TRUE; @@ -922,12 +916,6 @@ static HRESULT RegistrySearchValue( LPBYTE pData = NULL; DWORD cch = 0; BURN_VARIANT value = { }; - REGSAM samDesired = KEY_QUERY_VALUE; - - if (pSearch->RegistrySearch.fWin64) - { - samDesired = samDesired | KEY_WOW64_64KEY; - } // format key string hr = VariableFormatString(pVariables, pSearch->RegistrySearch.sczKey, &sczKey, NULL); @@ -941,7 +929,7 @@ static HRESULT RegistrySearchValue( } // open key - hr = RegOpen(pSearch->RegistrySearch.hRoot, sczKey, samDesired, &hKey); + hr = RegOpenEx(pSearch->RegistrySearch.hRoot, sczKey, KEY_QUERY_VALUE, pSearch->RegistrySearch.fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey); if (E_FILENOTFOUND == hr) { // What if there is a hidden variable in sczKey? diff --git a/src/burn/engine/variable.cpp b/src/burn/engine/variable.cpp index fa6190dd..b3dcdb7d 100644 --- a/src/burn/engine/variable.cpp +++ b/src/burn/engine/variable.cpp @@ -2361,7 +2361,7 @@ static HRESULT Get64bitFolderFromRegistry( AssertSz(CSIDL_PROGRAM_FILES == nFolder || CSIDL_PROGRAM_FILES_COMMON == nFolder, "Unknown folder CSIDL."); LPCWSTR wzFolderValue = CSIDL_PROGRAM_FILES_COMMON == nFolder ? L"CommonFilesDir" : L"ProgramFilesDir"; - hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", KEY_READ | KEY_WOW64_64KEY, &hkFolders); + hr = RegOpenEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", KEY_READ, REG_KEY_64BIT, &hkFolders); ExitOnFailure(hr, "Failed to open Windows folder key."); hr = RegReadString(hkFolders, wzFolderValue, psczPath); diff --git a/src/burn/test/BurnUnitTest/RegistrationTest.cpp b/src/burn/test/BurnUnitTest/RegistrationTest.cpp index dbcd2613..d2ec0a82 100644 --- a/src/burn/test/BurnUnitTest/RegistrationTest.cpp +++ b/src/burn/test/BurnUnitTest/RegistrationTest.cpp @@ -645,7 +645,7 @@ namespace Bootstrapper NativeAssert::Succeeded(hr, "Failed to allocate buffer for related bundle id."); // Verify we can find ourself via the UpgradeCode - hr = BundleEnumRelatedBundleFixed(TEST_BUNDLE_UPGRADE_CODE, BUNDLE_INSTALL_CONTEXT_USER, &dwRelatedBundleIndex, sczRelatedBundleId); + hr = BundleEnumRelatedBundleFixed(TEST_BUNDLE_UPGRADE_CODE, BUNDLE_INSTALL_CONTEXT_USER, REG_KEY_DEFAULT, &dwRelatedBundleIndex, sczRelatedBundleId); TestThrowOnFailure(hr, L"Failed to enumerate related bundle."); NativeAssert::StringEqual(TEST_BUNDLE_ID, sczRelatedBundleId); 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; } } diff --git a/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wixproj b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wixproj new file mode 100644 index 00000000..44bf9772 --- /dev/null +++ b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wixproj @@ -0,0 +1,16 @@ + + + + + TestBA_x64 + X64 + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wxs b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wxs new file mode 100644 index 00000000..7bf16212 --- /dev/null +++ b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wxs @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs index a515ed69..6d81252e 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs @@ -49,5 +49,22 @@ namespace WixToolsetTest.BurnE2E bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache(); } + + [Fact] + public void Bundle32UpgradesBundle64() + { + var packageAv1 = this.CreatePackageInstaller("PackageAv1"); + var packageAv2 = this.CreatePackageInstaller("PackageAv2"); + var bundleAv1x64 = this.CreateBundleInstaller("BundleAv1x64"); + var bundleAv2 = this.CreateBundleInstaller("BundleAv2"); + + bundleAv1x64.Install(); + bundleAv1x64.VerifyRegisteredAndInPackageCache(); + + bundleAv2.Install(); + bundleAv2.VerifyRegisteredAndInPackageCache(); + + bundleAv1x64.VerifyUnregisteredAndRemovedFromPackageCache(); + } } } -- cgit v1.2.3-55-g6feb