@joebigelow / wix-1 / commits / bae756f4

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 }