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
}