From e9a4f673511dd06a8209f3e4037ad20f153d6caa Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Tue, 30 Mar 2021 19:38:33 -0500 Subject: Skip bundle dependent checking when ignoring dependencies includes ALL. Fixes #6391. --- src/engine/dependency.cpp | 14 +++++-- src/engine/plan.cpp | 95 ++++++++++++++++++++++++----------------------- src/engine/plan.h | 1 + src/engine/registration.h | 1 + 4 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp index 51aca239..1bd0c7d4 100644 --- a/src/engine/dependency.cpp +++ b/src/engine/dependency.cpp @@ -19,7 +19,8 @@ static HRESULT DetectPackageDependents( static HRESULT SplitIgnoreDependencies( __in_z LPCWSTR wzIgnoreDependencies, __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, - __inout LPUINT pcDependencies + __inout LPUINT pcDependencies, + __out BOOL* pfIgnoreAll ); static HRESULT JoinIgnoreDependencies( @@ -194,7 +195,7 @@ extern "C" HRESULT DependencyInitialize( // Add the list of dependencies to ignore. if (wzIgnoreDependencies) { - hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies); + hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, &pRegistration->fIgnoreAllDependents); ExitOnFailure(hr, "Failed to split the list of dependencies to ignore."); } @@ -816,12 +817,14 @@ LExit: static HRESULT SplitIgnoreDependencies( __in_z LPCWSTR wzIgnoreDependencies, __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, - __inout LPUINT pcDependencies + __inout LPUINT pcDependencies, + __out BOOL* pfIgnoreAll ) { HRESULT hr = S_OK; LPWSTR wzContext = NULL; STRINGDICT_HANDLE sdIgnoreDependencies = NULL; + *pfIgnoreAll = FALSE; // Create a dictionary to hold unique dependencies. hr = DictCreateStringList(&sdIgnoreDependencies, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE); @@ -842,6 +845,11 @@ static HRESULT SplitIgnoreDependencies( hr = DictAddKey(sdIgnoreDependencies, wzToken); ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", wzToken); + + if (!*pfIgnoreAll && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, L"ALL", -1, wzToken, -1)) + { + *pfIgnoreAll = TRUE; + } } } diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 65da4ab3..c75c1753 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp @@ -588,8 +588,8 @@ extern "C" HRESULT PlanRegistration( STRINGDICT_HANDLE sdIgnoreDependents = NULL; pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. - pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed + pPlan->fIgnoreAllDependents = pRegistration->fIgnoreAllDependents; // Ensure the bundle is cached if not running from the cache. if (!CacheBundleRunningFromCache()) @@ -633,68 +633,71 @@ extern "C" HRESULT PlanRegistration( ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); } - // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. - // However, when being upgraded, we always execute our uninstall because a newer version of us is probably - // already on the machine and we need to clean up the stuff specific to this bundle. - if (BOOTSTRAPPER_RELATION_UPGRADE != relationType) + if (!pPlan->fIgnoreAllDependents) { - // If there were other dependencies to ignore, add them. - for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency) + // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. + // However, when being upgraded, we always execute our uninstall because a newer version of us is probably + // already on the machine and we need to clean up the stuff specific to this bundle. + if (BOOTSTRAPPER_RELATION_UPGRADE != relationType) { - DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency; - - hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey); - if (E_NOTFOUND != hr) - { - ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents."); - } - else + // If there were other dependencies to ignore, add them. + for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency) { - hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey); - ExitOnFailure(hr, "Failed to add dependent key to ignored dependents."); - } - } + DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency; - // For addon or patch bundles, dependent related bundles should be ignored. This allows - // that addon or patch to be removed even though bundles it targets still are registered. - for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) - { - const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; + hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey); + if (E_NOTFOUND != hr) + { + ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents."); + } + else + { + hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey); + ExitOnFailure(hr, "Failed to add dependent key to ignored dependents."); + } + } - if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType) + // For addon or patch bundles, dependent related bundles should be ignored. This allows + // that addon or patch to be removed even though bundles it targets still are registered. + for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) { - for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j) + const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; + + if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType) { - const BURN_DEPENDENCY_PROVIDER* pProvider = pRelatedBundle->package.rgDependencyProviders + j; + for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j) + { + const BURN_DEPENDENCY_PROVIDER* pProvider = pRelatedBundle->package.rgDependencyProviders + j; - hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey); - ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents."); + hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey); + ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents."); + } } } - } - - // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning. - for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent) - { - DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent; - hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey); - if (E_NOTFOUND == hr) + // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning. + for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent) { - hr = S_OK; + DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent; - // TODO: callback to the BA and let it have the option to ignore this dependent? - if (!pPlan->fDisallowRemoval) + hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey); + if (E_NOTFOUND == hr) { - pPlan->fDisallowRemoval = TRUE; // ensure the registration stays - *pfContinuePlanning = FALSE; // skip the rest of planning. + hr = S_OK; - LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); - } + // TODO: callback to the BA and let it have the option to ignore this dependent? + if (!pPlan->fDisallowRemoval) + { + pPlan->fDisallowRemoval = TRUE; // ensure the registration stays + *pfContinuePlanning = FALSE; // skip the rest of planning. - LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_DEPENDENT, pDependent->sczKey, LoggingStringOrUnknownIfNull(pDependent->sczName)); + LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); + } + + LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_DEPENDENT, pDependent->sczKey, LoggingStringOrUnknownIfNull(pDependent->sczName)); + } + ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); } - ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); } } } diff --git a/src/engine/plan.h b/src/engine/plan.h index e72186c7..77f82e1f 100644 --- a/src/engine/plan.h +++ b/src/engine/plan.h @@ -314,6 +314,7 @@ typedef struct _BURN_PLAN BOOL fDisallowRemoval; BOOL fDisableRollback; BOOL fAffectedMachineState; + BOOL fIgnoreAllDependents; DWORD64 qwCacheSizeTotal; diff --git a/src/engine/registration.h b/src/engine/registration.h index e0418fa3..39fee65f 100644 --- a/src/engine/registration.h +++ b/src/engine/registration.h @@ -146,6 +146,7 @@ typedef struct _BURN_REGISTRATION UINT cIgnoredDependencies; // Only valid after detect. DEPENDENCY* rgDependents; // Only valid after detect. UINT cDependents; // Only valid after detect. + BOOL fIgnoreAllDependents; // Only valid after detect. LPCWSTR wzSelfDependent; // Only valid after detect. BOOL fSelfRegisteredAsDependent; // Only valid after detect. BOOL fParentRegisteredAsDependent; // Only valid after detect. -- cgit v1.2.3-55-g6feb