From c2b00d75493798d9f2452d5e5014b14afcb14889 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 5 Jan 2022 21:51:00 -0600 Subject: Always run upgrade related bundles last. #5128 --- src/burn/engine/registration.cpp | 2 ++ src/burn/engine/relatedbundle.cpp | 55 +++++++++++++++++++++++++++++++++++++++ src/burn/engine/relatedbundle.h | 3 +++ 3 files changed, 60 insertions(+) (limited to 'src/burn') diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp index 9cc4b199..ffeb39d1 100644 --- a/src/burn/engine/registration.cpp +++ b/src/burn/engine/registration.cpp @@ -585,6 +585,8 @@ extern "C" HRESULT RegistrationDetectRelatedBundles( hr = RelatedBundlesInitializeForScope(FALSE, pRegistration, &pRegistration->relatedBundles); ExitOnFailure(hr, "Failed to initialize per-user related bundles."); + RelatedBundlesSort(&pRegistration->relatedBundles); + LExit: return hr; } diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp index e2380aab..1eafef07 100644 --- a/src/burn/engine/relatedbundle.cpp +++ b/src/burn/engine/relatedbundle.cpp @@ -4,6 +4,11 @@ // internal function declarations +static __callback int __cdecl CompareRelatedBundles( + __in void* pvContext, + __in const void* pvLeft, + __in const void* pvRight + ); static HRESULT LoadIfRelatedBundle( __in BOOL fPerMachine, __in HKEY hkUninstallKey, @@ -128,9 +133,59 @@ LExit: return hr; } +extern "C" void RelatedBundlesSort( + __in BURN_RELATED_BUNDLES* pRelatedBundles + ) +{ + qsort_s(pRelatedBundles->rgRelatedBundles, pRelatedBundles->cRelatedBundles, sizeof(BURN_RELATED_BUNDLE), CompareRelatedBundles, NULL); +} + // internal helper functions +static __callback int __cdecl CompareRelatedBundles( + __in void* /*pvContext*/, + __in const void* pvLeft, + __in const void* pvRight + ) +{ + int ret = 0; + const BURN_RELATED_BUNDLE* pBundleLeft = static_cast(pvLeft); + const BURN_RELATED_BUNDLE* pBundleRight = static_cast(pvRight); + + // Sort by relation type, then version, then bundle id. + if (pBundleLeft->relationType != pBundleRight->relationType) + { + // Upgrade bundles last, everything else according to the enum. + if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleLeft->relationType) + { + ret = 1; + } + else if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleRight->relationType) + { + ret = -1; + } + else if (pBundleLeft->relationType < pBundleRight->relationType) + { + ret = -1; + } + else + { + ret = 1; + } + } + else + { + VerCompareParsedVersions(pBundleLeft->pVersion, pBundleRight->pVersion, &ret); + if (0 == ret) + { + ret = ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pBundleLeft->package.sczId, -1, pBundleRight->package.sczId, -1) - 2; + } + } + + return ret; +} + static HRESULT LoadIfRelatedBundle( __in BOOL fPerMachine, __in HKEY hkUninstallKey, diff --git a/src/burn/engine/relatedbundle.h b/src/burn/engine/relatedbundle.h index 0113c8ee..be039421 100644 --- a/src/burn/engine/relatedbundle.h +++ b/src/burn/engine/relatedbundle.h @@ -19,6 +19,9 @@ HRESULT RelatedBundleFindById( __in_z LPCWSTR wzId, __out BURN_RELATED_BUNDLE** ppRelatedBundle ); +void RelatedBundlesSort( + __in BURN_RELATED_BUNDLES* pRelatedBundles + ); #if defined(__cplusplus) } -- cgit v1.2.3-55-g6feb