@joebigelow / wix / commits / b152761d

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");