aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-03-30 19:38:33 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-03-30 21:59:51 -0500
commite9a4f673511dd06a8209f3e4037ad20f153d6caa (patch)
treedf3ea53150c1927f43bd7375d1a33bf0e0491932
parent5cbe372f0a512babc5db7f519fc407eb40606346 (diff)
downloadwix-e9a4f673511dd06a8209f3e4037ad20f153d6caa.tar.gz
wix-e9a4f673511dd06a8209f3e4037ad20f153d6caa.tar.bz2
wix-e9a4f673511dd06a8209f3e4037ad20f153d6caa.zip
Skip bundle dependent checking when ignoring dependencies includes ALL.
Fixes #6391.
-rw-r--r--src/engine/dependency.cpp14
-rw-r--r--src/engine/plan.cpp95
-rw-r--r--src/engine/plan.h1
-rw-r--r--src/engine/registration.h1
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(
19static HRESULT SplitIgnoreDependencies( 19static HRESULT SplitIgnoreDependencies(
20 __in_z LPCWSTR wzIgnoreDependencies, 20 __in_z LPCWSTR wzIgnoreDependencies,
21 __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, 21 __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies,
22 __inout LPUINT pcDependencies 22 __inout LPUINT pcDependencies,
23 __out BOOL* pfIgnoreAll
23 ); 24 );
24 25
25static HRESULT JoinIgnoreDependencies( 26static HRESULT JoinIgnoreDependencies(
@@ -194,7 +195,7 @@ extern "C" HRESULT DependencyInitialize(
194 // Add the list of dependencies to ignore. 195 // Add the list of dependencies to ignore.
195 if (wzIgnoreDependencies) 196 if (wzIgnoreDependencies)
196 { 197 {
197 hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies); 198 hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, &pRegistration->fIgnoreAllDependents);
198 ExitOnFailure(hr, "Failed to split the list of dependencies to ignore."); 199 ExitOnFailure(hr, "Failed to split the list of dependencies to ignore.");
199 } 200 }
200 201
@@ -816,12 +817,14 @@ LExit:
816static HRESULT SplitIgnoreDependencies( 817static HRESULT SplitIgnoreDependencies(
817 __in_z LPCWSTR wzIgnoreDependencies, 818 __in_z LPCWSTR wzIgnoreDependencies,
818 __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, 819 __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies,
819 __inout LPUINT pcDependencies 820 __inout LPUINT pcDependencies,
821 __out BOOL* pfIgnoreAll
820 ) 822 )
821{ 823{
822 HRESULT hr = S_OK; 824 HRESULT hr = S_OK;
823 LPWSTR wzContext = NULL; 825 LPWSTR wzContext = NULL;
824 STRINGDICT_HANDLE sdIgnoreDependencies = NULL; 826 STRINGDICT_HANDLE sdIgnoreDependencies = NULL;
827 *pfIgnoreAll = FALSE;
825 828
826 // Create a dictionary to hold unique dependencies. 829 // Create a dictionary to hold unique dependencies.
827 hr = DictCreateStringList(&sdIgnoreDependencies, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE); 830 hr = DictCreateStringList(&sdIgnoreDependencies, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE);
@@ -842,6 +845,11 @@ static HRESULT SplitIgnoreDependencies(
842 845
843 hr = DictAddKey(sdIgnoreDependencies, wzToken); 846 hr = DictAddKey(sdIgnoreDependencies, wzToken);
844 ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", 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 }
845 } 853 }
846 } 854 }
847 855
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(
588 STRINGDICT_HANDLE sdIgnoreDependents = NULL; 588 STRINGDICT_HANDLE sdIgnoreDependents = NULL;
589 589
590 pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. 590 pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state.
591
592 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed 591 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed
592 pPlan->fIgnoreAllDependents = pRegistration->fIgnoreAllDependents;
593 593
594 // Ensure the bundle is cached if not running from the cache. 594 // Ensure the bundle is cached if not running from the cache.
595 if (!CacheBundleRunningFromCache()) 595 if (!CacheBundleRunningFromCache())
@@ -633,68 +633,71 @@ extern "C" HRESULT PlanRegistration(
633 ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); 633 ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents.");
634 } 634 }
635 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. 636 if (!pPlan->fIgnoreAllDependents)
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)
640 { 637 {
641 // If there were other dependencies to ignore, add them. 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.
642 for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency) 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)
643 { 642 {
644 DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency; 643 // If there were other dependencies to ignore, add them.
645 644 for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency)
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
652 { 645 {
653 hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey); 646 DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency;
654 ExitOnFailure(hr, "Failed to add dependent key to ignored dependents.");
655 }
656 }
657 647
658 // For addon or patch bundles, dependent related bundles should be ignored. This allows 648 hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey);
659 // that addon or patch to be removed even though bundles it targets still are registered. 649 if (E_NOTFOUND != hr)
660 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) 650 {
661 { 651 ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents.");
662 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; 652 }
653 else
654 {
655 hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey);
656 ExitOnFailure(hr, "Failed to add dependent key to ignored dependents.");
657 }
658 }
663 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)
665 { 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 { 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;
669 671
670 hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey); 672 hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey);
671 ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents."); 673 ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents.");
674 }
672 } 675 }
673 } 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;
680 677
681 hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey); 678 // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning.
682 if (E_NOTFOUND == hr) 679 for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent)
683 { 680 {
684 hr = S_OK; 681 DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent;
685 682
686 // TODO: callback to the BA and let it have the option to ignore this dependent? 683 hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey);
687 if (!pPlan->fDisallowRemoval) 684 if (E_NOTFOUND == hr)
688 { 685 {
689 pPlan->fDisallowRemoval = TRUE; // ensure the registration stays 686 hr = S_OK;
690 *pfContinuePlanning = FALSE; // skip the rest of planning.
691 687
692 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); 688 // TODO: callback to the BA and let it have the option to ignore this dependent?
693 } 689 if (!pPlan->fDisallowRemoval)
690 {
691 pPlan->fDisallowRemoval = TRUE; // ensure the registration stays
692 *pfContinuePlanning = FALSE; // skip the rest of planning.
694 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.");
696 } 700 }
697 ExitOnFailure(hr, "Failed to check for remaining dependents during planning.");
698 } 701 }
699 } 702 }
700 } 703 }
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
314 BOOL fDisallowRemoval; 314 BOOL fDisallowRemoval;
315 BOOL fDisableRollback; 315 BOOL fDisableRollback;
316 BOOL fAffectedMachineState; 316 BOOL fAffectedMachineState;
317 BOOL fIgnoreAllDependents;
317 318
318 DWORD64 qwCacheSizeTotal; 319 DWORD64 qwCacheSizeTotal;
319 320
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
146 UINT cIgnoredDependencies; // Only valid after detect. 146 UINT cIgnoredDependencies; // Only valid after detect.
147 DEPENDENCY* rgDependents; // Only valid after detect. 147 DEPENDENCY* rgDependents; // Only valid after detect.
148 UINT cDependents; // Only valid after detect. 148 UINT cDependents; // Only valid after detect.
149 BOOL fIgnoreAllDependents; // Only valid after detect.
149 LPCWSTR wzSelfDependent; // Only valid after detect. 150 LPCWSTR wzSelfDependent; // Only valid after detect.
150 BOOL fSelfRegisteredAsDependent; // Only valid after detect. 151 BOOL fSelfRegisteredAsDependent; // Only valid after detect.
151 BOOL fParentRegisteredAsDependent; // Only valid after detect. 152 BOOL fParentRegisteredAsDependent; // Only valid after detect.