@joebigelow / wix-1 / commits / e9a4f673

Skip bundle dependent checking when ignoring dependencies includes ALL.

Fixes #6391.

Sean Hall committed Mar 30, 2021 at 19:38 UTC e9a4f673511dd06a8209f3e4037ad20f153d6caa
4 files changed +62 -49
src/engine/dependency.cpp
+11 -3
@@ -19,7 +19,8 @@ static HRESULT DetectPackageDependents(
19 static HRESULT SplitIgnoreDependencies(
20 __in_z LPCWSTR wzIgnoreDependencies,
21 __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies,
22 - __inout LPUINT pcDependencies
22 + __inout LPUINT pcDependencies,
23 + __out BOOL* pfIgnoreAll
24 );
25
26 static HRESULT JoinIgnoreDependencies(
@@ -194,7 +195,7 @@ extern "C" HRESULT DependencyInitialize(
195 // Add the list of dependencies to ignore.
196 if (wzIgnoreDependencies)
197 {
197 - hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies);
198 + hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, &pRegistration->fIgnoreAllDependents);
199 ExitOnFailure(hr, "Failed to split the list of dependencies to ignore.");
200 }
201
@@ -816,12 +817,14 @@ LExit:
817 static HRESULT SplitIgnoreDependencies(
818 __in_z LPCWSTR wzIgnoreDependencies,
819 __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies,
819 - __inout LPUINT pcDependencies
820 + __inout LPUINT pcDependencies,
821 + __out BOOL* pfIgnoreAll
822 )
823 {
824 HRESULT hr = S_OK;
825 LPWSTR wzContext = NULL;
826 STRINGDICT_HANDLE sdIgnoreDependencies = NULL;
827 + *pfIgnoreAll = FALSE;
828
829 // Create a dictionary to hold unique dependencies.
830 hr = DictCreateStringList(&sdIgnoreDependencies, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE);
@@ -842,6 +845,11 @@ static HRESULT SplitIgnoreDependencies(
845
846 hr = DictAddKey(sdIgnoreDependencies, wzToken);
847 ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", wzToken);
848 +
849 + if (!*pfIgnoreAll && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, L"ALL", -1, wzToken, -1))
850 + {
851 + *pfIgnoreAll = TRUE;
852 + }
853 }
854 }
855
src/engine/plan.cpp
+49 -46
@@ -588,8 +588,8 @@ extern "C" HRESULT PlanRegistration(
588 STRINGDICT_HANDLE sdIgnoreDependents = NULL;
589
590 pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state.
591 -
591 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed
592 + pPlan->fIgnoreAllDependents = pRegistration->fIgnoreAllDependents;
593
594 // Ensure the bundle is cached if not running from the cache.
595 if (!CacheBundleRunningFromCache())
@@ -633,68 +633,71 @@ extern "C" HRESULT PlanRegistration(
633 ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents.");
634 }
635
636 - // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning.
637 - // However, when being upgraded, we always execute our uninstall because a newer version of us is probably
638 - // already on the machine and we need to clean up the stuff specific to this bundle.
639 - if (BOOTSTRAPPER_RELATION_UPGRADE != relationType)
636 + if (!pPlan->fIgnoreAllDependents)
637 {
641 - // If there were other dependencies to ignore, add them.
642 - for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency)
638 + // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning.
639 + // However, when being upgraded, we always execute our uninstall because a newer version of us is probably
640 + // already on the machine and we need to clean up the stuff specific to this bundle.
641 + if (BOOTSTRAPPER_RELATION_UPGRADE != relationType)
642 {
644 - DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency;
645 -
646 - hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey);
647 - if (E_NOTFOUND != hr)
648 - {
649 - ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents.");
650 - }
651 - else
643 + // If there were other dependencies to ignore, add them.
644 + for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency)
645 {
653 - hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey);
654 - ExitOnFailure(hr, "Failed to add dependent key to ignored dependents.");
655 - }
656 - }
646 + DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency;
647
658 - // For addon or patch bundles, dependent related bundles should be ignored. This allows
659 - // that addon or patch to be removed even though bundles it targets still are registered.
660 - for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
661 - {
662 - const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
648 + hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey);
649 + if (E_NOTFOUND != hr)
650 + {
651 + ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents.");
652 + }
653 + else
654 + {
655 + hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey);
656 + ExitOnFailure(hr, "Failed to add dependent key to ignored dependents.");
657 + }
658 + }
659
664 - if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType)
660 + // For addon or patch bundles, dependent related bundles should be ignored. This allows
661 + // that addon or patch to be removed even though bundles it targets still are registered.
662 + for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
663 {
666 - for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j)
664 + const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
665 +
666 + if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType)
667 {
668 - const BURN_DEPENDENCY_PROVIDER* pProvider = pRelatedBundle->package.rgDependencyProviders + j;
668 + for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j)
669 + {
670 + const BURN_DEPENDENCY_PROVIDER* pProvider = pRelatedBundle->package.rgDependencyProviders + j;
671
670 - hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey);
671 - ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents.");
672 + hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey);
673 + ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents.");
674 + }
675 }
676 }
674 - }
675 -
676 - // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning.
677 - for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent)
678 - {
679 - DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent;
677
681 - hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey);
682 - if (E_NOTFOUND == hr)
678 + // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning.
679 + for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent)
680 {
684 - hr = S_OK;
681 + DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent;
682
686 - // TODO: callback to the BA and let it have the option to ignore this dependent?
687 - if (!pPlan->fDisallowRemoval)
683 + hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey);
684 + if (E_NOTFOUND == hr)
685 {
689 - pPlan->fDisallowRemoval = TRUE; // ensure the registration stays
690 - *pfContinuePlanning = FALSE; // skip the rest of planning.
686 + hr = S_OK;
687
692 - LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS);
693 - }
688 + // TODO: callback to the BA and let it have the option to ignore this dependent?
689 + if (!pPlan->fDisallowRemoval)
690 + {
691 + pPlan->fDisallowRemoval = TRUE; // ensure the registration stays
692 + *pfContinuePlanning = FALSE; // skip the rest of planning.
693
695 - LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_DEPENDENT, pDependent->sczKey, LoggingStringOrUnknownIfNull(pDependent->sczName));
694 + LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS);
695 + }
696 +
697 + LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_DEPENDENT, pDependent->sczKey, LoggingStringOrUnknownIfNull(pDependent->sczName));
698 + }
699 + ExitOnFailure(hr, "Failed to check for remaining dependents during planning.");
700 }
697 - ExitOnFailure(hr, "Failed to check for remaining dependents during planning.");
701 }
702 }
703 }
src/engine/plan.h
+1
@@ -314,6 +314,7 @@ typedef struct _BURN_PLAN
314 BOOL fDisallowRemoval;
315 BOOL fDisableRollback;
316 BOOL fAffectedMachineState;
317 + BOOL fIgnoreAllDependents;
318
319 DWORD64 qwCacheSizeTotal;
320
src/engine/registration.h
+1
@@ -146,6 +146,7 @@ typedef struct _BURN_REGISTRATION
146 UINT cIgnoredDependencies; // Only valid after detect.
147 DEPENDENCY* rgDependents; // Only valid after detect.
148 UINT cDependents; // Only valid after detect.
149 + BOOL fIgnoreAllDependents; // Only valid after detect.
150 LPCWSTR wzSelfDependent; // Only valid after detect.
151 BOOL fSelfRegisteredAsDependent; // Only valid after detect.
152 BOOL fParentRegisteredAsDependent; // Only valid after detect.