Handle 32-bit related-bundle registration...
...from 64-bit bundles.
Bob Arnson committed
Jan 3, 2022 at 22:36 UTC
bae756f4354fed4de6097c931590ccafc907fdb2
4 files changed
+105
-32
src/burn/engine/relatedbundle.cpp
+61
-32
@@ -8,9 +8,16 @@ static __callback int __cdecl CompareRelatedBundles(
8
__in void* pvContext,
9
__in const void* pvLeft,
10
__in const void* pvRight
11
+);
12
+static HRESULT InitializeForScopeAndBitness(
13
+ __in BOOL fPerMachine,
14
+ __in BOOL fWow6432,
15
+ __in BURN_REGISTRATION* pRegistration,
16
+ __in BURN_RELATED_BUNDLES* pRelatedBundles
17
);
18
static HRESULT LoadIfRelatedBundle(
19
__in BOOL fPerMachine,
20
+ __in BOOL fWow6432,
21
__in HKEY hkUninstallKey,
22
__in_z LPCWSTR sczRelatedBundleId,
23
__in BURN_REGISTRATION* pRegistration,
@@ -39,41 +46,16 @@ extern "C" HRESULT RelatedBundlesInitializeForScope(
46
)
47
{
48
HRESULT hr = S_OK;
42
- HKEY hkRoot = fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
43
- HKEY hkUninstallKey = NULL;
44
- LPWSTR sczRelatedBundleId = NULL;
45
-
46
- hr = RegOpen(hkRoot, BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, &hkUninstallKey);
47
- if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
48
- {
49
- ExitFunction1(hr = S_OK);
50
- }
51
- ExitOnFailure(hr, "Failed to open uninstall registry key.");
49
53
- for (DWORD dwIndex = 0; /* exit via break below */; ++dwIndex)
54
- {
55
- hr = RegKeyEnum(hkUninstallKey, dwIndex, &sczRelatedBundleId);
56
- if (E_NOMOREITEMS == hr)
57
- {
58
- hr = S_OK;
59
- break;
60
- }
61
- ExitOnFailure(hr, "Failed to enumerate uninstall key for related bundles.");
50
+ hr = InitializeForScopeAndBitness(fPerMachine, /*fWow6432*/FALSE, pRegistration, pRelatedBundles);
51
+ ExitOnFailure(hr, "Failed to open platform-native uninstall registry key.");
52
63
- // If we did not find our bundle id, try to load the subkey as a related bundle.
64
- if (CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczRelatedBundleId, -1, pRegistration->sczId, -1))
65
- {
66
- // Ignore failures here since we'll often find products that aren't actually
67
- // related bundles (or even bundles at all).
68
- HRESULT hrRelatedBundle = LoadIfRelatedBundle(fPerMachine, hkUninstallKey, sczRelatedBundleId, pRegistration, pRelatedBundles);
69
- UNREFERENCED_PARAMETER(hrRelatedBundle);
70
- }
71
- }
53
+#if defined(_WIN64)
54
+ hr = InitializeForScopeAndBitness(fPerMachine, /*fWow6432*/TRUE, pRegistration, pRelatedBundles);
55
+ ExitOnFailure(hr, "Failed to open 32-bit uninstall registry key.");
56
+#endif
57
58
LExit:
74
- ReleaseStr(sczRelatedBundleId);
75
- ReleaseRegKey(hkUninstallKey);
76
-
59
return hr;
60
}
61
@@ -186,8 +168,55 @@ static __callback int __cdecl CompareRelatedBundles(
168
return ret;
169
}
170
171
+static HRESULT InitializeForScopeAndBitness(
172
+ __in BOOL fPerMachine,
173
+ __in BOOL fWow6432,
174
+ __in BURN_REGISTRATION * pRegistration,
175
+ __in BURN_RELATED_BUNDLES * pRelatedBundles
176
+)
177
+{
178
+ HRESULT hr = S_OK;
179
+ HKEY hkRoot = fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
180
+ HKEY hkUninstallKey = NULL;
181
+ LPWSTR sczRelatedBundleId = NULL;
182
+
183
+ hr = RegOpen(hkRoot, BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ | (fWow6432 ? KEY_WOW64_32KEY : 0), &hkUninstallKey);
184
+ if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
185
+ {
186
+ ExitFunction1(hr = S_OK);
187
+ }
188
+ ExitOnFailure(hr, "Failed to open uninstall registry key.");
189
+
190
+ for (DWORD dwIndex = 0; /* exit via break below */; ++dwIndex)
191
+ {
192
+ hr = RegKeyEnum(hkUninstallKey, dwIndex, &sczRelatedBundleId);
193
+ if (E_NOMOREITEMS == hr)
194
+ {
195
+ hr = S_OK;
196
+ break;
197
+ }
198
+ ExitOnFailure(hr, "Failed to enumerate uninstall key for related bundles.");
199
+
200
+ // If we did not find our bundle id, try to load the subkey as a related bundle.
201
+ if (CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczRelatedBundleId, -1, pRegistration->sczId, -1))
202
+ {
203
+ // Ignore failures here since we'll often find products that aren't actually
204
+ // related bundles (or even bundles at all).
205
+ HRESULT hrRelatedBundle = LoadIfRelatedBundle(fPerMachine, fWow6432, hkUninstallKey, sczRelatedBundleId, pRegistration, pRelatedBundles);
206
+ UNREFERENCED_PARAMETER(hrRelatedBundle);
207
+ }
208
+ }
209
+
210
+LExit:
211
+ ReleaseStr(sczRelatedBundleId);
212
+ ReleaseRegKey(hkUninstallKey);
213
+
214
+ return hr;
215
+}
216
+
217
static HRESULT LoadIfRelatedBundle(
218
__in BOOL fPerMachine,
219
+ __in BOOL fWow6432,
220
__in HKEY hkUninstallKey,
221
__in_z LPCWSTR sczRelatedBundleId,
222
__in BURN_REGISTRATION* pRegistration,
@@ -198,7 +227,7 @@ static HRESULT LoadIfRelatedBundle(
227
HKEY hkBundleId = NULL;
228
BOOTSTRAPPER_RELATION_TYPE relationType = BOOTSTRAPPER_RELATION_NONE;
229
201
- hr = RegOpen(hkUninstallKey, sczRelatedBundleId, KEY_READ, &hkBundleId);
230
+ hr = RegOpen(hkUninstallKey, sczRelatedBundleId, KEY_READ | (fWow6432 ? KEY_WOW64_32KEY : 0), &hkBundleId);
231
ExitOnFailure(hr, "Failed to open uninstall key for potential related bundle: %ls", sczRelatedBundleId);
232
233
hr = DetermineRelationType(hkBundleId, pRegistration, &relationType);
src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv2x64/BundleAv2x64.wixproj
new
+17
@@ -0,0 +1,17 @@
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
+ <Version>2.0.0.0</Version>
8
+ </PropertyGroup>
9
+ <ItemGroup>
10
+ <ProjectReference Include="..\PackageAv2\PackageAv2.wixproj" />
11
+ <ProjectReference Include="..\..\TestBA\TestBAWixlib_x64\testbawixlib_x64.wixproj" />
12
+ </ItemGroup>
13
+ <ItemGroup>
14
+ <PackageReference Include="WixToolset.Bal.wixext" />
15
+ <PackageReference Include="WixToolset.NetFx.wixext" />
16
+ </ItemGroup>
17
+</Project>
\ No newline at end of file
src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv2x64/BundleAv2x64.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.PackageAv2.TargetPath)" />
8
+ </PackageGroup>
9
+ </Fragment>
10
+</Wix>
src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs
+17
@@ -32,5 +32,22 @@ namespace WixToolsetTest.BurnE2E
32
Assert.True(LogVerifier.MessageInLogFileRegex(bundleAv2InstallLogFilePath, @"OnDetectRelatedBundle\(\) - id: \{[0-9A-Za-z\-]{36}\}, missing from cache: True"));
33
Assert.True(LogVerifier.MessageInLogFileRegex(bundleAv2InstallLogFilePath, @"Detected related bundle: \{[0-9A-Za-z\-]{36}\}, type: Upgrade, scope: PerMachine, version: 1\.0\.0\.0, cached: No"));
34
}
35
+
36
+ [Fact]
37
+ public void Bundle64UpgradesBundle32()
38
+ {
39
+ var packageAv1 = this.CreatePackageInstaller("PackageAv1");
40
+ var packageAv2 = this.CreatePackageInstaller("PackageAv2");
41
+ var bundleAv1 = this.CreateBundleInstaller("BundleAv1");
42
+ var bundleAv2x64 = this.CreateBundleInstaller("BundleAv2x64");
43
+
44
+ bundleAv1.Install();
45
+ bundleAv1.VerifyRegisteredAndInPackageCache();
46
+
47
+ bundleAv2x64.Install();
48
+ bundleAv2x64.VerifyRegisteredAndInPackageCache();
49
+
50
+ bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache();
51
+ }
52
}
53
}