Remove orphan package providers when unregistering the bundle.
Fixes #3850
Sean Hall committed
Jan 31, 2022 at 15:44 UTC
b152761dfddc0a131dcd13f70ae0e9b9e41b37fe
4 files changed
+60
-15
src/burn/engine/dependency.cpp
+53
-8
@@ -77,6 +77,9 @@ static void UnregisterPackageDependency(
77
__in const BURN_PACKAGE* pPackage,
78
__in_z LPCWSTR wzDependentProviderKey
79
);
80
+static void UnregisterOrphanPackageProviders(
81
+ __in const BURN_PACKAGE* pPackage
82
+ );
83
84
85
// functions
@@ -734,15 +737,19 @@ extern "C" void DependencyUnregisterBundle(
737
HRESULT hr = S_OK;
738
LPCWSTR wzDependentProviderKey = pRegistration->sczId;
739
737
- // Remove the bundle provider key.
738
- hr = DepUnregisterDependency(pRegistration->hkRoot, pRegistration->sczProviderKey);
739
- if (SUCCEEDED(hr))
740
- {
741
- LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_UNREGISTERED, pRegistration->sczProviderKey);
742
- }
743
- else if (FAILED(hr) && E_FILENOTFOUND != hr)
740
+ // If we own the bundle dependency then remove it.
741
+ if (!pRegistration->fDetectedForeignProviderKeyBundleId)
742
{
745
- LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_UNREGISTERED_FAILED, pRegistration->sczProviderKey, hr);
743
+ // Remove the bundle provider key.
744
+ hr = DepUnregisterDependency(pRegistration->hkRoot, pRegistration->sczProviderKey);
745
+ if (SUCCEEDED(hr))
746
+ {
747
+ LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_UNREGISTERED, pRegistration->sczProviderKey);
748
+ }
749
+ else if (FAILED(hr) && E_FILENOTFOUND != hr)
750
+ {
751
+ LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_UNREGISTERED_FAILED, pRegistration->sczProviderKey, hr);
752
+ }
753
}
754
755
// Best effort to make sure this bundle is not registered as a dependent for anything.
@@ -757,6 +764,13 @@ extern "C" void DependencyUnregisterBundle(
764
const BURN_PACKAGE* pPackage = &pRegistration->relatedBundles.rgRelatedBundles[i].package;
765
UnregisterPackageDependency(pPackage->fPerMachine, pPackage, wzDependentProviderKey);
766
}
767
+
768
+ // Best effort to make sure package providers are removed if unused.
769
+ for (DWORD i = 0; i < pPackages->cPackages; ++i)
770
+ {
771
+ const BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
772
+ UnregisterOrphanPackageProviders(pPackage);
773
+ }
774
}
775
776
extern "C" HRESULT DependencyDetectCompatibleEntry(
@@ -1431,3 +1445,34 @@ static void UnregisterPackageDependency(
1445
}
1446
}
1447
}
1448
+
1449
+static void UnregisterOrphanPackageProviders(
1450
+ __in const BURN_PACKAGE* pPackage
1451
+ )
1452
+{
1453
+ HRESULT hr = S_OK;
1454
+ DEPENDENCY* rgDependents = NULL;
1455
+ UINT cDependents = 0;
1456
+ HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1457
+
1458
+ for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
1459
+ {
1460
+ const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];
1461
+
1462
+ // Skip providers not owned by the bundle.
1463
+ if (pProvider->fImported)
1464
+ {
1465
+ continue;
1466
+ }
1467
+
1468
+ hr = DepCheckDependents(hkRoot, pProvider->sczKey, 0, NULL, &rgDependents, &cDependents);
1469
+ if (SUCCEEDED(hr) && !cDependents)
1470
+ {
1471
+ UnregisterPackageProvider(pProvider, pPackage->sczId, hkRoot);
1472
+ }
1473
+
1474
+ ReleaseDependencyArray(rgDependents, cDependents);
1475
+ rgDependents = NULL;
1476
+ cDependents = 0;
1477
+ }
1478
+}
src/burn/engine/registration.cpp
+2
-6
@@ -900,12 +900,8 @@ extern "C" HRESULT RegistrationSessionEnd(
900
{
901
AssertSz(BOOTSTRAPPER_REGISTRATION_TYPE_NONE == registrationType, "Registration type must be NONE if resume mode is NONE");
902
903
- // If we own the bundle dependency then remove it.
904
- if (!pRegistration->fDetectedForeignProviderKeyBundleId)
905
- {
906
- // Remove the bundle dependency key.
907
- DependencyUnregisterBundle(pRegistration, pPackages);
908
- }
903
+ // Remove the bundle dependencies.
904
+ DependencyUnregisterBundle(pRegistration, pPackages);
905
906
// Delete update registration key.
907
if (pRegistration->update.fRegisterUpdate)
src/ext/Dependency/ca/wixdepca.cpp
+4
@@ -338,6 +338,10 @@ static HRESULT EnsureAbsentDependents(
338
339
// Check the registry to see if the provider has any dependents registered.
340
hr = DepCheckDependents(hkHive, sczProviderKey, iAttributes, sdIgnoredDependents, &rgDependents, &cDependents);
341
+ if (E_FILENOTFOUND == hr)
342
+ {
343
+ hr = S_OK;
344
+ }
345
ExitOnFailure(hr, "Failed dependents check for %ls.", sczId);
346
}
347
src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
+1
-1
@@ -857,7 +857,7 @@ namespace WixToolsetTest.BurnE2E
857
bundleA.VerifyExeTestRegistryRootDeleted(testRegistryValueExe);
858
}
859
860
- [Fact(Skip = "https://github.com/wixtoolset/issues/issues/3850")]
860
+ [Fact]
861
public void RemovesDependencyProviderFromUpgradedPackageDuringUninstall()
862
{
863
var packageC = this.CreatePackageInstaller("PackageC");