@joebigelow / wix-1 / commits / 47bca2dc

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.

Bob Arnson committed Jan 15, 2022 at 21:40 UTC 47bca2dc51525fcad86f325278b14953ac5b137e
14 files changed +180 -197
src/burn/engine/elevation.cpp
+1 -7
@@ -3299,7 +3299,6 @@ static HRESULT OnLaunchApprovedExe(
3299 SIZE_T iData = 0;
3300 BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = NULL;
3301 BURN_APPROVED_EXE* pApprovedExe = NULL;
3302 - REGSAM samDesired = KEY_QUERY_VALUE;
3302 HKEY hKey = NULL;
3303 DWORD dwProcessId = 0;
3304 BYTE* pbSendData = NULL;
@@ -3323,12 +3322,7 @@ static HRESULT OnLaunchApprovedExe(
3322
3323 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_SEARCH, pApprovedExe->sczKey, pApprovedExe->sczValueName ? pApprovedExe->sczValueName : L"", pApprovedExe->fWin64 ? L"yes" : L"no");
3324
3326 - if (pApprovedExe->fWin64)
3327 - {
3328 - samDesired |= KEY_WOW64_64KEY;
3329 - }
3330 -
3331 - hr = RegOpen(HKEY_LOCAL_MACHINE, pApprovedExe->sczKey, samDesired, &hKey);
3325 + hr = RegOpenEx(HKEY_LOCAL_MACHINE, pApprovedExe->sczKey, KEY_QUERY_VALUE, pApprovedExe->fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey);
3326 ExitOnFailure(hr, "Failed to open the registry key for the approved exe path.");
3327
3328 hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath);
src/burn/engine/relatedbundle.cpp
+11 -13
@@ -11,13 +11,13 @@ static __callback int __cdecl CompareRelatedBundles(
11 );
12 static HRESULT InitializeForScopeAndBitness(
13 __in BOOL fPerMachine,
14 - __in BOOL fWow6432,
14 + __in REG_KEY_BITNESS regBitness,
15 __in BURN_REGISTRATION* pRegistration,
16 __in BURN_RELATED_BUNDLES* pRelatedBundles
17 );
18 static HRESULT LoadIfRelatedBundle(
19 __in BOOL fPerMachine,
20 - __in BOOL fWow6432,
20 + __in REG_KEY_BITNESS regBitness,
21 __in HKEY hkUninstallKey,
22 __in_z LPCWSTR sczRelatedBundleId,
23 __in BURN_REGISTRATION* pRegistration,
@@ -47,13 +47,11 @@ extern "C" HRESULT RelatedBundlesInitializeForScope(
47 {
48 HRESULT hr = S_OK;
49
50 - hr = InitializeForScopeAndBitness(fPerMachine, /*fWow6432*/FALSE, pRegistration, pRelatedBundles);
51 - ExitOnFailure(hr, "Failed to open platform-native uninstall registry key.");
52 -
53 -#if defined(_WIN64)
54 - hr = InitializeForScopeAndBitness(fPerMachine, /*fWow6432*/TRUE, pRegistration, pRelatedBundles);
50 + hr = InitializeForScopeAndBitness(fPerMachine, REG_KEY_32BIT, pRegistration, pRelatedBundles);
51 ExitOnFailure(hr, "Failed to open 32-bit uninstall registry key.");
56 -#endif
52 +
53 + hr = InitializeForScopeAndBitness(fPerMachine, REG_KEY_64BIT, pRegistration, pRelatedBundles);
54 + ExitOnFailure(hr, "Failed to open 64-bit uninstall registry key.");
55
56 LExit:
57 return hr;
@@ -170,7 +168,7 @@ static __callback int __cdecl CompareRelatedBundles(
168
169 static HRESULT InitializeForScopeAndBitness(
170 __in BOOL fPerMachine,
173 - __in BOOL fWow6432,
171 + __in REG_KEY_BITNESS regBitness,
172 __in BURN_REGISTRATION * pRegistration,
173 __in BURN_RELATED_BUNDLES * pRelatedBundles
174 )
@@ -180,7 +178,7 @@ static HRESULT InitializeForScopeAndBitness(
178 HKEY hkUninstallKey = NULL;
179 LPWSTR sczRelatedBundleId = NULL;
180
183 - hr = RegOpen(hkRoot, BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ | (fWow6432 ? KEY_WOW64_32KEY : 0), &hkUninstallKey);
181 + hr = RegOpenEx(hkRoot, BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, regBitness, &hkUninstallKey);
182 if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
183 {
184 ExitFunction1(hr = S_OK);
@@ -202,7 +200,7 @@ static HRESULT InitializeForScopeAndBitness(
200 {
201 // Ignore failures here since we'll often find products that aren't actually
202 // related bundles (or even bundles at all).
205 - HRESULT hrRelatedBundle = LoadIfRelatedBundle(fPerMachine, fWow6432, hkUninstallKey, sczRelatedBundleId, pRegistration, pRelatedBundles);
203 + HRESULT hrRelatedBundle = LoadIfRelatedBundle(fPerMachine, regBitness, hkUninstallKey, sczRelatedBundleId, pRegistration, pRelatedBundles);
204 UNREFERENCED_PARAMETER(hrRelatedBundle);
205 }
206 }
@@ -216,7 +214,7 @@ LExit:
214
215 static HRESULT LoadIfRelatedBundle(
216 __in BOOL fPerMachine,
219 - __in BOOL fWow6432,
217 + __in REG_KEY_BITNESS regBitness,
218 __in HKEY hkUninstallKey,
219 __in_z LPCWSTR sczRelatedBundleId,
220 __in BURN_REGISTRATION* pRegistration,
@@ -227,7 +225,7 @@ static HRESULT LoadIfRelatedBundle(
225 HKEY hkBundleId = NULL;
226 BOOTSTRAPPER_RELATION_TYPE relationType = BOOTSTRAPPER_RELATION_NONE;
227
230 - hr = RegOpen(hkUninstallKey, sczRelatedBundleId, KEY_READ | (fWow6432 ? KEY_WOW64_32KEY : 0), &hkBundleId);
228 + hr = RegOpenEx(hkUninstallKey, sczRelatedBundleId, KEY_READ, regBitness, &hkBundleId);
229 ExitOnFailure(hr, "Failed to open uninstall key for potential related bundle: %ls", sczRelatedBundleId);
230
231 hr = DetermineRelationType(hkBundleId, pRegistration, &relationType);
src/burn/engine/search.cpp
+2 -14
@@ -836,19 +836,13 @@ static HRESULT RegistrySearchExists(
836 HKEY hKey = NULL;
837 DWORD dwType = 0;
838 BOOL fExists = FALSE;
839 - REGSAM samDesired = KEY_QUERY_VALUE;
840 -
841 - if (pSearch->RegistrySearch.fWin64)
842 - {
843 - samDesired = samDesired | KEY_WOW64_64KEY;
844 - }
839
840 // format key string
841 hr = VariableFormatString(pVariables, pSearch->RegistrySearch.sczKey, &sczKey, NULL);
842 ExitOnFailure(hr, "Failed to format key string.");
843
844 // open key
851 - hr = RegOpen(pSearch->RegistrySearch.hRoot, sczKey, samDesired, &hKey);
845 + hr = RegOpenEx(pSearch->RegistrySearch.hRoot, sczKey, KEY_QUERY_VALUE, pSearch->RegistrySearch.fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey);
846 if (SUCCEEDED(hr))
847 {
848 fExists = TRUE;
@@ -922,12 +916,6 @@ static HRESULT RegistrySearchValue(
916 LPBYTE pData = NULL;
917 DWORD cch = 0;
918 BURN_VARIANT value = { };
925 - REGSAM samDesired = KEY_QUERY_VALUE;
926 -
927 - if (pSearch->RegistrySearch.fWin64)
928 - {
929 - samDesired = samDesired | KEY_WOW64_64KEY;
930 - }
919
920 // format key string
921 hr = VariableFormatString(pVariables, pSearch->RegistrySearch.sczKey, &sczKey, NULL);
@@ -941,7 +929,7 @@ static HRESULT RegistrySearchValue(
929 }
930
931 // open key
944 - hr = RegOpen(pSearch->RegistrySearch.hRoot, sczKey, samDesired, &hKey);
932 + hr = RegOpenEx(pSearch->RegistrySearch.hRoot, sczKey, KEY_QUERY_VALUE, pSearch->RegistrySearch.fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey);
933 if (E_FILENOTFOUND == hr)
934 {
935 // What if there is a hidden variable in sczKey?
src/burn/engine/variable.cpp
+1 -1
@@ -2361,7 +2361,7 @@ static HRESULT Get64bitFolderFromRegistry(
2361 AssertSz(CSIDL_PROGRAM_FILES == nFolder || CSIDL_PROGRAM_FILES_COMMON == nFolder, "Unknown folder CSIDL.");
2362 LPCWSTR wzFolderValue = CSIDL_PROGRAM_FILES_COMMON == nFolder ? L"CommonFilesDir" : L"ProgramFilesDir";
2363
2364 - hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", KEY_READ | KEY_WOW64_64KEY, &hkFolders);
2364 + hr = RegOpenEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", KEY_READ, REG_KEY_64BIT, &hkFolders);
2365 ExitOnFailure(hr, "Failed to open Windows folder key.");
2366
2367 hr = RegReadString(hkFolders, wzFolderValue, psczPath);
src/burn/test/BurnUnitTest/RegistrationTest.cpp
+1 -1
@@ -645,7 +645,7 @@ namespace Bootstrapper
645 NativeAssert::Succeeded(hr, "Failed to allocate buffer for related bundle id.");
646
647 // Verify we can find ourself via the UpgradeCode
648 - hr = BundleEnumRelatedBundleFixed(TEST_BUNDLE_UPGRADE_CODE, BUNDLE_INSTALL_CONTEXT_USER, &dwRelatedBundleIndex, sczRelatedBundleId);
648 + hr = BundleEnumRelatedBundleFixed(TEST_BUNDLE_UPGRADE_CODE, BUNDLE_INSTALL_CONTEXT_USER, REG_KEY_DEFAULT, &dwRelatedBundleIndex, sczRelatedBundleId);
649 TestThrowOnFailure(hr, L"Failed to enumerate related bundle.");
650
651 NativeAssert::StringEqual(TEST_BUNDLE_ID, sczRelatedBundleId);
src/libs/dutil/WixToolset.DUtil/butil.cpp
+100 -132
@@ -63,13 +63,6 @@ static HRESULT CopyStringToBuffer(
63 __in_z_opt LPWSTR wzBuffer,
64 __inout SIZE_T* pcchBuffer
65 );
66 -static HRESULT DoBundleEnumRelatedBundle(
67 - __in HKEY hkRoot,
68 - __in REG_KEY_BITNESS kbKeyBitness,
69 - __in_z LPCWSTR wzUpgradeCode,
70 - __inout PDWORD pdwStartIndex,
71 - __deref_out_z LPWSTR* psczBundleId
72 - );
66
67
68 DAPI_(HRESULT) BundleGetBundleInfo(
@@ -156,11 +149,21 @@ LExit:
149 DAPI_(HRESULT) BundleEnumRelatedBundle(
150 __in_z LPCWSTR wzUpgradeCode,
151 __in BUNDLE_INSTALL_CONTEXT context,
152 + __in REG_KEY_BITNESS kbKeyBitness,
153 __inout PDWORD pdwStartIndex,
154 __deref_out_z LPWSTR* psczBundleId
155 )
156 {
157 HRESULT hr = S_OK;
158 + BOOL fUpgradeCodeFound = FALSE;
159 + HKEY hkUninstall = NULL;
160 + HKEY hkBundle = NULL;
161 + LPWSTR sczUninstallSubKey = NULL;
162 + LPWSTR sczUninstallSubKeyPath = NULL;
163 + LPWSTR sczValue = NULL;
164 + DWORD dwType = 0;
165 + LPWSTR* rgsczBundleUpgradeCodes = NULL;
166 + DWORD cBundleUpgradeCodes = 0;
167 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
168
169 if (!wzUpgradeCode || !pdwStartIndex)
@@ -168,27 +171,105 @@ DAPI_(HRESULT) BundleEnumRelatedBundle(
171 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function.");
172 }
173
171 - hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_DEFAULT, wzUpgradeCode, pdwStartIndex, psczBundleId);
172 - ButilExitOnFailure(hr, "Failed to enumerate default-bitness bundles.");
173 - if (S_FALSE == hr)
174 + hr = RegOpenEx(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, kbKeyBitness, &hkUninstall);
175 + ButilExitOnFailure(hr, "Failed to open bundle uninstall key path.");
176 +
177 + for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++)
178 {
175 -#if defined(_WIN64)
176 - hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_32BIT, wzUpgradeCode, pdwStartIndex, psczBundleId);
177 - ButilExitOnFailure(hr, "Failed to enumerate 32-bit bundles.");
178 -#else
179 - hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_64BIT, wzUpgradeCode, pdwStartIndex, psczBundleId);
180 - ButilExitOnFailure(hr, "Failed to enumerate 64-bit bundles.");
181 -#endif
179 + hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey);
180 + ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path.");
181 +
182 + hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey);
183 + ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path.");
184 +
185 + hr = RegOpenEx(hkRoot, sczUninstallSubKeyPath, KEY_READ, kbKeyBitness, &hkBundle);
186 + ButilExitOnFailure(hr, "Failed to open uninstall key path.");
187 +
188 + // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ
189 + hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType);
190 + if (FAILED(hr))
191 + {
192 + ReleaseRegKey(hkBundle);
193 + ReleaseNullStr(sczUninstallSubKey);
194 + ReleaseNullStr(sczUninstallSubKeyPath);
195 + // Not a bundle
196 + continue;
197 + }
198 +
199 + switch (dwType)
200 + {
201 + case REG_SZ:
202 + hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue);
203 + ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property.");
204 +
205 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1))
206 + {
207 + *pdwStartIndex = dwIndex;
208 + fUpgradeCodeFound = TRUE;
209 + break;
210 + }
211 +
212 + ReleaseNullStr(sczValue);
213 +
214 + break;
215 + case REG_MULTI_SZ:
216 + hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes);
217 + ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property.");
218 +
219 + for (DWORD i = 0; i < cBundleUpgradeCodes; i++)
220 + {
221 + LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i];
222 + if (wzBundleUpgradeCode && *wzBundleUpgradeCode)
223 + {
224 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1))
225 + {
226 + *pdwStartIndex = dwIndex;
227 + fUpgradeCodeFound = TRUE;
228 + break;
229 + }
230 + }
231 + }
232 + ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
233 +
234 + break;
235 +
236 + default:
237 + ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType);
238 + }
239 +
240 + if (fUpgradeCodeFound)
241 + {
242 + if (psczBundleId)
243 + {
244 + *psczBundleId = sczUninstallSubKey;
245 + sczUninstallSubKey = NULL;
246 + }
247 +
248 + break;
249 + }
250 +
251 + // Cleanup before next iteration
252 + ReleaseRegKey(hkBundle);
253 + ReleaseNullStr(sczUninstallSubKey);
254 + ReleaseNullStr(sczUninstallSubKeyPath);
255 }
256
257 LExit:
185 - return hr;
258 + ReleaseStr(sczValue);
259 + ReleaseStr(sczUninstallSubKey);
260 + ReleaseStr(sczUninstallSubKeyPath);
261 + ReleaseRegKey(hkBundle);
262 + ReleaseRegKey(hkUninstall);
263 + ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
264 +
265 + return FAILED(hr) ? hr : fUpgradeCodeFound ? S_OK : S_FALSE;
266 }
267
268
269 DAPI_(HRESULT) BundleEnumRelatedBundleFixed(
270 __in_z LPCWSTR wzUpgradeCode,
271 __in BUNDLE_INSTALL_CONTEXT context,
272 + __in REG_KEY_BITNESS kbKeyBitness,
273 __inout PDWORD pdwStartIndex,
274 __out_ecount(MAX_GUID_CHARS+1) LPWSTR wzBundleId
275 )
@@ -197,7 +278,7 @@ DAPI_(HRESULT) BundleEnumRelatedBundleFixed(
278 LPWSTR sczValue = NULL;
279 size_t cchValue = 0;
280
200 - hr = BundleEnumRelatedBundle(wzUpgradeCode, context, pdwStartIndex, &sczValue);
281 + hr = BundleEnumRelatedBundle(wzUpgradeCode, context, kbKeyBitness, pdwStartIndex, &sczValue);
282 if (S_OK == hr && wzBundleId)
283 {
284 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchValue);
@@ -396,116 +477,3 @@ static HRESULT CopyStringToBuffer(
477
478 return hr;
479 }
399 -
400 -static HRESULT DoBundleEnumRelatedBundle(
401 - __in HKEY hkRoot,
402 - __in REG_KEY_BITNESS kbKeyBitness,
403 - __in_z LPCWSTR wzUpgradeCode,
404 - __inout PDWORD pdwStartIndex,
405 - __deref_out_z LPWSTR* psczBundleId
406 -)
407 -{
408 - HRESULT hr = S_OK;
409 - BOOL fUpgradeCodeFound = FALSE;
410 - HKEY hkUninstall = NULL;
411 - HKEY hkBundle = NULL;
412 - LPWSTR sczUninstallSubKey = NULL;
413 - LPWSTR sczUninstallSubKeyPath = NULL;
414 - LPWSTR sczValue = NULL;
415 - DWORD dwType = 0;
416 - LPWSTR* rgsczBundleUpgradeCodes = NULL;
417 - DWORD cBundleUpgradeCodes = 0;
418 -
419 - hr = RegOpenEx(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, kbKeyBitness, &hkUninstall);
420 - ButilExitOnFailure(hr, "Failed to open bundle uninstall key path.");
421 -
422 - for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++)
423 - {
424 - hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey);
425 - ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path.");
426 -
427 - hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey);
428 - ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path.");
429 -
430 - hr = RegOpenEx(hkRoot, sczUninstallSubKeyPath, KEY_READ, kbKeyBitness, &hkBundle);
431 - ButilExitOnFailure(hr, "Failed to open uninstall key path.");
432 -
433 - // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ
434 - hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType);
435 - if (FAILED(hr))
436 - {
437 - ReleaseRegKey(hkBundle);
438 - ReleaseNullStr(sczUninstallSubKey);
439 - ReleaseNullStr(sczUninstallSubKeyPath);
440 - // Not a bundle
441 - continue;
442 - }
443 -
444 - switch (dwType)
445 - {
446 - case REG_SZ:
447 - hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue);
448 - ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property.");
449 -
450 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1))
451 - {
452 - *pdwStartIndex = dwIndex;
453 - fUpgradeCodeFound = TRUE;
454 - break;
455 - }
456 -
457 - ReleaseNullStr(sczValue);
458 -
459 - break;
460 - case REG_MULTI_SZ:
461 - hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes);
462 - ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property.");
463 -
464 - for (DWORD i = 0; i < cBundleUpgradeCodes; i++)
465 - {
466 - LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i];
467 - if (wzBundleUpgradeCode && *wzBundleUpgradeCode)
468 - {
469 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1))
470 - {
471 - *pdwStartIndex = dwIndex;
472 - fUpgradeCodeFound = TRUE;
473 - break;
474 - }
475 - }
476 - }
477 - ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
478 -
479 - break;
480 -
481 - default:
482 - ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType);
483 - }
484 -
485 - if (fUpgradeCodeFound)
486 - {
487 - if (psczBundleId)
488 - {
489 - *psczBundleId = sczUninstallSubKey;
490 - sczUninstallSubKey = NULL;
491 - }
492 -
493 - break;
494 - }
495 -
496 - // Cleanup before next iteration
497 - ReleaseRegKey(hkBundle);
498 - ReleaseNullStr(sczUninstallSubKey);
499 - ReleaseNullStr(sczUninstallSubKeyPath);
500 - }
501 -
502 -LExit:
503 - ReleaseStr(sczValue);
504 - ReleaseStr(sczUninstallSubKey);
505 - ReleaseStr(sczUninstallSubKeyPath);
506 - ReleaseRegKey(hkBundle);
507 - ReleaseRegKey(hkUninstall);
508 - ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
509 -
510 - return FAILED(hr) ? hr : fUpgradeCodeFound ? S_OK : S_FALSE;
511 -}
src/libs/dutil/WixToolset.DUtil/inc/butil.h
+6 -1
@@ -60,7 +60,9 @@ HRESULT DAPI BundleGetBundleInfoFixed(
60 );
61
62 /********************************************************************
63 -BundleEnumRelatedBundle - Queries the bundle installation metadata for installs with the given upgrade code
63 +BundleEnumRelatedBundle - Queries the bundle installation metadata for installs with the given upgrade code.
64 +Enumerate 32-bit and 64-bit in two passes.
65 +
66 RETURNS:
67 E_INVALIDARG
68 An invalid parameter was passed to the function.
@@ -74,12 +76,14 @@ RETURNS:
76 HRESULT DAPI BundleEnumRelatedBundle(
77 __in_z LPCWSTR wzUpgradeCode,
78 __in BUNDLE_INSTALL_CONTEXT context,
79 + __in REG_KEY_BITNESS kbKeyBitness,
80 __inout PDWORD pdwStartIndex,
81 __deref_out_z LPWSTR* psczBundleId
82 );
83
84 /********************************************************************
85 BundleEnumRelatedBundleFixed - Queries the bundle installation metadata for installs with the given upgrade code
86 +Enumerate 32-bit and 64-bit in two passes.
87
88 NOTE: lpBundleIdBuff is a buffer to receive the bundle GUID. This buffer must be 39 characters long.
89 The first 38 characters are for the GUID, and the last character is for the terminating null character.
@@ -96,6 +100,7 @@ RETURNS:
100 HRESULT DAPI BundleEnumRelatedBundleFixed(
101 __in_z LPCWSTR wzUpgradeCode,
102 __in BUNDLE_INSTALL_CONTEXT context,
103 + __in REG_KEY_BITNESS kbKeyBitness,
104 __inout PDWORD pdwStartIndex,
105 __out_ecount(MAX_GUID_CHARS+1) LPWSTR wzBundleId
106 );
src/libs/dutil/WixToolset.DUtil/inc/regutil.h
+9
@@ -408,6 +408,15 @@ BOOL DAPI RegValueExists(
408 __in REG_KEY_BITNESS kbKeyBitness
409 );
410
411 +/********************************************************************
412 +RegTranslateKeyBitness - Converts from REG_KEY_BITNESS values to
413 +REGSAM-compatible values.
414 +
415 +*********************************************************************/
416 +REGSAM DAPI RegTranslateKeyBitness(
417 + __in REG_KEY_BITNESS kbKeyBitness
418 + );
419 +
420 #ifdef __cplusplus
421 }
422 #endif
src/libs/dutil/WixToolset.DUtil/monutil.cpp
+1 -12
@@ -1677,18 +1677,7 @@ static REGSAM GetRegKeyBitness(
1677 __in MON_REQUEST *pRequest
1678 )
1679 {
1680 - if (REG_KEY_32BIT == pRequest->regkey.kbKeyBitness)
1681 - {
1682 - return KEY_WOW64_32KEY;
1683 - }
1684 - else if (REG_KEY_64BIT == pRequest->regkey.kbKeyBitness)
1685 - {
1686 - return KEY_WOW64_64KEY;
1687 - }
1688 - else
1689 - {
1690 - return 0;
1691 - }
1680 + return RegTranslateKeyBitness(pRequest->regkey.kbKeyBitness);
1681 }
1682
1683 static HRESULT DuplicateRemoveMessage(
src/libs/dutil/WixToolset.DUtil/precomp.h
+1 -1
@@ -48,7 +48,6 @@
48 #include "apputil.h"
49 #include "atomutil.h"
50 #include "buffutil.h"
51 -#include "butil.h"
51 #include "cabcutil.h"
52 #include "cabutil.h"
53 #include "conutil.h"
@@ -76,6 +75,7 @@
75 #include "polcutil.h"
76 #include "procutil.h"
77 #include "regutil.h"
78 +#include "butil.h" // NOTE: Butil must come after Regutil.
79 #include "resrutil.h"
80 #include "reswutil.h"
81 #include "rmutil.h"
src/libs/dutil/WixToolset.DUtil/regutil.cpp
+4 -15
@@ -32,9 +32,6 @@ static PFN_REGDELETEVALUEW vpfnRegDeleteValueW = ::RegDeleteValueW;
32 static HMODULE vhAdvApi32Dll = NULL;
33 static BOOL vfRegInitialized = FALSE;
34
35 -static REGSAM TranslateKeyBitness(
36 - __in REG_KEY_BITNESS kbKeyBitness
37 -);
35 static HRESULT WriteStringToRegistry(
36 __in HKEY hk,
37 __in_z_opt LPCWSTR wzName,
@@ -135,7 +132,7 @@ DAPI_(HRESULT) RegCreateEx(
132 DWORD er = ERROR_SUCCESS;
133 DWORD dwDisposition;
134
138 - REGSAM samDesired = TranslateKeyBitness(kbKeyBitness);
135 + REGSAM samDesired = RegTranslateKeyBitness(kbKeyBitness);
136 er = vpfnRegCreateKeyExW(hkRoot, wzSubKey, 0, NULL, fVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE, dwAccess | samDesired, pSecurityAttributes, phk, &dwDisposition);
137 RegExitOnWin32Error(er, hr, "Failed to create registry key.");
138
@@ -171,7 +168,7 @@ DAPI_(HRESULT) RegOpenEx(
168 HRESULT hr = S_OK;
169 DWORD er = ERROR_SUCCESS;
170
174 - REGSAM samDesired = TranslateKeyBitness(kbKeyBitness);
171 + REGSAM samDesired = RegTranslateKeyBitness(kbKeyBitness);
172 er = vpfnRegOpenKeyExW(hkRoot, wzSubKey, 0, dwAccess | samDesired, phk);
173 if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er))
174 {
@@ -229,7 +226,7 @@ DAPI_(HRESULT) RegDelete(
226
227 if (NULL != vpfnRegDeleteKeyExW)
228 {
232 - REGSAM samDesired = TranslateKeyBitness(kbKeyBitness);
229 + REGSAM samDesired = RegTranslateKeyBitness(kbKeyBitness);
230 er = vpfnRegDeleteKeyExW(hkRoot, wzSubKey, samDesired, 0);
231 if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er))
232 {
@@ -912,11 +909,6 @@ LExit:
909 return hr;
910 }
911
915 -/********************************************************************
916 -RegValueExists - determines whether a named value exists in a
917 -specified subkey.
918 -
919 -*********************************************************************/
912 DAPI_(BOOL) RegValueExists(
913 __in HKEY hk,
914 __in_z LPCWSTR wzSubKey,
@@ -940,7 +932,7 @@ LExit:
932 return SUCCEEDED(hr);
933 }
934
943 -static REGSAM TranslateKeyBitness(
935 +DAPI_(REGSAM) RegTranslateKeyBitness(
936 __in REG_KEY_BITNESS kbKeyBitness
937 )
938 {
@@ -948,14 +940,11 @@ static REGSAM TranslateKeyBitness(
940 {
941 case REG_KEY_32BIT:
942 return KEY_WOW64_32KEY;
951 - break;
943 case REG_KEY_64BIT:
944 return KEY_WOW64_64KEY;
954 - break;
945 case REG_KEY_DEFAULT:
946 default:
947 return 0;
958 - break;
948 }
949 }
950
src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wixproj new
+16
@@ -0,0 +1,16 @@
1 +<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2 +<Project Sdk="WixToolset.Sdk">
3 + <Import Project="..\BundleAv1\BundleA.props" />
4 + <PropertyGroup>
5 + <BA>TestBA_x64</BA>
6 + <InstallerPlatform>X64</InstallerPlatform>
7 + </PropertyGroup>
8 + <ItemGroup>
9 + <ProjectReference Include="..\PackageAv1\PackageAv1.wixproj" />
10 + <ProjectReference Include="..\..\TestBA\TestBAWixlib_x64\testbawixlib_x64.wixproj" />
11 + </ItemGroup>
12 + <ItemGroup>
13 + <PackageReference Include="WixToolset.Bal.wixext" />
14 + <PackageReference Include="WixToolset.NetFx.wixext" />
15 + </ItemGroup>
16 +</Project>
\ No newline at end of file
src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv1x64/BundleAv1x64.wxs new
+10
@@ -0,0 +1,10 @@
1 +<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2 +
3 +
4 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
5 + <Fragment>
6 + <PackageGroup Id="BundlePackages">
7 + <MsiPackage Id="PackageA" SourceFile="$(var.PackageAv1.TargetPath)" />
8 + </PackageGroup>
9 + </Fragment>
10 +</Wix>
src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs
+17
@@ -49,5 +49,22 @@ namespace WixToolsetTest.BurnE2E
49
50 bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache();
51 }
52 +
53 + [Fact]
54 + public void Bundle32UpgradesBundle64()
55 + {
56 + var packageAv1 = this.CreatePackageInstaller("PackageAv1");
57 + var packageAv2 = this.CreatePackageInstaller("PackageAv2");
58 + var bundleAv1x64 = this.CreateBundleInstaller("BundleAv1x64");
59 + var bundleAv2 = this.CreateBundleInstaller("BundleAv2");
60 +
61 + bundleAv1x64.Install();
62 + bundleAv1x64.VerifyRegisteredAndInPackageCache();
63 +
64 + bundleAv2.Install();
65 + bundleAv2.VerifyRegisteredAndInPackageCache();
66 +
67 + bundleAv1x64.VerifyUnregisteredAndRemovedFromPackageCache();
68 + }
69 }
70 }