aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-03-13 23:45:32 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-03-14 14:53:29 -0500
commit4cd1c4e06145434ca940ac828772dc47b9d9738e (patch)
treea754d685039173c63303dc6d0d8b1a2bf3ab506b
parent89adb2e3cc232b11b28e5bdeccb0c522c8124a29 (diff)
downloadwix-4cd1c4e06145434ca940ac828772dc47b9d9738e.tar.gz
wix-4cd1c4e06145434ca940ac828772dc47b9d9738e.tar.bz2
wix-4cd1c4e06145434ca940ac828772dc47b9d9738e.zip
Allow the BA to override the bundle relation type during plan.
-rw-r--r--src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h29
-rw-r--r--src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs26
-rw-r--r--src/api/burn/WixToolset.Mba.Core/EventArgs.cs31
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs60
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs5
-rw-r--r--src/api/burn/balutil/inc/BAFunctions.h1
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctions.h10
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h1
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h11
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h12
-rw-r--r--src/api/burn/balutil/inc/IBootstrapperApplication.h8
-rw-r--r--src/burn/engine/bundlepackageengine.cpp29
-rw-r--r--src/burn/engine/core.cpp16
-rw-r--r--src/burn/engine/detect.cpp18
-rw-r--r--src/burn/engine/elevation.cpp9
-rw-r--r--src/burn/engine/engine.mc10
-rw-r--r--src/burn/engine/logging.cpp31
-rw-r--r--src/burn/engine/logging.h4
-rw-r--r--src/burn/engine/plan.cpp161
-rw-r--r--src/burn/engine/plan.h16
-rw-r--r--src/burn/engine/registration.cpp23
-rw-r--r--src/burn/engine/registration.h8
-rw-r--r--src/burn/engine/relatedbundle.cpp105
-rw-r--r--src/burn/engine/relatedbundle.h5
-rw-r--r--src/burn/engine/userexperience.cpp32
-rw-r--r--src/burn/engine/userexperience.h5
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp149
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp44
-rw-r--r--src/ext/Bal/wixstdba/wixstdba.mc7
-rw-r--r--src/libs/dutil/WixToolset.DUtil/butil.cpp12
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/butil.h4
31 files changed, 785 insertions, 97 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index 9a5fb8f8..b507b167 100644
--- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -103,10 +103,22 @@ enum BOOTSTRAPPER_RELATION_TYPE
103 BOOTSTRAPPER_RELATION_UPGRADE, 103 BOOTSTRAPPER_RELATION_UPGRADE,
104 BOOTSTRAPPER_RELATION_ADDON, 104 BOOTSTRAPPER_RELATION_ADDON,
105 BOOTSTRAPPER_RELATION_PATCH, 105 BOOTSTRAPPER_RELATION_PATCH,
106 BOOTSTRAPPER_RELATION_DEPENDENT, 106 BOOTSTRAPPER_RELATION_DEPENDENT_ADDON,
107 BOOTSTRAPPER_RELATION_DEPENDENT_PATCH,
107 BOOTSTRAPPER_RELATION_UPDATE, 108 BOOTSTRAPPER_RELATION_UPDATE,
108}; 109};
109 110
111enum BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE
112{
113 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE,
114 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE,
115 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE,
116 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON,
117 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH,
118 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON,
119 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH,
120};
121
110enum BOOTSTRAPPER_CACHE_TYPE 122enum BOOTSTRAPPER_CACHE_TYPE
111{ 123{
112 BOOTSTRAPPER_CACHE_TYPE_REMOVE, 124 BOOTSTRAPPER_CACHE_TYPE_REMOVE,
@@ -210,6 +222,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
210 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, 222 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE,
211 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, 223 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE,
212 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, 224 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE,
225 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE,
213}; 226};
214 227
215enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION 228enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -1209,6 +1222,20 @@ struct BA_ONPLANRELATEDBUNDLE_RESULTS
1209 BOOTSTRAPPER_REQUEST_STATE requestedState; 1222 BOOTSTRAPPER_REQUEST_STATE requestedState;
1210}; 1223};
1211 1224
1225struct BA_ONPLANRELATEDBUNDLETYPE_ARGS
1226{
1227 DWORD cbSize;
1228 LPCWSTR wzBundleId;
1229 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE recommendedType;
1230};
1231
1232struct BA_ONPLANRELATEDBUNDLETYPE_RESULTS
1233{
1234 DWORD cbSize;
1235 BOOL fCancel;
1236 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE requestedType;
1237};
1238
1212struct BA_ONPLANRESTORERELATEDBUNDLE_ARGS 1239struct BA_ONPLANRESTORERELATEDBUNDLE_ARGS
1213{ 1240{
1214 DWORD cbSize; 1241 DWORD cbSize;
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
index 1df992be..fd36cf26 100644
--- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
@@ -89,6 +89,9 @@ namespace WixToolset.Mba.Core
89 public event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle; 89 public event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle;
90 90
91 /// <inheritdoc/> 91 /// <inheritdoc/>
92 public event EventHandler<PlanRelatedBundleTypeEventArgs> PlanRelatedBundleType;
93
94 /// <inheritdoc/>
92 public event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary; 95 public event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary;
93 96
94 /// <inheritdoc/> 97 /// <inheritdoc/>
@@ -534,6 +537,19 @@ namespace WixToolset.Mba.Core
534 } 537 }
535 538
536 /// <summary> 539 /// <summary>
540 /// Called by the engine, raises the <see cref="PlanRelatedBundleType"/> event.
541 /// </summary>
542 /// <param name="args">Additional arguments for this event.</param>
543 protected virtual void OnPlanRelatedBundleType(PlanRelatedBundleTypeEventArgs args)
544 {
545 EventHandler<PlanRelatedBundleTypeEventArgs> handler = this.PlanRelatedBundleType;
546 if (null != handler)
547 {
548 handler(this, args);
549 }
550 }
551
552 /// <summary>
537 /// Called by the engine, raises the <see cref="PlanRollbackBoundary"/> event. 553 /// Called by the engine, raises the <see cref="PlanRollbackBoundary"/> event.
538 /// </summary> 554 /// </summary>
539 protected virtual void OnPlanRollbackBoundary(PlanRollbackBoundaryEventArgs args) 555 protected virtual void OnPlanRollbackBoundary(PlanRollbackBoundaryEventArgs args)
@@ -1514,6 +1530,16 @@ namespace WixToolset.Mba.Core
1514 return args.HResult; 1530 return args.HResult;
1515 } 1531 }
1516 1532
1533 int IBootstrapperApplication.OnPlanRelatedBundleType(string wzBundleId, RelatedBundlePlanType recommendedType, ref RelatedBundlePlanType pRequestedType, ref bool fCancel)
1534 {
1535 PlanRelatedBundleTypeEventArgs args = new PlanRelatedBundleTypeEventArgs(wzBundleId, recommendedType, pRequestedType, fCancel);
1536 this.OnPlanRelatedBundleType(args);
1537
1538 pRequestedType = args.Type;
1539 fCancel = args.Cancel;
1540 return args.HResult;
1541 }
1542
1517 int IBootstrapperApplication.OnPlanRollbackBoundary(string wzRollbackBoundaryId, bool fRecommendedTransaction, ref bool fTransaction, ref bool fCancel) 1543 int IBootstrapperApplication.OnPlanRollbackBoundary(string wzRollbackBoundaryId, bool fRecommendedTransaction, ref bool fTransaction, ref bool fCancel)
1518 { 1544 {
1519 PlanRollbackBoundaryEventArgs args = new PlanRollbackBoundaryEventArgs(wzRollbackBoundaryId, fRecommendedTransaction, fTransaction, fCancel); 1545 PlanRollbackBoundaryEventArgs args = new PlanRollbackBoundaryEventArgs(wzRollbackBoundaryId, fRecommendedTransaction, fTransaction, fCancel);
diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
index 816757cc..d8ec7998 100644
--- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
@@ -746,6 +746,37 @@ namespace WixToolset.Mba.Core
746 } 746 }
747 747
748 /// <summary> 748 /// <summary>
749 /// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanRelatedBundleType"/>
750 /// </summary>
751 [Serializable]
752 public class PlanRelatedBundleTypeEventArgs : CancellableHResultEventArgs
753 {
754 /// <summary />
755 public PlanRelatedBundleTypeEventArgs(string bundleId, RelatedBundlePlanType recommendedType, RelatedBundlePlanType type, bool cancelRecommendation)
756 : base(cancelRecommendation)
757 {
758 this.BundleId = bundleId;
759 this.RecommendedType = recommendedType;
760 this.Type = type;
761 }
762
763 /// <summary>
764 /// Gets the identity of the bundle to plan for.
765 /// </summary>
766 public string BundleId { get; private set; }
767
768 /// <summary>
769 /// Gets the recommended plan type for the bundle.
770 /// </summary>
771 public RelatedBundlePlanType RecommendedType { get; private set; }
772
773 /// <summary>
774 /// Gets or sets the plan type for the bundle.
775 /// </summary>
776 public RelatedBundlePlanType Type { get; set; }
777 }
778
779 /// <summary>
749 /// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanPackageBegin"/> 780 /// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanPackageBegin"/>
750 /// </summary> 781 /// </summary>
751 [Serializable] 782 [Serializable]
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
index 489e3b6d..4ab0f8d9 100644
--- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
@@ -1148,6 +1148,18 @@ namespace WixToolset.Mba.Core
1148 [MarshalAs(UnmanagedType.U4)] ref RequestState pRequestedState, 1148 [MarshalAs(UnmanagedType.U4)] ref RequestState pRequestedState,
1149 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel 1149 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel
1150 ); 1150 );
1151
1152 /// <summary>
1153 /// See <see cref="IDefaultBootstrapperApplication.PlanRelatedBundleType"/>.
1154 /// </summary>
1155 [PreserveSig]
1156 [return: MarshalAs(UnmanagedType.I4)]
1157 int OnPlanRelatedBundleType(
1158 [MarshalAs(UnmanagedType.LPWStr)] string wzBundleId,
1159 [MarshalAs(UnmanagedType.U4)] RelatedBundlePlanType recommendedType,
1160 [MarshalAs(UnmanagedType.U4)] ref RelatedBundlePlanType pRequestedType,
1161 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel
1162 );
1151 } 1163 }
1152 1164
1153 /// <summary> 1165 /// <summary>
@@ -1669,7 +1681,12 @@ namespace WixToolset.Mba.Core
1669 /// <summary> 1681 /// <summary>
1670 /// 1682 ///
1671 /// </summary> 1683 /// </summary>
1672 Dependent, 1684 DependentAddon,
1685
1686 /// <summary>
1687 ///
1688 /// </summary>
1689 DependentPatch,
1673 1690
1674 /// <summary> 1691 /// <summary>
1675 /// 1692 ///
@@ -1678,6 +1695,47 @@ namespace WixToolset.Mba.Core
1678 } 1695 }
1679 1696
1680 /// <summary> 1697 /// <summary>
1698 /// The planned relation type for related bundles.
1699 /// </summary>
1700 public enum RelatedBundlePlanType
1701 {
1702 /// <summary>
1703 ///
1704 /// </summary>
1705 None,
1706
1707 /// <summary>
1708 ///
1709 /// </summary>
1710 Downgrade,
1711
1712 /// <summary>
1713 ///
1714 /// </summary>
1715 Upgrade,
1716
1717 /// <summary>
1718 ///
1719 /// </summary>
1720 Addon,
1721
1722 /// <summary>
1723 ///
1724 /// </summary>
1725 Patch,
1726
1727 /// <summary>
1728 ///
1729 /// </summary>
1730 DependentAddon,
1731
1732 /// <summary>
1733 ///
1734 /// </summary>
1735 DependentPatch,
1736 }
1737
1738 /// <summary>
1681 /// One or more reasons why the application is requested to be closed or is being closed. 1739 /// One or more reasons why the application is requested to be closed or is being closed.
1682 /// </summary> 1740 /// </summary>
1683 [Flags] 1741 [Flags]
diff --git a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
index c237cb9d..ebd1580b 100644
--- a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
@@ -334,6 +334,11 @@ namespace WixToolset.Mba.Core
334 event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle; 334 event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle;
335 335
336 /// <summary> 336 /// <summary>
337 /// Fired when the engine has begun planning the related bundle relation type.
338 /// </summary>
339 event EventHandler<PlanRelatedBundleTypeEventArgs> PlanRelatedBundleType;
340
341 /// <summary>
337 /// Fired when the engine has begun planning an upgrade related bundle for restoring in case of failure. 342 /// Fired when the engine has begun planning an upgrade related bundle for restoring in case of failure.
338 /// </summary> 343 /// </summary>
339 event EventHandler<PlanRestoreRelatedBundleEventArgs> PlanRestoreRelatedBundle; 344 event EventHandler<PlanRestoreRelatedBundleEventArgs> PlanRestoreRelatedBundle;
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h
index cbef88df..f772eb3f 100644
--- a/src/api/burn/balutil/inc/BAFunctions.h
+++ b/src/api/burn/balutil/inc/BAFunctions.h
@@ -89,6 +89,7 @@ enum BA_FUNCTIONS_MESSAGE
89 BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, 89 BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE,
90 BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, 90 BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE,
91 BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, 91 BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE,
92 BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE,
92 93
93 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, 94 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
94 BA_FUNCTIONS_MESSAGE_WNDPROC, 95 BA_FUNCTIONS_MESSAGE_WNDPROC,
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
index 60a70e3e..f558828f 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
@@ -859,6 +859,16 @@ public: // IBootstrapperApplication
859 return S_OK; 859 return S_OK;
860 } 860 }
861 861
862 virtual STDMETHODIMP OnPlanRelatedBundleType(
863 __in_z LPCWSTR /*wzBundleId*/,
864 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE /*recommendedType*/,
865 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* /*pRequestedType*/,
866 __inout BOOL* /*pfCancel*/
867 )
868 {
869 return S_OK;
870 }
871
862public: // IBAFunctions 872public: // IBAFunctions
863 virtual STDMETHODIMP OnPlan( 873 virtual STDMETHODIMP OnPlan(
864 ) 874 )
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
index 09cc189e..ede00f28 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
@@ -160,6 +160,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
160 case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE: 160 case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE:
161 case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: 161 case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE:
162 case BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE: 162 case BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE:
163 case BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE:
163 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); 164 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext);
164 break; 165 break;
165 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: 166 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED:
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
index 7b3cf827..49f4b7ca 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
@@ -1058,6 +1058,17 @@ public: // IBootstrapperApplication
1058 return S_OK; 1058 return S_OK;
1059 } 1059 }
1060 1060
1061 virtual STDMETHODIMP OnPlanRelatedBundleType(
1062 __in_z LPCWSTR /*wzBundleId*/,
1063 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE /*recommendedType*/,
1064 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* /*pRequestedType*/,
1065 __inout BOOL* pfCancel
1066 )
1067 {
1068 *pfCancel |= CheckCanceled();
1069 return S_OK;
1070 }
1071
1061public: //CBalBaseBootstrapperApplication 1072public: //CBalBaseBootstrapperApplication
1062 virtual STDMETHODIMP Initialize( 1073 virtual STDMETHODIMP Initialize(
1063 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs 1074 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
index 8c3b8b72..698349f7 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
@@ -729,6 +729,15 @@ static HRESULT BalBaseBAProcOnPlanRestoreRelatedBundle(
729 return pBA->OnPlanRestoreRelatedBundle(pArgs->wzBundleId, pArgs->recommendedState, &pResults->requestedState, &pResults->fCancel); 729 return pBA->OnPlanRestoreRelatedBundle(pArgs->wzBundleId, pArgs->recommendedState, &pResults->requestedState, &pResults->fCancel);
730} 730}
731 731
732static HRESULT BalBaseBAProcOnPlanRelatedBundleType(
733 __in IBootstrapperApplication* pBA,
734 __in BA_ONPLANRELATEDBUNDLETYPE_ARGS* pArgs,
735 __inout BA_ONPLANRELATEDBUNDLETYPE_RESULTS* pResults
736 )
737{
738 return pBA->OnPlanRelatedBundleType(pArgs->wzBundleId, pArgs->recommendedType, &pResults->requestedType, &pResults->fCancel);
739}
740
732/******************************************************************* 741/*******************************************************************
733BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. 742BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication.
734 Provides a default mapping between the new message based BA interface and 743 Provides a default mapping between the new message based BA interface and
@@ -988,6 +997,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc(
988 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE: 997 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE:
989 hr = BalBaseBAProcOnPlanRestoreRelatedBundle(pBA, reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_RESULTS*>(pvResults)); 998 hr = BalBaseBAProcOnPlanRestoreRelatedBundle(pBA, reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_RESULTS*>(pvResults));
990 break; 999 break;
1000 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE:
1001 hr = BalBaseBAProcOnPlanRelatedBundleType(pBA, reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults));
1002 break;
991 } 1003 }
992 } 1004 }
993 1005
diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h
index e916d41e..462df0cc 100644
--- a/src/api/burn/balutil/inc/IBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h
@@ -699,4 +699,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
699 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState, 699 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState,
700 __inout BOOL* pfCancel 700 __inout BOOL* pfCancel
701 ) = 0; 701 ) = 0;
702
703 // OnPlanRelatedBundleType - called when the engine begins planning the related bundle relation type.
704 STDMETHOD(OnPlanRelatedBundleType)(
705 __in_z LPCWSTR wzBundleId,
706 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE recommendedType,
707 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType,
708 __inout BOOL* pfCancel
709 ) = 0;
702}; 710};
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index b5fc51e5..88a00f5e 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -2,7 +2,9 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType(
6 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relationType
7 );
6 8
7// function definitions 9// function definitions
8 10
@@ -265,7 +267,7 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
265 GENERIC_EXECUTE_MESSAGE message = { }; 267 GENERIC_EXECUTE_MESSAGE message = { };
266 BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action; 268 BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action;
267 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle; 269 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
268 BOOTSTRAPPER_RELATION_TYPE relationType = pRelatedBundle->relationType; 270 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pRelatedBundle->planRelationType);
269 BURN_PACKAGE* pPackage = &pRelatedBundle->package; 271 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
270 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; 272 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
271 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType); 273 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
@@ -467,3 +469,26 @@ LExit:
467 469
468 return hr; 470 return hr;
469} 471}
472
473static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType(
474 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relationType
475 )
476{
477 switch (relationType)
478 {
479 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE: __fallthrough;
480 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE:
481 return BOOTSTRAPPER_RELATION_UPGRADE;
482 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON:
483 return BOOTSTRAPPER_RELATION_ADDON;
484 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH:
485 return BOOTSTRAPPER_RELATION_PATCH;
486 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON:
487 return BOOTSTRAPPER_RELATION_DEPENDENT_ADDON;
488 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH:
489 return BOOTSTRAPPER_RELATION_DEPENDENT_PATCH;
490 default:
491 AssertSz(BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE == relationType, "Unknown BUNDLE_RELATION_TYPE");
492 return BOOTSTRAPPER_RELATION_NONE;
493 }
494}
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 43f79133..9d4ea43e 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -449,11 +449,11 @@ extern "C" HRESULT CorePlan(
449 449
450 if (!pEngineState->fDetected) 450 if (!pEngineState->fDetected)
451 { 451 {
452 ExitOnFailure(hr = E_INVALIDSTATE, "Plan cannot be done without a successful Detect."); 452 ExitWithRootFailure(hr, E_INVALIDSTATE, "Plan cannot be done without a successful Detect.");
453 } 453 }
454 else if (pEngineState->plan.fAffectedMachineState) 454 else if (pEngineState->plan.fAffectedMachineState)
455 { 455 {
456 ExitOnFailure(hr = E_INVALIDSTATE, "Plan requires a new successful Detect after calling Apply."); 456 ExitWithRootFailure(hr, E_INVALIDSTATE, "Plan requires a new successful Detect after calling Apply.");
457 } 457 }
458 458
459 // Always reset the plan. 459 // Always reset the plan.
@@ -482,6 +482,9 @@ extern "C" HRESULT CorePlan(
482 hr = DependencyPlanInitialize(&pEngineState->dependencies, &pEngineState->plan); 482 hr = DependencyPlanInitialize(&pEngineState->dependencies, &pEngineState->plan);
483 ExitOnFailure(hr, "Failed to initialize the dependencies for the plan."); 483 ExitOnFailure(hr, "Failed to initialize the dependencies for the plan.");
484 484
485 hr = RegistrationPlanInitialize(&pEngineState->registration);
486 ExitOnFailure(hr, "Failed to initialize registration for the plan.");
487
485 if (BOOTSTRAPPER_ACTION_LAYOUT == action) 488 if (BOOTSTRAPPER_ACTION_LAYOUT == action)
486 { 489 {
487 Assert(!pEngineState->plan.fPerMachine); 490 Assert(!pEngineState->plan.fPerMachine);
@@ -521,6 +524,9 @@ extern "C" HRESULT CorePlan(
521 { 524 {
522 pEngineState->plan.fPerMachine = pEngineState->registration.fPerMachine; // default the scope of the plan to the per-machine state of the bundle. 525 pEngineState->plan.fPerMachine = pEngineState->registration.fPerMachine; // default the scope of the plan to the per-machine state of the bundle.
523 526
527 hr = PlanRelatedBundlesInitialize(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
528 ExitOnFailure(hr, "Failed to initialize related bundles for plan.");
529
524 hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, &pEngineState->dependencies, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning); 530 hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, &pEngineState->dependencies, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning);
525 ExitOnFailure(hr, "Failed to plan registration."); 531 ExitOnFailure(hr, "Failed to plan registration.");
526 532
@@ -918,8 +924,8 @@ extern "C" LPCWSTR CoreRelationTypeToCommandLineString(
918 case BOOTSTRAPPER_RELATION_UPDATE: 924 case BOOTSTRAPPER_RELATION_UPDATE:
919 wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_UPDATE; 925 wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_UPDATE;
920 break; 926 break;
921 case BOOTSTRAPPER_RELATION_DEPENDENT: 927 case BOOTSTRAPPER_RELATION_DEPENDENT_ADDON: __fallthrough;
922 break; 928 case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH: __fallthrough;
923 case BOOTSTRAPPER_RELATION_NONE: __fallthrough; 929 case BOOTSTRAPPER_RELATION_NONE: __fallthrough;
924 default: 930 default:
925 wzRelationTypeCommandLine = NULL; 931 wzRelationTypeCommandLine = NULL;
@@ -2308,7 +2314,7 @@ static void LogRelatedBundles(
2308 2314
2309 if (pRelatedBundle->fPlannable) 2315 if (pRelatedBundle->fPlannable)
2310 { 2316 {
2311 LogId(REPORT_STANDARD, MSG_PLANNED_RELATED_BUNDLE, pPackage->sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingRequestStateToString(pRelatedBundle->defaultRequestedRestore), LoggingRequestStateToString(pRelatedBundle->requestedRestore), LoggingActionStateToString(pRelatedBundle->restore), LoggingDependencyActionToString(pPackage->dependencyExecute)); 2317 LogId(REPORT_STANDARD, MSG_PLANNED_RELATED_BUNDLE, pPackage->sczId, LoggingRelationTypeToString(pRelatedBundle->detectRelationType), LoggingPlanRelationTypeToString(pRelatedBundle->defaultPlanRelationType), LoggingPlanRelationTypeToString(pRelatedBundle->planRelationType), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingRequestStateToString(pRelatedBundle->defaultRequestedRestore), LoggingRequestStateToString(pRelatedBundle->requestedRestore), LoggingActionStateToString(pRelatedBundle->restore), LoggingDependencyActionToString(pPackage->dependencyExecute));
2312 } 2318 }
2313 } 2319 }
2314 } 2320 }
diff --git a/src/burn/engine/detect.cpp b/src/burn/engine/detect.cpp
index f7a030ff..7628b26a 100644
--- a/src/burn/engine/detect.cpp
+++ b/src/burn/engine/detect.cpp
@@ -129,7 +129,7 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
129 { 129 {
130 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; 130 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
131 131
132 if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType && 132 if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->detectRelationType &&
133 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1)) 133 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1))
134 { 134 {
135 hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult); 135 hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult);
@@ -143,10 +143,10 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
143 pRegistration->fForwardCompatibleBundleExists = TRUE; 143 pRegistration->fForwardCompatibleBundleExists = TRUE;
144 } 144 }
145 145
146 hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, !pRelatedBundle->package.fCached); 146 hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->detectRelationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, !pRelatedBundle->package.fCached);
147 ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); 147 ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle.");
148 148
149 LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRelatedBundle->package.fCached)); 149 LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->detectRelationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRelatedBundle->package.fCached));
150 } 150 }
151 } 151 }
152 } 152 }
@@ -164,6 +164,7 @@ extern "C" HRESULT DetectReportRelatedBundles(
164 ) 164 )
165{ 165{
166 HRESULT hr = S_OK; 166 HRESULT hr = S_OK;
167 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
167 BOOTSTRAPPER_REQUEST_STATE uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 168 BOOTSTRAPPER_REQUEST_STATE uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
168 *pfEligibleForCleanup = BOOTSTRAPPER_REGISTRATION_TYPE_NONE != pRegistration->detectedRegistrationType || pRegistration->fCached; 169 *pfEligibleForCleanup = BOOTSTRAPPER_REGISTRATION_TYPE_NONE != pRegistration->detectedRegistrationType || pRegistration->fCached;
169 170
@@ -171,16 +172,21 @@ extern "C" HRESULT DetectReportRelatedBundles(
171 { 172 {
172 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; 173 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
173 174
174 LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRelatedBundle->package.fCached)); 175 LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->detectRelationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRelatedBundle->package.fCached));
175 176
176 hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, !pRelatedBundle->package.fCached); 177 hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->detectRelationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, !pRelatedBundle->package.fCached);
177 ExitOnRootFailure(hr, "BA aborted detect related bundle."); 178 ExitOnRootFailure(hr, "BA aborted detect related bundle.");
178 179
179 // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle. 180 // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle.
180 if (*pfEligibleForCleanup && pRelatedBundle->fPlannable) 181 if (*pfEligibleForCleanup && pRelatedBundle->fPlannable)
181 { 182 {
183 planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
182 uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 184 uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
183 hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, BOOTSTRAPPER_ACTION_UNINSTALL, pRegistration->pVersion, pRelatedBundle->pVersion, &uninstallRequestState); 185
186 hr = PlanDefaultRelatedBundlePlanType(pRelatedBundle->detectRelationType, pRegistration->pVersion, pRelatedBundle->pVersion, &planRelationType);
187 ExitOnFailure(hr, "Failed to get the default plan type for related bundle for calculating fEligibleForCleanup");
188
189 hr = PlanDefaultRelatedBundleRequestState(relationType, planRelationType, BOOTSTRAPPER_ACTION_UNINSTALL, &uninstallRequestState);
184 ExitOnFailure(hr, "Failed to get the default request state for related bundle for calculating fEligibleForCleanup"); 190 ExitOnFailure(hr, "Failed to get the default request state for related bundle for calculating fEligibleForCleanup");
185 191
186 if (BOOTSTRAPPER_REQUEST_STATE_NONE != uninstallRequestState) 192 if (BOOTSTRAPPER_REQUEST_STATE_NONE != uninstallRequestState)
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index e479b6c0..636d67ce 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -874,6 +874,9 @@ extern "C" HRESULT ElevationExecuteRelatedBundle(
874 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action); 874 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action);
875 ExitOnFailure(hr, "Failed to write action to message buffer."); 875 ExitOnFailure(hr, "Failed to write action to message buffer.");
876 876
877 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.pRelatedBundle->planRelationType);
878 ExitOnFailure(hr, "Failed to write planRelationType to message buffer.");
879
877 hr = BuffWriteNumber(&pbData, &cbData, fRollback); 880 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
878 ExitOnFailure(hr, "Failed to write rollback."); 881 ExitOnFailure(hr, "Failed to write rollback.");
879 882
@@ -2723,6 +2726,7 @@ static HRESULT OnExecuteRelatedBundle(
2723 HRESULT hr = S_OK; 2726 HRESULT hr = S_OK;
2724 SIZE_T iData = 0; 2727 SIZE_T iData = 0;
2725 LPWSTR sczPackage = NULL; 2728 LPWSTR sczPackage = NULL;
2729 DWORD dwPlanRelationType = 0;
2726 DWORD dwRollback = 0; 2730 DWORD dwRollback = 0;
2727 BURN_EXECUTE_ACTION executeAction = { }; 2731 BURN_EXECUTE_ACTION executeAction = { };
2728 LPWSTR sczIgnoreDependencies = NULL; 2732 LPWSTR sczIgnoreDependencies = NULL;
@@ -2739,6 +2743,9 @@ static HRESULT OnExecuteRelatedBundle(
2739 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action); 2743 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action);
2740 ExitOnFailure(hr, "Failed to read action."); 2744 ExitOnFailure(hr, "Failed to read action.");
2741 2745
2746 hr = BuffReadNumber(pbData, cbData, &iData, &dwPlanRelationType);
2747 ExitOnFailure(hr, "Failed to read planRelationType.");
2748
2742 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); 2749 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
2743 ExitOnFailure(hr, "Failed to read rollback."); 2750 ExitOnFailure(hr, "Failed to read rollback.");
2744 2751
@@ -2757,6 +2764,8 @@ static HRESULT OnExecuteRelatedBundle(
2757 hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle); 2764 hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle);
2758 ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage); 2765 ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage);
2759 2766
2767 executeAction.relatedBundle.pRelatedBundle->planRelationType = (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE)dwPlanRelationType;
2768
2760 // Pass the list of dependencies to ignore, if any, to the related bundle. 2769 // Pass the list of dependencies to ignore, if any, to the related bundle.
2761 if (sczIgnoreDependencies && *sczIgnoreDependencies) 2770 if (sczIgnoreDependencies && *sczIgnoreDependencies)
2762 { 2771 {
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 6a826365..a5c4e2ba 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -384,7 +384,7 @@ MessageId=207
384Severity=Success 384Severity=Success
385SymbolicName=MSG_PLANNED_RELATED_BUNDLE 385SymbolicName=MSG_PLANNED_RELATED_BUNDLE
386Language=English 386Language=English
387Planned related bundle: %1!ls!, type: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, default requested restore: %7!hs!, ba requested restore: %8!hs!, restore: %9!hs!, dependency: %10!hs! 387Planned related bundle: %1!ls!, detect type: %2!hs!, default plan type: %3!hs!, ba plan type: %4!hs!, default requested: %5!hs!, ba requested: %6!hs!, execute: %7!hs!, rollback: %8!hs!, default requested restore: %9!hs!, ba requested restore: %10!hs!, restore: %11!hs!, dependency: %12!hs!
388. 388.
389 389
390MessageId=208 390MessageId=208
@@ -426,14 +426,14 @@ MessageId=213
426Severity=Success 426Severity=Success
427SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_DEPENDENT 427SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_DEPENDENT
428Language=English 428Language=English
429Plan skipped related bundle: %1!ls!, type: %2!hs!, because it was dependent and the current bundle is being executed as type: %3!hs!. 429Plan skipped related bundle: %1!ls!, because it was dependent and the current bundle is being executed as type: %2!hs!.
430. 430.
431 431
432MessageId=214 432MessageId=214
433Severity=Success 433Severity=Success
434SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_SCHEDULED 434SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_SCHEDULED
435Language=English 435Language=English
436Plan skipped related bundle: %1!ls!, type: %2!hs!, because it was previously scheduled. 436Plan skipped related bundle: %1!ls!, because it was previously scheduled.
437. 437.
438 438
439MessageId=215 439MessageId=215
@@ -447,14 +447,14 @@ MessageId=216
447Severity=Success 447Severity=Success
448SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_EMBEDDED_BUNDLE_NEWER 448SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_EMBEDDED_BUNDLE_NEWER
449Language=English 449Language=English
450Plan skipped related bundle: %1!ls!, type: %2!hs!, provider key: %3!ls!, because an embedded bundle with the same provider key is being installed. 450Plan skipped related bundle: %1!ls!, provider key: %2!ls!, because an embedded bundle with the same provider key is being installed.
451. 451.
452 452
453MessageId=217 453MessageId=217
454Severity=Success 454Severity=Success
455SymbolicName=MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR 455SymbolicName=MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR
456Language=English 456Language=English
457Plan skipped dependent bundle repair: %1!ls!, type: %2!hs!, because no packages are being executed during this uninstall operation. 457Plan skipped dependent bundle repair: %1!ls!, because no packages are being executed during this uninstall operation.
458. 458.
459 459
460MessageId=218 460MessageId=218
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 07fc9ef3..2aa1bada 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -715,6 +715,31 @@ extern "C" LPCSTR LoggingResumeModeToString(
715 } 715 }
716} 716}
717 717
718extern "C" LPCSTR LoggingPlanRelationTypeToString(
719 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE type
720 )
721{
722 switch (type)
723 {
724 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE:
725 return "None";
726 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE:
727 return "Downgrade";
728 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE:
729 return "Upgrade";
730 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON:
731 return "Addon";
732 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH:
733 return "Patch";
734 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON:
735 return "DependentAddon";
736 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH:
737 return "DependentPatch";
738 default:
739 return "Invalid";
740 }
741}
742
718extern "C" LPCSTR LoggingRelationTypeToString( 743extern "C" LPCSTR LoggingRelationTypeToString(
719 __in BOOTSTRAPPER_RELATION_TYPE type 744 __in BOOTSTRAPPER_RELATION_TYPE type
720 ) 745 )
@@ -731,8 +756,10 @@ extern "C" LPCSTR LoggingRelationTypeToString(
731 return "Addon"; 756 return "Addon";
732 case BOOTSTRAPPER_RELATION_PATCH: 757 case BOOTSTRAPPER_RELATION_PATCH:
733 return "Patch"; 758 return "Patch";
734 case BOOTSTRAPPER_RELATION_DEPENDENT: 759 case BOOTSTRAPPER_RELATION_DEPENDENT_ADDON:
735 return "Dependent"; 760 return "DependentAddon";
761 case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH:
762 return "DependentPatch";
736 case BOOTSTRAPPER_RELATION_UPDATE: 763 case BOOTSTRAPPER_RELATION_UPDATE:
737 return "Update"; 764 return "Update";
738 default: 765 default:
diff --git a/src/burn/engine/logging.h b/src/burn/engine/logging.h
index ef603931..15eb298a 100644
--- a/src/burn/engine/logging.h
+++ b/src/burn/engine/logging.h
@@ -154,6 +154,10 @@ LPCSTR LoggingResumeModeToString(
154 __in BURN_RESUME_MODE resumeMode 154 __in BURN_RESUME_MODE resumeMode
155 ); 155 );
156 156
157LPCSTR LoggingPlanRelationTypeToString(
158 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE type
159 );
160
157LPCSTR LoggingRelationTypeToString( 161LPCSTR LoggingRelationTypeToString(
158 __in BOOTSTRAPPER_RELATION_TYPE type 162 __in BOOTSTRAPPER_RELATION_TYPE type
159 ); 163 );
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index c9337df5..d3cc60f1 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -511,7 +511,7 @@ extern "C" HRESULT PlanForwardCompatibleBundles(
511 511
512 fIgnoreBundle = fRecommendIgnore; 512 fIgnoreBundle = fRecommendIgnore;
513 513
514 hr = UserExperienceOnPlanForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, &fIgnoreBundle); 514 hr = UserExperienceOnPlanForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->detectRelationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, &fIgnoreBundle);
515 ExitOnRootFailure(hr, "BA aborted plan forward compatible bundle."); 515 ExitOnRootFailure(hr, "BA aborted plan forward compatible bundle.");
516 516
517 if (!fIgnoreBundle) 517 if (!fIgnoreBundle)
@@ -621,7 +621,8 @@ extern "C" HRESULT PlanRegistration(
621 { 621 {
622 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; 622 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
623 623
624 if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType) 624 if (BOOTSTRAPPER_RELATION_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
625 BOOTSTRAPPER_RELATION_DEPENDENT_PATCH == pRelatedBundle->planRelationType)
625 { 626 {
626 for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j) 627 for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j)
627 { 628 {
@@ -703,7 +704,8 @@ extern "C" HRESULT PlanRegistration(
703 { 704 {
704 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; 705 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
705 706
706 if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType) 707 if (BOOTSTRAPPER_RELATION_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
708 BOOTSTRAPPER_RELATION_DEPENDENT_PATCH == pRelatedBundle->planRelationType)
707 { 709 {
708 for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j) 710 for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j)
709 { 711 {
@@ -1212,17 +1214,63 @@ LExit:
1212 return hr; 1214 return hr;
1213} 1215}
1214 1216
1215extern "C" HRESULT PlanDefaultRelatedBundleRequestState( 1217extern "C" HRESULT PlanDefaultRelatedBundlePlanType(
1216 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType,
1217 __in BOOTSTRAPPER_RELATION_TYPE relatedBundleRelationType, 1218 __in BOOTSTRAPPER_RELATION_TYPE relatedBundleRelationType,
1218 __in BOOTSTRAPPER_ACTION action,
1219 __in VERUTIL_VERSION* pRegistrationVersion, 1219 __in VERUTIL_VERSION* pRegistrationVersion,
1220 __in VERUTIL_VERSION* pRelatedBundleVersion, 1220 __in VERUTIL_VERSION* pRelatedBundleVersion,
1221 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState 1221 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pPlanRelationType
1222 ) 1222 )
1223{ 1223{
1224 HRESULT hr = S_OK; 1224 HRESULT hr = S_OK;
1225 int nCompareResult = 0; 1225 int nCompareResult = 0;
1226
1227 switch (relatedBundleRelationType)
1228 {
1229 case BOOTSTRAPPER_RELATION_UPGRADE:
1230 hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult);
1231 ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistrationVersion->sczVersion, pRelatedBundleVersion->sczVersion);
1232
1233 if (nCompareResult < 0)
1234 {
1235 *pPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE;
1236 }
1237 else
1238 {
1239 *pPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE;
1240 }
1241 break;
1242 case BOOTSTRAPPER_RELATION_ADDON:
1243 *pPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON;
1244 break;
1245 case BOOTSTRAPPER_RELATION_PATCH:
1246 *pPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH;
1247 break;
1248 case BOOTSTRAPPER_RELATION_DEPENDENT_ADDON:
1249 *pPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON;
1250 break;
1251 case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH:
1252 *pPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH;
1253 break;
1254 case BOOTSTRAPPER_RELATION_DETECT:
1255 break;
1256 default:
1257 hr = E_UNEXPECTED;
1258 ExitOnFailure(hr, "Unexpected relation type encountered during plan: %d", relatedBundleRelationType);
1259 break;
1260 }
1261
1262LExit:
1263 return hr;
1264}
1265
1266extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1267 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType,
1268 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relatedBundleRelationType,
1269 __in BOOTSTRAPPER_ACTION action,
1270 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState
1271 )
1272{
1273 HRESULT hr = S_OK;
1226 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action; 1274 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action;
1227 1275
1228 // Never touch related bundles during Cache. 1276 // Never touch related bundles during Cache.
@@ -1233,17 +1281,14 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1233 1281
1234 switch (relatedBundleRelationType) 1282 switch (relatedBundleRelationType)
1235 { 1283 {
1236 case BOOTSTRAPPER_RELATION_UPGRADE: 1284 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE:
1237 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && !fUninstalling) 1285 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && !fUninstalling)
1238 { 1286 {
1239 hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult); 1287 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
1240 ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistrationVersion ? pRegistrationVersion->sczVersion : NULL, pRelatedBundleVersion ? pRelatedBundleVersion->sczVersion : NULL);
1241
1242 *pRequestState = (nCompareResult < 0) ? BOOTSTRAPPER_REQUEST_STATE_NONE : BOOTSTRAPPER_REQUEST_STATE_ABSENT;
1243 } 1288 }
1244 break; 1289 break;
1245 case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; 1290 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH: __fallthrough;
1246 case BOOTSTRAPPER_RELATION_ADDON: 1291 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON:
1247 if (fUninstalling) 1292 if (fUninstalling)
1248 { 1293 {
1249 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; 1294 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
@@ -1257,7 +1302,8 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1257 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; 1302 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
1258 } 1303 }
1259 break; 1304 break;
1260 case BOOTSTRAPPER_RELATION_DEPENDENT: 1305 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON: __fallthrough;
1306 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH:
1261 // Automatically repair dependent bundles to restore missing 1307 // Automatically repair dependent bundles to restore missing
1262 // packages after uninstall unless we're being upgraded with the 1308 // packages after uninstall unless we're being upgraded with the
1263 // assumption that upgrades are cumulative (as intended). 1309 // assumption that upgrades are cumulative (as intended).
@@ -1266,11 +1312,12 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1266 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; 1312 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
1267 } 1313 }
1268 break; 1314 break;
1269 case BOOTSTRAPPER_RELATION_DETECT: 1315 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE: __fallthrough;
1316 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE:
1270 break; 1317 break;
1271 default: 1318 default:
1272 hr = E_UNEXPECTED; 1319 hr = E_UNEXPECTED;
1273 ExitOnFailure(hr, "Unexpected relation type encountered during plan: %d", relatedBundleRelationType); 1320 ExitOnFailure(hr, "Unexpected plan relation type encountered during plan: %d", relatedBundleRelationType);
1274 break; 1321 break;
1275 } 1322 }
1276 1323
@@ -1278,6 +1325,45 @@ LExit:
1278 return hr; 1325 return hr;
1279} 1326}
1280 1327
1328extern "C" HRESULT PlanRelatedBundlesInitialize(
1329 __in BURN_USER_EXPERIENCE* pUserExperience,
1330 __in BURN_REGISTRATION* pRegistration,
1331 __in BOOTSTRAPPER_RELATION_TYPE /*relationType*/,
1332 __in BURN_PLAN* /*pPlan*/
1333 )
1334{
1335 HRESULT hr = S_OK;
1336
1337 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
1338 {
1339 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
1340
1341 pRelatedBundle->defaultRequestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE;
1342 pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE;
1343 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE;
1344 pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1345 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1346 pRelatedBundle->defaultPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
1347 pRelatedBundle->planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
1348
1349 // Determine the plan relation type even if later it is ignored due to the planned action, the command relation type, or the related bundle not being plannable.
1350 // This gives more information to the BA in case it wants to override default behavior.
1351 // Doing it during plan instead of Detect allows the BA to change its mind without having to go all the way through Detect again.
1352 hr = PlanDefaultRelatedBundlePlanType(pRelatedBundle->detectRelationType, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->defaultPlanRelationType);
1353 ExitOnFailure(hr, "Failed to get default plan type for related bundle.");
1354
1355 pRelatedBundle->planRelationType = pRelatedBundle->defaultPlanRelationType;
1356
1357 hr = UserExperienceOnPlanRelatedBundleType(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->planRelationType);
1358 ExitOnRootFailure(hr, "BA aborted plan related bundle type.");
1359 }
1360
1361 RelatedBundlesSortPlan(&pRegistration->relatedBundles);
1362
1363LExit:
1364 return hr;
1365}
1366
1281extern "C" HRESULT PlanRelatedBundlesBegin( 1367extern "C" HRESULT PlanRelatedBundlesBegin(
1282 __in BURN_USER_EXPERIENCE* pUserExperience, 1368 __in BURN_USER_EXPERIENCE* pUserExperience,
1283 __in BURN_REGISTRATION* pRegistration, 1369 __in BURN_REGISTRATION* pRegistration,
@@ -1302,18 +1388,15 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1302 1388
1303 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) 1389 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
1304 { 1390 {
1305 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; 1391 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgpPlanSortedRelatedBundles[i];
1306 1392
1307 if (!pRelatedBundle->fPlannable) 1393 if (!pRelatedBundle->fPlannable)
1308 { 1394 {
1309 continue; 1395 continue;
1310 } 1396 }
1311 1397
1312 pRelatedBundle->defaultRequestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE; 1398 BOOL fDependent = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
1313 pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE; 1399 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH == pRelatedBundle->planRelationType;
1314 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE;
1315 pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1316 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1317 1400
1318 // Do not execute the same bundle twice. 1401 // Do not execute the same bundle twice.
1319 if (sdAncestors) 1402 if (sdAncestors)
@@ -1321,7 +1404,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1321 hr = DictKeyExists(sdAncestors, pRelatedBundle->package.sczId); 1404 hr = DictKeyExists(sdAncestors, pRelatedBundle->package.sczId);
1322 if (SUCCEEDED(hr)) 1405 if (SUCCEEDED(hr))
1323 { 1406 {
1324 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_RELATED_BUNDLE_SCHEDULED, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType)); 1407 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_RELATED_BUNDLE_SCHEDULED, pRelatedBundle->package.sczId);
1325 continue; 1408 continue;
1326 } 1409 }
1327 else if (E_NOTFOUND != hr) 1410 else if (E_NOTFOUND != hr)
@@ -1329,10 +1412,10 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1329 ExitOnFailure(hr, "Failed to lookup the bundle ID in the ancestors dictionary."); 1412 ExitOnFailure(hr, "Failed to lookup the bundle ID in the ancestors dictionary.");
1330 } 1413 }
1331 } 1414 }
1332 else if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_RELATION_NONE != relationType) 1415 else if (fDependent && BOOTSTRAPPER_RELATION_NONE != relationType)
1333 { 1416 {
1334 // Avoid repair loops for older bundles that do not handle ancestors. 1417 // Avoid repair loops for older bundles that do not handle ancestors.
1335 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_RELATED_BUNDLE_DEPENDENT, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingRelationTypeToString(relationType)); 1418 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_RELATED_BUNDLE_DEPENDENT, pRelatedBundle->package.sczId, LoggingRelationTypeToString(relationType));
1336 continue; 1419 continue;
1337 } 1420 }
1338 1421
@@ -1340,7 +1423,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1340 pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors; 1423 pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
1341 pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory; 1424 pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
1342 1425
1343 hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested); 1426 hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->planRelationType, pPlan->action, &pRelatedBundle->package.requested);
1344 ExitOnFailure(hr, "Failed to get default request state for related bundle."); 1427 ExitOnFailure(hr, "Failed to get default request state for related bundle.");
1345 1428
1346 pRelatedBundle->package.defaultRequested = pRelatedBundle->package.requested; 1429 pRelatedBundle->package.defaultRequested = pRelatedBundle->package.requested;
@@ -1349,7 +1432,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1349 ExitOnRootFailure(hr, "BA aborted plan related bundle."); 1432 ExitOnRootFailure(hr, "BA aborted plan related bundle.");
1350 1433
1351 // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. 1434 // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting.
1352 if (fUninstalling && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) 1435 if (fUninstalling && fDependent && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested)
1353 { 1436 {
1354 if (0 < pRelatedBundle->package.cDependencyProviders) 1437 if (0 < pRelatedBundle->package.cDependencyProviders)
1355 { 1438 {
@@ -1437,7 +1520,11 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1437 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) 1520 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
1438 { 1521 {
1439 DWORD *pdwInsertIndex = NULL; 1522 DWORD *pdwInsertIndex = NULL;
1440 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; 1523 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgpPlanSortedRelatedBundles[i];
1524 BOOL fDependent = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
1525 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH == pRelatedBundle->planRelationType;
1526 BOOL fAddonOrPatch = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON == pRelatedBundle->planRelationType ||
1527 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH == pRelatedBundle->planRelationType;
1441 1528
1442 if (!pRelatedBundle->fPlannable) 1529 if (!pRelatedBundle->fPlannable)
1443 { 1530 {
@@ -1454,7 +1541,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1454 { 1541 {
1455 ExitOnFailure(hr, "Failed to check the dictionary for a related bundle provider key: \"%ls\".", pProvider->sczKey); 1542 ExitOnFailure(hr, "Failed to check the dictionary for a related bundle provider key: \"%ls\".", pProvider->sczKey);
1456 // Key found, so there is an embedded bundle with the same provider key that will be executed. So this related bundle should not be added to the plan 1543 // Key found, so there is an embedded bundle with the same provider key that will be executed. So this related bundle should not be added to the plan
1457 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_RELATED_BUNDLE_EMBEDDED_BUNDLE_NEWER, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), pProvider->sczKey); 1544 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_RELATED_BUNDLE_EMBEDDED_BUNDLE_NEWER, pRelatedBundle->package.sczId, pProvider->sczKey);
1458 continue; 1545 continue;
1459 } 1546 }
1460 else 1547 else
@@ -1464,13 +1551,13 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1464 } 1551 }
1465 1552
1466 // For an uninstall, there is no need to repair dependent bundles if no packages are executing. 1553 // For an uninstall, there is no need to repair dependent bundles if no packages are executing.
1467 if (!fExecutingAnyPackage && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pRelatedBundle->package.requested && fUninstalling) 1554 if (!fExecutingAnyPackage && fDependent && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pRelatedBundle->package.requested && fUninstalling)
1468 { 1555 {
1469 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1556 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1470 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType)); 1557 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR, pRelatedBundle->package.sczId);
1471 } 1558 }
1472 1559
1473 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1560 if (fAddonOrPatch)
1474 { 1561 {
1475 // Addon and patch bundles will be passed a list of dependencies to ignore for planning. 1562 // Addon and patch bundles will be passed a list of dependencies to ignore for planning.
1476 hr = StrAllocString(&pRelatedBundle->package.Bundle.sczIgnoreDependencies, sczIgnoreDependencies, 0); 1563 hr = StrAllocString(&pRelatedBundle->package.Bundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
@@ -1489,7 +1576,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1489 ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId); 1576 ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1490 1577
1491 // Calculate package states based on reference count for addon and patch related bundles. 1578 // Calculate package states based on reference count for addon and patch related bundles.
1492 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1579 if (fAddonOrPatch)
1493 { 1580 {
1494 hr = DependencyPlanPackageBegin(pRegistration->fPerMachine, &pRelatedBundle->package, pPlan); 1581 hr = DependencyPlanPackageBegin(pRegistration->fPerMachine, &pRelatedBundle->package, pPlan);
1495 ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId); 1582 ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId);
@@ -1505,7 +1592,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1505 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId); 1592 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1506 1593
1507 // Calculate package states based on reference count for addon and patch related bundles. 1594 // Calculate package states based on reference count for addon and patch related bundles.
1508 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1595 if (fAddonOrPatch)
1509 { 1596 {
1510 hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan); 1597 hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan);
1511 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId); 1598 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId);
@@ -1517,7 +1604,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1517 PlannedExecutePackage(pPlan, &pRelatedBundle->package); 1604 PlannedExecutePackage(pPlan, &pRelatedBundle->package);
1518 } 1605 }
1519 } 1606 }
1520 else if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1607 else if (fAddonOrPatch)
1521 { 1608 {
1522 // Make sure the package is properly ref-counted even if no plan is requested. 1609 // Make sure the package is properly ref-counted even if no plan is requested.
1523 hr = DependencyPlanPackageBegin(pRegistration->fPerMachine, &pRelatedBundle->package, pPlan); 1610 hr = DependencyPlanPackageBegin(pRegistration->fPerMachine, &pRelatedBundle->package, pPlan);
@@ -1530,7 +1617,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1530 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId); 1617 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId);
1531 } 1618 }
1532 1619
1533 if (fInstallingAnyPackage && BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType) 1620 if (fInstallingAnyPackage && BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE == pRelatedBundle->planRelationType)
1534 { 1621 {
1535 BURN_EXECUTE_ACTION* pAction = NULL; 1622 BURN_EXECUTE_ACTION* pAction = NULL;
1536 1623
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 63bcd3ce..1f3fe07c 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -316,6 +316,12 @@ HRESULT PlanSetVariables(
316 __in BOOTSTRAPPER_ACTION action, 316 __in BOOTSTRAPPER_ACTION action,
317 __in BURN_VARIABLES* pVariables 317 __in BURN_VARIABLES* pVariables
318 ); 318 );
319HRESULT PlanDefaultRelatedBundlePlanType(
320 __in BOOTSTRAPPER_RELATION_TYPE relatedBundleRelationType,
321 __in VERUTIL_VERSION* pRegistrationVersion,
322 __in VERUTIL_VERSION* pRelatedBundleVersion,
323 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pPlanRelationType
324 );
319HRESULT PlanDefaultPackageRequestState( 325HRESULT PlanDefaultPackageRequestState(
320 __in BURN_PACKAGE_TYPE packageType, 326 __in BURN_PACKAGE_TYPE packageType,
321 __in BOOTSTRAPPER_PACKAGE_STATE currentState, 327 __in BOOTSTRAPPER_PACKAGE_STATE currentState,
@@ -383,12 +389,16 @@ HRESULT PlanExecutePackage(
383 ); 389 );
384HRESULT PlanDefaultRelatedBundleRequestState( 390HRESULT PlanDefaultRelatedBundleRequestState(
385 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType, 391 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType,
386 __in BOOTSTRAPPER_RELATION_TYPE relatedBundleRelationType, 392 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relatedBundleRelationType,
387 __in BOOTSTRAPPER_ACTION action, 393 __in BOOTSTRAPPER_ACTION action,
388 __in VERUTIL_VERSION* pRegistrationVersion,
389 __in VERUTIL_VERSION* pRelatedBundleVersion,
390 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState 394 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState
391 ); 395 );
396HRESULT PlanRelatedBundlesInitialize(
397 __in BURN_USER_EXPERIENCE* pUserExperience,
398 __in BURN_REGISTRATION* pRegistration,
399 __in BOOTSTRAPPER_RELATION_TYPE relationType,
400 __in BURN_PLAN* pPlan
401 );
392HRESULT PlanRelatedBundlesBegin( 402HRESULT PlanRelatedBundlesBegin(
393 __in BURN_USER_EXPERIENCE* pUserExperience, 403 __in BURN_USER_EXPERIENCE* pUserExperience,
394 __in BURN_REGISTRATION* pRegistration, 404 __in BURN_REGISTRATION* pRegistration,
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index 545c390b..6bae2e7b 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -614,7 +614,28 @@ extern "C" HRESULT RegistrationDetectRelatedBundles(
614 hr = RelatedBundlesInitializeForScope(FALSE, pRegistration, &pRegistration->relatedBundles); 614 hr = RelatedBundlesInitializeForScope(FALSE, pRegistration, &pRegistration->relatedBundles);
615 ExitOnFailure(hr, "Failed to initialize per-user related bundles."); 615 ExitOnFailure(hr, "Failed to initialize per-user related bundles.");
616 616
617 RelatedBundlesSort(&pRegistration->relatedBundles); 617 RelatedBundlesSortDetect(&pRegistration->relatedBundles);
618
619LExit:
620 return hr;
621}
622
623extern "C" HRESULT RegistrationPlanInitialize(
624 __in BURN_REGISTRATION* pRegistration
625 )
626{
627 HRESULT hr = S_OK;
628
629 if (pRegistration->relatedBundles.cRelatedBundles && !pRegistration->relatedBundles.rgpPlanSortedRelatedBundles)
630 {
631 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pRegistration->relatedBundles.rgpPlanSortedRelatedBundles), pRegistration->relatedBundles.cRelatedBundles, sizeof(BURN_RELATED_BUNDLE*), 5);
632 ExitOnFailure(hr, "Failed to initialize plan related bundles array.");
633
634 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
635 {
636 pRegistration->relatedBundles.rgpPlanSortedRelatedBundles[i] = pRegistration->relatedBundles.rgRelatedBundles + i;
637 }
638 }
618 639
619LExit: 640LExit:
620 return hr; 641 return hr;
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h
index bfaab1f1..e4dd6f4a 100644
--- a/src/burn/engine/registration.h
+++ b/src/burn/engine/registration.h
@@ -53,7 +53,9 @@ typedef struct _BURN_UPDATE_REGISTRATION
53 53
54typedef struct _BURN_RELATED_BUNDLE 54typedef struct _BURN_RELATED_BUNDLE
55{ 55{
56 BOOTSTRAPPER_RELATION_TYPE relationType; 56 BOOTSTRAPPER_RELATION_TYPE detectRelationType;
57 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE defaultPlanRelationType;
58 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE planRelationType;
57 BOOL fForwardCompatible; 59 BOOL fForwardCompatible;
58 60
59 VERUTIL_VERSION* pVersion; 61 VERUTIL_VERSION* pVersion;
@@ -71,6 +73,7 @@ typedef struct _BURN_RELATED_BUNDLES
71{ 73{
72 BURN_RELATED_BUNDLE* rgRelatedBundles; 74 BURN_RELATED_BUNDLE* rgRelatedBundles;
73 DWORD cRelatedBundles; 75 DWORD cRelatedBundles;
76 BURN_RELATED_BUNDLE** rgpPlanSortedRelatedBundles;
74} BURN_RELATED_BUNDLES; 77} BURN_RELATED_BUNDLES;
75 78
76typedef struct _BURN_SOFTWARE_TAG 79typedef struct _BURN_SOFTWARE_TAG
@@ -185,6 +188,9 @@ HRESULT RegistrationDetectResumeType(
185HRESULT RegistrationDetectRelatedBundles( 188HRESULT RegistrationDetectRelatedBundles(
186 __in BURN_REGISTRATION* pRegistration 189 __in BURN_REGISTRATION* pRegistration
187 ); 190 );
191HRESULT RegistrationPlanInitialize(
192 __in BURN_REGISTRATION* pRegistration
193 );
188HRESULT RegistrationSessionBegin( 194HRESULT RegistrationSessionBegin(
189 __in_z LPCWSTR wzEngineWorkingPath, 195 __in_z LPCWSTR wzEngineWorkingPath,
190 __in BURN_REGISTRATION* pRegistration, 196 __in BURN_REGISTRATION* pRegistration,
diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp
index e6633131..58911711 100644
--- a/src/burn/engine/relatedbundle.cpp
+++ b/src/burn/engine/relatedbundle.cpp
@@ -10,11 +10,16 @@ typedef struct _BUNDLE_QUERY_CONTEXT
10 10
11// internal function declarations 11// internal function declarations
12 12
13static __callback int __cdecl CompareRelatedBundles( 13static __callback int __cdecl CompareRelatedBundlesDetect(
14 __in void* pvContext, 14 __in void* pvContext,
15 __in const void* pvLeft, 15 __in const void* pvLeft,
16 __in const void* pvRight 16 __in const void* pvRight
17); 17 );
18static __callback int __cdecl CompareRelatedBundlesPlan(
19 __in void* /*pvContext*/,
20 __in const void* pvLeft,
21 __in const void* pvRight
22 );
18static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback( 23static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback(
19 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, 24 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
20 __in_opt LPVOID pvContext 25 __in_opt LPVOID pvContext
@@ -88,6 +93,8 @@ extern "C" void RelatedBundlesUninitialize(
88 MemFree(pRelatedBundles->rgRelatedBundles); 93 MemFree(pRelatedBundles->rgRelatedBundles);
89 } 94 }
90 95
96 ReleaseMem(pRelatedBundles->rgpPlanSortedRelatedBundles);
97
91 memset(pRelatedBundles, 0, sizeof(BURN_RELATED_BUNDLES)); 98 memset(pRelatedBundles, 0, sizeof(BURN_RELATED_BUNDLES));
92} 99}
93 100
@@ -122,17 +129,24 @@ LExit:
122 return hr; 129 return hr;
123} 130}
124 131
125extern "C" void RelatedBundlesSort( 132extern "C" void RelatedBundlesSortDetect(
133 __in BURN_RELATED_BUNDLES* pRelatedBundles
134 )
135{
136 qsort_s(pRelatedBundles->rgRelatedBundles, pRelatedBundles->cRelatedBundles, sizeof(BURN_RELATED_BUNDLE), CompareRelatedBundlesDetect, NULL);
137}
138
139extern "C" void RelatedBundlesSortPlan(
126 __in BURN_RELATED_BUNDLES* pRelatedBundles 140 __in BURN_RELATED_BUNDLES* pRelatedBundles
127 ) 141 )
128{ 142{
129 qsort_s(pRelatedBundles->rgRelatedBundles, pRelatedBundles->cRelatedBundles, sizeof(BURN_RELATED_BUNDLE), CompareRelatedBundles, NULL); 143 qsort_s(pRelatedBundles->rgpPlanSortedRelatedBundles, pRelatedBundles->cRelatedBundles, sizeof(BURN_RELATED_BUNDLE*), CompareRelatedBundlesPlan, NULL);
130} 144}
131 145
132 146
133// internal helper functions 147// internal helper functions
134 148
135static __callback int __cdecl CompareRelatedBundles( 149static __callback int __cdecl CompareRelatedBundlesDetect(
136 __in void* /*pvContext*/, 150 __in void* /*pvContext*/,
137 __in const void* pvLeft, 151 __in const void* pvLeft,
138 __in const void* pvRight 152 __in const void* pvRight
@@ -143,18 +157,61 @@ static __callback int __cdecl CompareRelatedBundles(
143 const BURN_RELATED_BUNDLE* pBundleRight = static_cast<const BURN_RELATED_BUNDLE*>(pvRight); 157 const BURN_RELATED_BUNDLE* pBundleRight = static_cast<const BURN_RELATED_BUNDLE*>(pvRight);
144 158
145 // Sort by relation type, then version, then bundle id. 159 // Sort by relation type, then version, then bundle id.
146 if (pBundleLeft->relationType != pBundleRight->relationType) 160 if (pBundleLeft->detectRelationType != pBundleRight->detectRelationType)
147 { 161 {
148 // Upgrade bundles last, everything else according to the enum. 162 // Upgrade bundles last, everything else according to the enum.
149 if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleLeft->relationType) 163 if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleLeft->detectRelationType)
150 { 164 {
151 ret = 1; 165 ret = 1;
152 } 166 }
153 else if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleRight->relationType) 167 else if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleRight->detectRelationType)
154 { 168 {
155 ret = -1; 169 ret = -1;
156 } 170 }
157 else if (pBundleLeft->relationType < pBundleRight->relationType) 171 else if (pBundleLeft->detectRelationType < pBundleRight->detectRelationType)
172 {
173 ret = -1;
174 }
175 else
176 {
177 ret = 1;
178 }
179 }
180 else
181 {
182 VerCompareParsedVersions(pBundleLeft->pVersion, pBundleRight->pVersion, &ret);
183 if (0 == ret)
184 {
185 ret = ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pBundleLeft->package.sczId, -1, pBundleRight->package.sczId, -1) - 2;
186 }
187 }
188
189 return ret;
190}
191
192static __callback int __cdecl CompareRelatedBundlesPlan(
193 __in void* /*pvContext*/,
194 __in const void* pvLeft,
195 __in const void* pvRight
196 )
197{
198 int ret = 0;
199 const BURN_RELATED_BUNDLE* pBundleLeft = *reinterpret_cast<BURN_RELATED_BUNDLE**>(const_cast<void*>(pvLeft));
200 const BURN_RELATED_BUNDLE* pBundleRight = *reinterpret_cast<BURN_RELATED_BUNDLE**>(const_cast<void*>(pvRight));
201
202 // Sort by relation type, then version, then bundle id.
203 if (pBundleLeft->planRelationType != pBundleRight->planRelationType)
204 {
205 // Upgrade bundles last, everything else according to the enum.
206 if (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE == pBundleLeft->planRelationType)
207 {
208 ret = 1;
209 }
210 else if (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE == pBundleRight->planRelationType)
211 {
212 ret = -1;
213 }
214 else if (pBundleLeft->planRelationType < pBundleRight->planRelationType)
158 { 215 {
159 ret = -1; 216 ret = -1;
160 } 217 }
@@ -191,6 +248,30 @@ LExit:
191 return result; 248 return result;
192} 249}
193 250
251static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType(
252 __in BUNDLE_RELATION_TYPE relationType
253 )
254{
255 switch (relationType)
256 {
257 case BUNDLE_RELATION_DETECT:
258 return BOOTSTRAPPER_RELATION_DETECT;
259 case BUNDLE_RELATION_UPGRADE:
260 return BOOTSTRAPPER_RELATION_UPGRADE;
261 case BUNDLE_RELATION_ADDON:
262 return BOOTSTRAPPER_RELATION_ADDON;
263 case BUNDLE_RELATION_PATCH:
264 return BOOTSTRAPPER_RELATION_PATCH;
265 case BUNDLE_RELATION_DEPENDENT_ADDON:
266 return BOOTSTRAPPER_RELATION_DEPENDENT_ADDON;
267 case BUNDLE_RELATION_DEPENDENT_PATCH:
268 return BOOTSTRAPPER_RELATION_DEPENDENT_PATCH;
269 default:
270 AssertSz(BUNDLE_RELATION_NONE == relationType, "Unknown BUNDLE_RELATION_TYPE");
271 return BOOTSTRAPPER_RELATION_NONE;
272 }
273}
274
194static HRESULT LoadIfRelatedBundle( 275static HRESULT LoadIfRelatedBundle(
195 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, 276 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
196 __in BURN_REGISTRATION* pRegistration, 277 __in BURN_REGISTRATION* pRegistration,
@@ -199,7 +280,7 @@ static HRESULT LoadIfRelatedBundle(
199{ 280{
200 HRESULT hr = S_OK; 281 HRESULT hr = S_OK;
201 BOOL fPerMachine = BUNDLE_INSTALL_CONTEXT_MACHINE == pBundle->installContext; 282 BOOL fPerMachine = BUNDLE_INSTALL_CONTEXT_MACHINE == pBundle->installContext;
202 BOOTSTRAPPER_RELATION_TYPE relationType = (BOOTSTRAPPER_RELATION_TYPE)pBundle->relationType; 283 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pBundle->relationType);
203 BURN_RELATED_BUNDLE* pRelatedBundle = NULL; 284 BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
204 285
205 // If we found our bundle id, it's not a related bundle. 286 // If we found our bundle id, it's not a related bundle.
@@ -316,11 +397,11 @@ static HRESULT LoadRelatedBundleFromKey(
316 } 397 }
317 ExitOnFailure(hr, "Failed to read tag from registry for bundle: %ls", wzRelatedBundleId); 398 ExitOnFailure(hr, "Failed to read tag from registry for bundle: %ls", wzRelatedBundleId);
318 399
319 pRelatedBundle->relationType = relationType; 400 pRelatedBundle->detectRelationType = relationType;
320 401
321 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, 402 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId,
322#ifdef DEBUG 403#ifdef DEBUG
323 pRelatedBundle->relationType, 404 pRelatedBundle->detectRelationType,
324#endif 405#endif
325 fCached, sczCachePath, qwFileSize, pBundleDependencyProvider); 406 fCached, sczCachePath, qwFileSize, pBundleDependencyProvider);
326 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId); 407 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId);
diff --git a/src/burn/engine/relatedbundle.h b/src/burn/engine/relatedbundle.h
index be039421..24469f3d 100644
--- a/src/burn/engine/relatedbundle.h
+++ b/src/burn/engine/relatedbundle.h
@@ -19,7 +19,10 @@ HRESULT RelatedBundleFindById(
19 __in_z LPCWSTR wzId, 19 __in_z LPCWSTR wzId,
20 __out BURN_RELATED_BUNDLE** ppRelatedBundle 20 __out BURN_RELATED_BUNDLE** ppRelatedBundle
21 ); 21 );
22void RelatedBundlesSort( 22void RelatedBundlesSortDetect(
23 __in BURN_RELATED_BUNDLES* pRelatedBundles
24 );
25void RelatedBundlesSortPlan(
23 __in BURN_RELATED_BUNDLES* pRelatedBundles 26 __in BURN_RELATED_BUNDLES* pRelatedBundles
24 ); 27 );
25 28
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index f299772b..8668cf6f 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad(
104 args.pCommand = pCommand; 104 args.pCommand = pCommand;
105 args.pfnBootstrapperEngineProc = EngineForApplicationProc; 105 args.pfnBootstrapperEngineProc = EngineForApplicationProc;
106 args.pvBootstrapperEngineProcContext = pEngineContext; 106 args.pvBootstrapperEngineProcContext = pEngineContext;
107 args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 4, 0); 107 args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 14, 0);
108 108
109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); 109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS);
110 110
@@ -2176,6 +2176,36 @@ LExit:
2176 return hr; 2176 return hr;
2177} 2177}
2178 2178
2179EXTERN_C BAAPI UserExperienceOnPlanRelatedBundleType(
2180 __in BURN_USER_EXPERIENCE* pUserExperience,
2181 __in_z LPCWSTR wzBundleId,
2182 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType
2183 )
2184{
2185 HRESULT hr = S_OK;
2186 BA_ONPLANRELATEDBUNDLETYPE_ARGS args = { };
2187 BA_ONPLANRELATEDBUNDLETYPE_RESULTS results = { };
2188
2189 args.cbSize = sizeof(args);
2190 args.wzBundleId = wzBundleId;
2191 args.recommendedType = *pRequestedType;
2192
2193 results.cbSize = sizeof(results);
2194 results.requestedType = *pRequestedType;
2195
2196 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE, &args, &results);
2197 ExitOnFailure(hr, "BA OnPlanRelatedBundleType failed.");
2198
2199 if (results.fCancel)
2200 {
2201 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
2202 }
2203 *pRequestedType = results.requestedType;
2204
2205LExit:
2206 return hr;
2207}
2208
2179EXTERN_C BAAPI UserExperienceOnPlanRestoreRelatedBundle( 2209EXTERN_C BAAPI UserExperienceOnPlanRestoreRelatedBundle(
2180 __in BURN_USER_EXPERIENCE* pUserExperience, 2210 __in BURN_USER_EXPERIENCE* pUserExperience,
2181 __in_z LPCWSTR wzBundleId, 2211 __in_z LPCWSTR wzBundleId,
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index 37fa5174..11344365 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -497,6 +497,11 @@ BAAPI UserExperienceOnPlanRelatedBundle(
497 __in_z LPCWSTR wzBundleId, 497 __in_z LPCWSTR wzBundleId,
498 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState 498 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState
499 ); 499 );
500BAAPI UserExperienceOnPlanRelatedBundleType(
501 __in BURN_USER_EXPERIENCE* pUserExperience,
502 __in_z LPCWSTR wzBundleId,
503 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType
504 );
500BAAPI UserExperienceOnPlanRestoreRelatedBundle( 505BAAPI UserExperienceOnPlanRestoreRelatedBundle(
501 __in BURN_USER_EXPERIENCE* pUserExperience, 506 __in BURN_USER_EXPERIENCE* pUserExperience,
502 __in_z LPCWSTR wzBundleId, 507 __in_z LPCWSTR wzBundleId,
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 881a960a..7852f1c9 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -18,6 +18,8 @@ static BOOL vfUsePackageRequestState = FALSE;
18static BOOTSTRAPPER_REQUEST_STATE vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 18static BOOTSTRAPPER_REQUEST_STATE vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
19static BOOL vfUseRelatedBundleRequestState = FALSE; 19static BOOL vfUseRelatedBundleRequestState = FALSE;
20static BOOTSTRAPPER_REQUEST_STATE vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 20static BOOTSTRAPPER_REQUEST_STATE vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
21static BOOL vfUseRelatedBundlePlanType = FALSE;
22static BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE vRelatedBundlePlanType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
21 23
22static BURN_DEPENDENCY_ACTION registerActions1[] = { BURN_DEPENDENCY_ACTION_REGISTER }; 24static BURN_DEPENDENCY_ACTION registerActions1[] = { BURN_DEPENDENCY_ACTION_REGISTER };
23static BURN_DEPENDENCY_ACTION unregisterActions1[] = { BURN_DEPENDENCY_ACTION_UNREGISTER }; 25static BURN_DEPENDENCY_ACTION unregisterActions1[] = { BURN_DEPENDENCY_ACTION_UNREGISTER };
@@ -52,7 +54,7 @@ namespace Bootstrapper
52 54
53 InitializeEngineStateForCorePlan(wzMsiTransactionManifestFileName, pEngineState); 55 InitializeEngineStateForCorePlan(wzMsiTransactionManifestFileName, pEngineState);
54 DetectPackagesAsAbsent(pEngineState); 56 DetectPackagesAsAbsent(pEngineState);
55 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"1.0.0.0"); 57 DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"1.0.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
56 58
57 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL); 59 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
58 NativeAssert::Succeeded(hr, "CorePlan failed"); 60 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -375,6 +377,122 @@ namespace Bootstrapper
375 } 377 }
376 378
377 [Fact] 379 [Fact]
380 void RelatedBundlesAreSortedByPlanType()
381 {
382 HRESULT hr = S_OK;
383 BURN_ENGINE_STATE engineState = { };
384 BURN_ENGINE_STATE* pEngineState = &engineState;
385 BURN_PLAN* pPlan = &engineState.plan;
386
387 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
388 DetectAttachedContainerAsAttached(pEngineState);
389 DetectPackagesAsAbsent(pEngineState);
390 DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
391 DetectRelatedBundle(pEngineState, L"{6B2D8401-C0C2-4060-BFEF-5DDFD04BD586}", L"0.2.0.0", BOOTSTRAPPER_RELATION_PATCH);
392 DetectRelatedBundle(pEngineState, L"{5C80A327-61B9-44CF-A6D4-64C45F4F90A9}", L"0.4.0.0", BOOTSTRAPPER_RELATION_ADDON);
393 DetectRelatedBundle(pEngineState, L"{33A8757F-32EA-4974-888E-D15547259B3C}", L"0.3.0.0", BOOTSTRAPPER_RELATION_DEPENDENT_PATCH);
394 DetectRelatedBundle(pEngineState, L"{59CD5A25-0398-41CA-AD53-AD8C061E2A1A}", L"0.7.0.0", BOOTSTRAPPER_RELATION_DEPENDENT_ADDON);
395
396 RelatedBundlesSortDetect(&pEngineState->registration.relatedBundles);
397 NativeAssert::StringEqual(L"{5C80A327-61B9-44CF-A6D4-64C45F4F90A9}", pEngineState->registration.relatedBundles.rgRelatedBundles[0].package.sczId);
398 NativeAssert::StringEqual(L"{6B2D8401-C0C2-4060-BFEF-5DDFD04BD586}", pEngineState->registration.relatedBundles.rgRelatedBundles[1].package.sczId);
399 NativeAssert::StringEqual(L"{59CD5A25-0398-41CA-AD53-AD8C061E2A1A}", pEngineState->registration.relatedBundles.rgRelatedBundles[2].package.sczId);
400 NativeAssert::StringEqual(L"{33A8757F-32EA-4974-888E-D15547259B3C}", pEngineState->registration.relatedBundles.rgRelatedBundles[3].package.sczId);
401 NativeAssert::StringEqual(L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", pEngineState->registration.relatedBundles.rgRelatedBundles[4].package.sczId);
402
403 vfUseRelatedBundlePlanType = TRUE;
404 vRelatedBundlePlanType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE;
405
406 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
407 NativeAssert::Succeeded(hr, "CorePlan failed");
408
409 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
410 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
411 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
412
413 BOOL fRollback = FALSE;
414 DWORD dwIndex = 0;
415 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
416 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
417 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
418 Assert::Equal(dwIndex, pPlan->cCacheActions);
419
420 fRollback = TRUE;
421 dwIndex = 0;
422 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA");
423 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
424 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
425
426 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
427 Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
428
429 fRollback = FALSE;
430 dwIndex = 0;
431 DWORD dwExecuteCheckpointId = 2;
432 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
433 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
434 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
435 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
436 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
437 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
438 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0);
439 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
440 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1);
441 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
442 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
443 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
444 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{6B2D8401-C0C2-4060-BFEF-5DDFD04BD586}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
445 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{33A8757F-32EA-4974-888E-D15547259B3C}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
446 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{5C80A327-61B9-44CF-A6D4-64C45F4F90A9}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
447 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{59CD5A25-0398-41CA-AD53-AD8C061E2A1A}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
448 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
449 Assert::Equal(dwIndex, pPlan->cExecuteActions);
450
451 fRollback = TRUE;
452 dwIndex = 0;
453 dwExecuteCheckpointId = 2;
454 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
455 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
456 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
457 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
458 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
459 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0);
460 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
461 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1);
462 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
463 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
464 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
465 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
466 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{6B2D8401-C0C2-4060-BFEF-5DDFD04BD586}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
467 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{33A8757F-32EA-4974-888E-D15547259B3C}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
468 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{5C80A327-61B9-44CF-A6D4-64C45F4F90A9}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
469 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{59CD5A25-0398-41CA-AD53-AD8C061E2A1A}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
470 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
471 Assert::Equal(dwIndex, pPlan->cRollbackActions);
472
473 Assert::Equal(6ul, pPlan->cExecutePackagesTotal);
474 Assert::Equal(7ul, pPlan->cOverallProgressTicksTotal);
475
476 dwIndex = 0;
477 ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{6B2D8401-C0C2-4060-BFEF-5DDFD04BD586}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
478 ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{33A8757F-32EA-4974-888E-D15547259B3C}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
479 ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{5C80A327-61B9-44CF-A6D4-64C45F4F90A9}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
480 ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{59CD5A25-0398-41CA-AD53-AD8C061E2A1A}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
481 ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
482 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
483
484 dwIndex = 0;
485 Assert::Equal(dwIndex, pPlan->cCleanActions);
486
487 UINT uIndex = 0;
488 ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL);
489 Assert::Equal(uIndex, pPlan->cPlannedProviders);
490
491 Assert::Equal(1ul, pEngineState->packages.cPackages);
492 ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT);
493 }
494
495 [Fact]
378 void RelatedBundleMissingFromCacheTest() 496 void RelatedBundleMissingFromCacheTest()
379 { 497 {
380 HRESULT hr = S_OK; 498 HRESULT hr = S_OK;
@@ -385,7 +503,7 @@ namespace Bootstrapper
385 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 503 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
386 DetectAttachedContainerAsAttached(pEngineState); 504 DetectAttachedContainerAsAttached(pEngineState);
387 DetectPackagesAsAbsent(pEngineState); 505 DetectPackagesAsAbsent(pEngineState);
388 BURN_RELATED_BUNDLE* pRelatedBundle = DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); 506 BURN_RELATED_BUNDLE* pRelatedBundle = DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
389 pRelatedBundle->fPlannable = FALSE; 507 pRelatedBundle->fPlannable = FALSE;
390 508
391 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL); 509 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
@@ -473,7 +591,7 @@ namespace Bootstrapper
473 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 591 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
474 DetectAttachedContainerAsAttached(pEngineState); 592 DetectAttachedContainerAsAttached(pEngineState);
475 DetectPackagesAsAbsent(pEngineState); 593 DetectPackagesAsAbsent(pEngineState);
476 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); 594 DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
477 595
478 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_CACHE); 596 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_CACHE);
479 NativeAssert::Succeeded(hr, "CorePlan failed"); 597 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -546,7 +664,7 @@ namespace Bootstrapper
546 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 664 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
547 DetectAttachedContainerAsAttached(pEngineState); 665 DetectAttachedContainerAsAttached(pEngineState);
548 DetectPackagesAsAbsent(pEngineState); 666 DetectPackagesAsAbsent(pEngineState);
549 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); 667 DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
550 668
551 vfUsePackageRequestState = TRUE; 669 vfUsePackageRequestState = TRUE;
552 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT; 670 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT;
@@ -621,7 +739,7 @@ namespace Bootstrapper
621 739
622 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 740 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
623 DetectPackagesAsPresentAndCached(pEngineState); 741 DetectPackagesAsPresentAndCached(pEngineState);
624 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); 742 DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
625 743
626 vfUsePackageRequestState = TRUE; 744 vfUsePackageRequestState = TRUE;
627 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT; 745 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
@@ -703,7 +821,7 @@ namespace Bootstrapper
703 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 821 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
704 DetectAttachedContainerAsAttached(pEngineState); 822 DetectAttachedContainerAsAttached(pEngineState);
705 DetectPackagesAsAbsent(pEngineState); 823 DetectPackagesAsAbsent(pEngineState);
706 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0"); 824 DetectRelatedBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0", BOOTSTRAPPER_RELATION_UPGRADE);
707 825
708 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL); 826 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
709 NativeAssert::Succeeded(hr, "CorePlan failed"); 827 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -1475,6 +1593,7 @@ namespace Bootstrapper
1475 1593
1476 vfUsePackageRequestState = FALSE; 1594 vfUsePackageRequestState = FALSE;
1477 vfUseRelatedBundleRequestState = FALSE; 1595 vfUseRelatedBundleRequestState = FALSE;
1596 vfUseRelatedBundlePlanType = FALSE;
1478 1597
1479 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); 1598 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
1480 1599
@@ -1686,10 +1805,11 @@ namespace Bootstrapper
1686 } 1805 }
1687 } 1806 }
1688 1807
1689 BURN_RELATED_BUNDLE* DetectUpgradeBundle( 1808 BURN_RELATED_BUNDLE* DetectRelatedBundle(
1690 __in BURN_ENGINE_STATE* pEngineState, 1809 __in BURN_ENGINE_STATE* pEngineState,
1691 __in LPCWSTR wzId, 1810 __in LPCWSTR wzId,
1692 __in LPCWSTR wzVersion 1811 __in LPCWSTR wzVersion,
1812 __in BOOTSTRAPPER_RELATION_TYPE relationType
1693 ) 1813 )
1694 { 1814 {
1695 HRESULT hr = S_OK; 1815 HRESULT hr = S_OK;
@@ -1717,11 +1837,11 @@ namespace Bootstrapper
1717 NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion); 1837 NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion);
1718 1838
1719 pRelatedBundle->fPlannable = TRUE; 1839 pRelatedBundle->fPlannable = TRUE;
1720 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; 1840 pRelatedBundle->detectRelationType = relationType;
1721 1841
1722 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, TRUE, TRUE, wzId, 1842 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, TRUE, TRUE, wzId,
1723#ifdef DEBUG 1843#ifdef DEBUG
1724 pRelatedBundle->relationType, 1844 pRelatedBundle->detectRelationType,
1725#endif 1845#endif
1726 TRUE, wzFilePath, 0, &dependencyProvider); 1846 TRUE, wzFilePath, 0, &dependencyProvider);
1727 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); 1847 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
@@ -1746,7 +1866,7 @@ namespace Bootstrapper
1746 pEngineState->command.relationType = BOOTSTRAPPER_RELATION_UPGRADE; 1866 pEngineState->command.relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1747 1867
1748 DetectPackagesAsPresentAndCached(pEngineState); 1868 DetectPackagesAsPresentAndCached(pEngineState);
1749 DetectUpgradeBundle(pEngineState, wzId, wzVersion); 1869 DetectRelatedBundle(pEngineState, wzId, wzVersion, BOOTSTRAPPER_RELATION_UPGRADE);
1750 1870
1751 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) 1871 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
1752 { 1872 {
@@ -2199,6 +2319,13 @@ static HRESULT WINAPI PlanTestBAProc(
2199 pResults->requestedState = vRelatedBundleRequestState; 2319 pResults->requestedState = vRelatedBundleRequestState;
2200 } 2320 }
2201 break; 2321 break;
2322 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE:
2323 if (vfUseRelatedBundlePlanType)
2324 {
2325 BA_ONPLANRELATEDBUNDLETYPE_RESULTS* pResults = reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults);
2326 pResults->requestedType = vRelatedBundlePlanType;
2327 }
2328 break;
2202 } 2329 }
2203 2330
2204 return S_OK; 2331 return S_OK;
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index 8c7bce7e..91033a26 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -169,6 +169,9 @@ static LPCSTR LoggingBoolToString(
169static LPCSTR LoggingRequestStateToString( 169static LPCSTR LoggingRequestStateToString(
170 __in BOOTSTRAPPER_REQUEST_STATE requestState 170 __in BOOTSTRAPPER_REQUEST_STATE requestState
171 ); 171 );
172static LPCSTR LoggingPlanRelationTypeToString(
173 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE type
174 );
172static LPCSTR LoggingMsiFeatureStateToString( 175static LPCSTR LoggingMsiFeatureStateToString(
173 __in BOOTSTRAPPER_FEATURE_STATE featureState 176 __in BOOTSTRAPPER_FEATURE_STATE featureState
174 ); 177 );
@@ -1436,6 +1439,12 @@ public: // IBootstrapperApplication
1436 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: 1439 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE:
1437 OnPlannedCompatiblePackageFallback(reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_RESULTS*>(pvResults)); 1440 OnPlannedCompatiblePackageFallback(reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_RESULTS*>(pvResults));
1438 break; 1441 break;
1442 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE:
1443 OnPlanRestoreRelatedBundleFallback(reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_RESULTS*>(pvResults));
1444 break;
1445 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE:
1446 OnPlanRelatedBundleTypeFallback(reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults));
1447 break;
1439 default: 1448 default:
1440#ifdef DEBUG 1449#ifdef DEBUG
1441 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message); 1450 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
@@ -1585,6 +1594,16 @@ private: // privates
1585 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState)); 1594 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState));
1586 } 1595 }
1587 1596
1597 void OnPlanRelatedBundleTypeFallback(
1598 __in BA_ONPLANRELATEDBUNDLETYPE_ARGS* pArgs,
1599 __inout BA_ONPLANRELATEDBUNDLETYPE_RESULTS* pResults
1600 )
1601 {
1602 BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE requestedType = pResults->requestedType;
1603 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE, pArgs, pResults, m_pvBAFunctionsProcContext);
1604 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE_TYPE, m_hModule, pArgs->wzBundleId, LoggingPlanRelationTypeToString(requestedType), LoggingPlanRelationTypeToString(pResults->requestedType));
1605 }
1606
1588 void OnPlanPackageBeginFallback( 1607 void OnPlanPackageBeginFallback(
1589 __in BA_ONPLANPACKAGEBEGIN_ARGS* pArgs, 1608 __in BA_ONPLANPACKAGEBEGIN_ARGS* pArgs,
1590 __inout BA_ONPLANPACKAGEBEGIN_RESULTS* pResults 1609 __inout BA_ONPLANPACKAGEBEGIN_RESULTS* pResults
@@ -4672,6 +4691,31 @@ static LPCSTR LoggingRequestStateToString(
4672 } 4691 }
4673} 4692}
4674 4693
4694static LPCSTR LoggingPlanRelationTypeToString(
4695 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE type
4696 )
4697{
4698 switch (type)
4699 {
4700 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE:
4701 return "None";
4702 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE:
4703 return "Downgrade";
4704 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE:
4705 return "Upgrade";
4706 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON:
4707 return "Addon";
4708 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH:
4709 return "Patch";
4710 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON:
4711 return "DependentAddon";
4712 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH:
4713 return "DependentPatch";
4714 default:
4715 return "Invalid";
4716 }
4717}
4718
4675static LPCSTR LoggingMsiFeatureStateToString( 4719static LPCSTR LoggingMsiFeatureStateToString(
4676 __in BOOTSTRAPPER_FEATURE_STATE featureState 4720 __in BOOTSTRAPPER_FEATURE_STATE featureState
4677 ) 4721 )
diff --git a/src/ext/Bal/wixstdba/wixstdba.mc b/src/ext/Bal/wixstdba/wixstdba.mc
index eeb69914..025315a5 100644
--- a/src/ext/Bal/wixstdba/wixstdba.mc
+++ b/src/ext/Bal/wixstdba/wixstdba.mc
@@ -92,3 +92,10 @@ Language=English
92WIXSTDBA: Planned restore related bundle: %1!ls!, wixstdba requested: %2!hs!, bafunctions requested: %3!hs! 92WIXSTDBA: Planned restore related bundle: %1!ls!, wixstdba requested: %2!hs!, bafunctions requested: %3!hs!
93. 93.
94 94
95MessageId=10
96Severity=Success
97SymbolicName=MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE_TYPE
98Language=English
99WIXSTDBA: Planned related bundle type: %1!ls!, wixstdba requested: %2!hs!, bafunctions requested: %3!hs!
100.
101
diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp
index ac322ae7..175903ad 100644
--- a/src/libs/dutil/WixToolset.DUtil/butil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp
@@ -559,7 +559,7 @@ static HRESULT DetermineRelationType(
559 { 559 {
560 ExitOnFailure(hr, "Failed to do array search for addon code match."); 560 ExitOnFailure(hr, "Failed to do array search for addon code match.");
561 561
562 *pRelationType = BUNDLE_RELATION_DEPENDENT; 562 *pRelationType = BUNDLE_RELATION_DEPENDENT_ADDON;
563 ExitFunction(); 563 ExitFunction();
564 } 564 }
565 565
@@ -571,9 +571,9 @@ static HRESULT DetermineRelationType(
571 } 571 }
572 else 572 else
573 { 573 {
574 ExitOnFailure(hr, "Failed to do array search for addon code match."); 574 ExitOnFailure(hr, "Failed to do array search for patch code match.");
575 575
576 *pRelationType = BUNDLE_RELATION_DEPENDENT; 576 *pRelationType = BUNDLE_RELATION_DEPENDENT_PATCH;
577 ExitFunction(); 577 ExitFunction();
578 } 578 }
579 579
@@ -690,7 +690,7 @@ static HRESULT DetermineRelationType(
690 { 690 {
691 ExitOnFailure(hr, "Failed to do array search for addon code match."); 691 ExitOnFailure(hr, "Failed to do array search for addon code match.");
692 692
693 *pRelationType = BUNDLE_RELATION_DEPENDENT; 693 *pRelationType = BUNDLE_RELATION_DEPENDENT_ADDON;
694 ExitFunction(); 694 ExitFunction();
695 } 695 }
696 696
@@ -702,9 +702,9 @@ static HRESULT DetermineRelationType(
702 } 702 }
703 else 703 else
704 { 704 {
705 ExitOnFailure(hr, "Failed to do array search for addon code match."); 705 ExitOnFailure(hr, "Failed to do array search for patch code match.");
706 706
707 *pRelationType = BUNDLE_RELATION_DEPENDENT; 707 *pRelationType = BUNDLE_RELATION_DEPENDENT_PATCH;
708 ExitFunction(); 708 ExitFunction();
709 } 709 }
710 710
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/butil.h b/src/libs/dutil/WixToolset.DUtil/inc/butil.h
index 0d3eefe3..5d390344 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/butil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/butil.h
@@ -25,8 +25,8 @@ typedef enum _BUNDLE_RELATION_TYPE
25 BUNDLE_RELATION_UPGRADE, 25 BUNDLE_RELATION_UPGRADE,
26 BUNDLE_RELATION_ADDON, 26 BUNDLE_RELATION_ADDON,
27 BUNDLE_RELATION_PATCH, 27 BUNDLE_RELATION_PATCH,
28 BUNDLE_RELATION_DEPENDENT, 28 BUNDLE_RELATION_DEPENDENT_ADDON,
29 BUNDLE_RELATION_UPDATE, 29 BUNDLE_RELATION_DEPENDENT_PATCH,
30} BUNDLE_RELATION_TYPE; 30} BUNDLE_RELATION_TYPE;
31 31
32typedef struct _BUNDLE_QUERY_RELATED_BUNDLE_RESULT 32typedef struct _BUNDLE_QUERY_RELATED_BUNDLE_RESULT