@joebigelow / wix-1 / commits / 4cd1c4e0

Allow the BA to override the bundle relation type during plan.

Sean Hall committed Mar 13, 2022 at 23:45 UTC 4cd1c4e06145434ca940ac828772dc47b9d9738e
31 files changed +785 -97
src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+28 -1
@@ -103,10 +103,22 @@ enum BOOTSTRAPPER_RELATION_TYPE
103 BOOTSTRAPPER_RELATION_UPGRADE,
104 BOOTSTRAPPER_RELATION_ADDON,
105 BOOTSTRAPPER_RELATION_PATCH,
106 - BOOTSTRAPPER_RELATION_DEPENDENT,
106 + BOOTSTRAPPER_RELATION_DEPENDENT_ADDON,
107 + BOOTSTRAPPER_RELATION_DEPENDENT_PATCH,
108 BOOTSTRAPPER_RELATION_UPDATE,
109 };
110
111 +enum 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 +
122 enum BOOTSTRAPPER_CACHE_TYPE
123 {
124 BOOTSTRAPPER_CACHE_TYPE_REMOVE,
@@ -210,6 +222,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
222 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE,
223 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE,
224 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE,
225 + BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE,
226 };
227
228 enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -1209,6 +1222,20 @@ struct BA_ONPLANRELATEDBUNDLE_RESULTS
1222 BOOTSTRAPPER_REQUEST_STATE requestedState;
1223 };
1224
1225 +struct BA_ONPLANRELATEDBUNDLETYPE_ARGS
1226 +{
1227 + DWORD cbSize;
1228 + LPCWSTR wzBundleId;
1229 + BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE recommendedType;
1230 +};
1231 +
1232 +struct BA_ONPLANRELATEDBUNDLETYPE_RESULTS
1233 +{
1234 + DWORD cbSize;
1235 + BOOL fCancel;
1236 + BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE requestedType;
1237 +};
1238 +
1239 struct BA_ONPLANRESTORERELATEDBUNDLE_ARGS
1240 {
1241 DWORD cbSize;
src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+26
@@ -88,6 +88,9 @@ namespace WixToolset.Mba.Core
88 /// <inheritdoc/>
89 public event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle;
90
91 + /// <inheritdoc/>
92 + public event EventHandler<PlanRelatedBundleTypeEventArgs> PlanRelatedBundleType;
93 +
94 /// <inheritdoc/>
95 public event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary;
96
@@ -533,6 +536,19 @@ namespace WixToolset.Mba.Core
536 }
537 }
538
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>
553 /// Called by the engine, raises the <see cref="PlanRollbackBoundary"/> event.
554 /// </summary>
@@ -1514,6 +1530,16 @@ namespace WixToolset.Mba.Core
1530 return args.HResult;
1531 }
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 +
1543 int IBootstrapperApplication.OnPlanRollbackBoundary(string wzRollbackBoundaryId, bool fRecommendedTransaction, ref bool fTransaction, ref bool fCancel)
1544 {
1545 PlanRollbackBoundaryEventArgs args = new PlanRollbackBoundaryEventArgs(wzRollbackBoundaryId, fRecommendedTransaction, fTransaction, fCancel);
src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+31
@@ -745,6 +745,37 @@ namespace WixToolset.Mba.Core
745 public RequestState State { get; set; }
746 }
747
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>
780 /// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanPackageBegin"/>
781 /// </summary>
src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+59 -1
@@ -1148,6 +1148,18 @@ namespace WixToolset.Mba.Core
1148 [MarshalAs(UnmanagedType.U4)] ref RequestState pRequestedState,
1149 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel
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 + );
1163 }
1164
1165 /// <summary>
@@ -1669,7 +1681,12 @@ namespace WixToolset.Mba.Core
1681 /// <summary>
1682 ///
1683 /// </summary>
1672 - Dependent,
1684 + DependentAddon,
1685 +
1686 + /// <summary>
1687 + ///
1688 + /// </summary>
1689 + DependentPatch,
1690
1691 /// <summary>
1692 ///
@@ -1677,6 +1694,47 @@ namespace WixToolset.Mba.Core
1694 Update,
1695 }
1696
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>
1739 /// One or more reasons why the application is requested to be closed or is being closed.
1740 /// </summary>
src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
+5
@@ -333,6 +333,11 @@ namespace WixToolset.Mba.Core
333 /// </summary>
334 event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle;
335
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>
342 /// Fired when the engine has begun planning an upgrade related bundle for restoring in case of failure.
343 /// </summary>
src/api/burn/balutil/inc/BAFunctions.h
+1
@@ -89,6 +89,7 @@ enum BA_FUNCTIONS_MESSAGE
89 BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE,
90 BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE,
91 BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE,
92 + BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE,
93
94 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
95 BA_FUNCTIONS_MESSAGE_WNDPROC,
src/api/burn/balutil/inc/BalBaseBAFunctions.h
+10
@@ -859,6 +859,16 @@ public: // IBootstrapperApplication
859 return S_OK;
860 }
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 +
872 public: // IBAFunctions
873 virtual STDMETHODIMP OnPlan(
874 )
src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+1
@@ -160,6 +160,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
160 case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE:
161 case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE:
162 case BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE:
163 + case BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE:
164 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext);
165 break;
166 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED:
src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+11
@@ -1058,6 +1058,17 @@ public: // IBootstrapperApplication
1058 return S_OK;
1059 }
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 +
1072 public: //CBalBaseBootstrapperApplication
1073 virtual STDMETHODIMP Initialize(
1074 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+12
@@ -729,6 +729,15 @@ static HRESULT BalBaseBAProcOnPlanRestoreRelatedBundle(
729 return pBA->OnPlanRestoreRelatedBundle(pArgs->wzBundleId, pArgs->recommendedState, &pResults->requestedState, &pResults->fCancel);
730 }
731
732 +static 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 +
741 /*******************************************************************
742 BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication.
743 Provides a default mapping between the new message based BA interface and
@@ -988,6 +997,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc(
997 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE:
998 hr = BalBaseBAProcOnPlanRestoreRelatedBundle(pBA, reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_RESULTS*>(pvResults));
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;
1003 }
1004 }
1005
src/api/burn/balutil/inc/IBootstrapperApplication.h
+8
@@ -699,4 +699,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
699 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState,
700 __inout BOOL* pfCancel
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;
710 };
src/burn/engine/bundlepackageengine.cpp
+27 -2
@@ -2,7 +2,9 @@
2
3 #include "precomp.h"
4
5 -
5 +static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType(
6 + __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relationType
7 + );
8
9 // function definitions
10
@@ -265,7 +267,7 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
267 GENERIC_EXECUTE_MESSAGE message = { };
268 BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action;
269 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
268 - BOOTSTRAPPER_RELATION_TYPE relationType = pRelatedBundle->relationType;
270 + BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pRelatedBundle->planRelationType);
271 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
272 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
273 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
@@ -467,3 +469,26 @@ LExit:
469
470 return hr;
471 }
472 +
473 +static 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 +}
src/burn/engine/core.cpp
+11 -5
@@ -449,11 +449,11 @@ extern "C" HRESULT CorePlan(
449
450 if (!pEngineState->fDetected)
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 }
454 else if (pEngineState->plan.fAffectedMachineState)
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 }
458
459 // Always reset the plan.
@@ -482,6 +482,9 @@ extern "C" HRESULT CorePlan(
482 hr = DependencyPlanInitialize(&pEngineState->dependencies, &pEngineState->plan);
483 ExitOnFailure(hr, "Failed to initialize the dependencies for the plan.");
484
485 + hr = RegistrationPlanInitialize(&pEngineState->registration);
486 + ExitOnFailure(hr, "Failed to initialize registration for the plan.");
487 +
488 if (BOOTSTRAPPER_ACTION_LAYOUT == action)
489 {
490 Assert(!pEngineState->plan.fPerMachine);
@@ -521,6 +524,9 @@ extern "C" HRESULT CorePlan(
524 {
525 pEngineState->plan.fPerMachine = pEngineState->registration.fPerMachine; // default the scope of the plan to the per-machine state of the bundle.
526
527 + hr = PlanRelatedBundlesInitialize(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
528 + ExitOnFailure(hr, "Failed to initialize related bundles for plan.");
529 +
530 hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, &pEngineState->dependencies, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning);
531 ExitOnFailure(hr, "Failed to plan registration.");
532
@@ -918,8 +924,8 @@ extern "C" LPCWSTR CoreRelationTypeToCommandLineString(
924 case BOOTSTRAPPER_RELATION_UPDATE:
925 wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_UPDATE;
926 break;
921 - case BOOTSTRAPPER_RELATION_DEPENDENT:
922 - break;
927 + case BOOTSTRAPPER_RELATION_DEPENDENT_ADDON: __fallthrough;
928 + case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH: __fallthrough;
929 case BOOTSTRAPPER_RELATION_NONE: __fallthrough;
930 default:
931 wzRelationTypeCommandLine = NULL;
@@ -2308,7 +2314,7 @@ static void LogRelatedBundles(
2314
2315 if (pRelatedBundle->fPlannable)
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));
2318 }
2319 }
2320 }
src/burn/engine/detect.cpp
+12 -6
@@ -129,7 +129,7 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
129 {
130 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
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))
134 {
135 hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult);
@@ -143,10 +143,10 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
143 pRegistration->fForwardCompatibleBundleExists = TRUE;
144 }
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.");
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 }
151 }
152 }
@@ -164,6 +164,7 @@ extern "C" HRESULT DetectReportRelatedBundles(
164 )
165 {
166 HRESULT hr = S_OK;
167 + BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
168 BOOTSTRAPPER_REQUEST_STATE uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
169 *pfEligibleForCleanup = BOOTSTRAPPER_REGISTRATION_TYPE_NONE != pRegistration->detectedRegistrationType || pRegistration->fCached;
170
@@ -171,16 +172,21 @@ extern "C" HRESULT DetectReportRelatedBundles(
172 {
173 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
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));
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);
178 ExitOnRootFailure(hr, "BA aborted detect related bundle.");
179
180 // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle.
181 if (*pfEligibleForCleanup && pRelatedBundle->fPlannable)
182 {
183 + planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_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);
190 ExitOnFailure(hr, "Failed to get the default request state for related bundle for calculating fEligibleForCleanup");
191
192 if (BOOTSTRAPPER_REQUEST_STATE_NONE != uninstallRequestState)
src/burn/engine/elevation.cpp
+9
@@ -874,6 +874,9 @@ extern "C" HRESULT ElevationExecuteRelatedBundle(
874 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action);
875 ExitOnFailure(hr, "Failed to write action to message buffer.");
876
877 + hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.pRelatedBundle->planRelationType);
878 + ExitOnFailure(hr, "Failed to write planRelationType to message buffer.");
879 +
880 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
881 ExitOnFailure(hr, "Failed to write rollback.");
882
@@ -2723,6 +2726,7 @@ static HRESULT OnExecuteRelatedBundle(
2726 HRESULT hr = S_OK;
2727 SIZE_T iData = 0;
2728 LPWSTR sczPackage = NULL;
2729 + DWORD dwPlanRelationType = 0;
2730 DWORD dwRollback = 0;
2731 BURN_EXECUTE_ACTION executeAction = { };
2732 LPWSTR sczIgnoreDependencies = NULL;
@@ -2739,6 +2743,9 @@ static HRESULT OnExecuteRelatedBundle(
2743 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action);
2744 ExitOnFailure(hr, "Failed to read action.");
2745
2746 + hr = BuffReadNumber(pbData, cbData, &iData, &dwPlanRelationType);
2747 + ExitOnFailure(hr, "Failed to read planRelationType.");
2748 +
2749 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
2750 ExitOnFailure(hr, "Failed to read rollback.");
2751
@@ -2757,6 +2764,8 @@ static HRESULT OnExecuteRelatedBundle(
2764 hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle);
2765 ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage);
2766
2767 + executeAction.relatedBundle.pRelatedBundle->planRelationType = (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE)dwPlanRelationType;
2768 +
2769 // Pass the list of dependencies to ignore, if any, to the related bundle.
2770 if (sczIgnoreDependencies && *sczIgnoreDependencies)
2771 {
src/burn/engine/engine.mc
+5 -5
@@ -384,7 +384,7 @@ MessageId=207
384 Severity=Success
385 SymbolicName=MSG_PLANNED_RELATED_BUNDLE
386 Language=English
387 -Planned 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!
387 +Planned 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 .
389
390 MessageId=208
@@ -426,14 +426,14 @@ MessageId=213
426 Severity=Success
427 SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_DEPENDENT
428 Language=English
429 -Plan skipped related bundle: %1!ls!, type: %2!hs!, because it was dependent and the current bundle is being executed as type: %3!hs!.
429 +Plan skipped related bundle: %1!ls!, because it was dependent and the current bundle is being executed as type: %2!hs!.
430 .
431
432 MessageId=214
433 Severity=Success
434 SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_SCHEDULED
435 Language=English
436 -Plan skipped related bundle: %1!ls!, type: %2!hs!, because it was previously scheduled.
436 +Plan skipped related bundle: %1!ls!, because it was previously scheduled.
437 .
438
439 MessageId=215
@@ -447,14 +447,14 @@ MessageId=216
447 Severity=Success
448 SymbolicName=MSG_PLAN_SKIPPED_RELATED_BUNDLE_EMBEDDED_BUNDLE_NEWER
449 Language=English
450 -Plan skipped related bundle: %1!ls!, type: %2!hs!, provider key: %3!ls!, because an embedded bundle with the same provider key is being installed.
450 +Plan skipped related bundle: %1!ls!, provider key: %2!ls!, because an embedded bundle with the same provider key is being installed.
451 .
452
453 MessageId=217
454 Severity=Success
455 SymbolicName=MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR
456 Language=English
457 -Plan skipped dependent bundle repair: %1!ls!, type: %2!hs!, because no packages are being executed during this uninstall operation.
457 +Plan skipped dependent bundle repair: %1!ls!, because no packages are being executed during this uninstall operation.
458 .
459
460 MessageId=218
src/burn/engine/logging.cpp
+29 -2
@@ -715,6 +715,31 @@ extern "C" LPCSTR LoggingResumeModeToString(
715 }
716 }
717
718 +extern "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 +
743 extern "C" LPCSTR LoggingRelationTypeToString(
744 __in BOOTSTRAPPER_RELATION_TYPE type
745 )
@@ -731,8 +756,10 @@ extern "C" LPCSTR LoggingRelationTypeToString(
756 return "Addon";
757 case BOOTSTRAPPER_RELATION_PATCH:
758 return "Patch";
734 - case BOOTSTRAPPER_RELATION_DEPENDENT:
735 - return "Dependent";
759 + case BOOTSTRAPPER_RELATION_DEPENDENT_ADDON:
760 + return "DependentAddon";
761 + case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH:
762 + return "DependentPatch";
763 case BOOTSTRAPPER_RELATION_UPDATE:
764 return "Update";
765 default:
src/burn/engine/logging.h
+4
@@ -154,6 +154,10 @@ LPCSTR LoggingResumeModeToString(
154 __in BURN_RESUME_MODE resumeMode
155 );
156
157 +LPCSTR LoggingPlanRelationTypeToString(
158 + __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE type
159 + );
160 +
161 LPCSTR LoggingRelationTypeToString(
162 __in BOOTSTRAPPER_RELATION_TYPE type
163 );
src/burn/engine/plan.cpp
+124 -37
@@ -511,7 +511,7 @@ extern "C" HRESULT PlanForwardCompatibleBundles(
511
512 fIgnoreBundle = fRecommendIgnore;
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.");
516
517 if (!fIgnoreBundle)
@@ -621,7 +621,8 @@ extern "C" HRESULT PlanRegistration(
621 {
622 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
623
624 - if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType)
624 + if (BOOTSTRAPPER_RELATION_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
625 + BOOTSTRAPPER_RELATION_DEPENDENT_PATCH == pRelatedBundle->planRelationType)
626 {
627 for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j)
628 {
@@ -703,7 +704,8 @@ extern "C" HRESULT PlanRegistration(
704 {
705 const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
706
706 - if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType)
707 + if (BOOTSTRAPPER_RELATION_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
708 + BOOTSTRAPPER_RELATION_DEPENDENT_PATCH == pRelatedBundle->planRelationType)
709 {
710 for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j)
711 {
@@ -1212,17 +1214,63 @@ LExit:
1214 return hr;
1215 }
1216
1215 -extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1216 - __in BOOTSTRAPPER_RELATION_TYPE commandRelationType,
1217 +extern "C" HRESULT PlanDefaultRelatedBundlePlanType(
1218 __in BOOTSTRAPPER_RELATION_TYPE relatedBundleRelationType,
1218 - __in BOOTSTRAPPER_ACTION action,
1219 __in VERUTIL_VERSION* pRegistrationVersion,
1220 __in VERUTIL_VERSION* pRelatedBundleVersion,
1221 - __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState
1221 + __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pPlanRelationType
1222 )
1223 {
1224 HRESULT hr = S_OK;
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 +
1262 +LExit:
1263 + return hr;
1264 +}
1265 +
1266 +extern "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;
1274 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action;
1275
1276 // Never touch related bundles during Cache.
@@ -1233,17 +1281,14 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1281
1282 switch (relatedBundleRelationType)
1283 {
1236 - case BOOTSTRAPPER_RELATION_UPGRADE:
1284 + case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE:
1285 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && !fUninstalling)
1286 {
1239 - hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult);
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;
1287 + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
1288 }
1289 break;
1245 - case BOOTSTRAPPER_RELATION_PATCH: __fallthrough;
1246 - case BOOTSTRAPPER_RELATION_ADDON:
1290 + case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH: __fallthrough;
1291 + case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON:
1292 if (fUninstalling)
1293 {
1294 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
@@ -1257,7 +1302,8 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1302 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
1303 }
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:
1307 // Automatically repair dependent bundles to restore missing
1308 // packages after uninstall unless we're being upgraded with the
1309 // assumption that upgrades are cumulative (as intended).
@@ -1266,11 +1312,12 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1312 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
1313 }
1314 break;
1269 - case BOOTSTRAPPER_RELATION_DETECT:
1315 + case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE: __fallthrough;
1316 + case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE:
1317 break;
1318 default:
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);
1321 break;
1322 }
1323
@@ -1278,6 +1325,45 @@ LExit:
1325 return hr;
1326 }
1327
1328 +extern "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 +
1363 +LExit:
1364 + return hr;
1365 +}
1366 +
1367 extern "C" HRESULT PlanRelatedBundlesBegin(
1368 __in BURN_USER_EXPERIENCE* pUserExperience,
1369 __in BURN_REGISTRATION* pRegistration,
@@ -1302,18 +1388,15 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1388
1389 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
1390 {
1305 - BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i;
1391 + BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgpPlanSortedRelatedBundles[i];
1392
1393 if (!pRelatedBundle->fPlannable)
1394 {
1395 continue;
1396 }
1397
1312 - pRelatedBundle->defaultRequestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE;
1313 - pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE;
1314 - pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE;
1315 - pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1316 - pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1398 + BOOL fDependent = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON == pRelatedBundle->planRelationType ||
1399 + BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH == pRelatedBundle->planRelationType;
1400
1401 // Do not execute the same bundle twice.
1402 if (sdAncestors)
@@ -1321,7 +1404,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1404 hr = DictKeyExists(sdAncestors, pRelatedBundle->package.sczId);
1405 if (SUCCEEDED(hr))
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);
1408 continue;
1409 }
1410 else if (E_NOTFOUND != hr)
@@ -1329,10 +1412,10 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1412 ExitOnFailure(hr, "Failed to lookup the bundle ID in the ancestors dictionary.");
1413 }
1414 }
1332 - else if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_RELATION_NONE != relationType)
1415 + else if (fDependent && BOOTSTRAPPER_RELATION_NONE != relationType)
1416 {
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));
1419 continue;
1420 }
1421
@@ -1340,7 +1423,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1423 pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
1424 pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
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);
1427 ExitOnFailure(hr, "Failed to get default request state for related bundle.");
1428
1429 pRelatedBundle->package.defaultRequested = pRelatedBundle->package.requested;
@@ -1349,7 +1432,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1432 ExitOnRootFailure(hr, "BA aborted plan related bundle.");
1433
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)
1436 {
1437 if (0 < pRelatedBundle->package.cDependencyProviders)
1438 {
@@ -1437,7 +1520,11 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1520 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
1521 {
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;
1528
1529 if (!pRelatedBundle->fPlannable)
1530 {
@@ -1454,7 +1541,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1541 {
1542 ExitOnFailure(hr, "Failed to check the dictionary for a related bundle provider key: \"%ls\".", pProvider->sczKey);
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);
1545 continue;
1546 }
1547 else
@@ -1464,13 +1551,13 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1551 }
1552
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)
1555 {
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);
1558 }
1559
1473 - if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
1560 + if (fAddonOrPatch)
1561 {
1562 // Addon and patch bundles will be passed a list of dependencies to ignore for planning.
1563 hr = StrAllocString(&pRelatedBundle->package.Bundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
@@ -1489,7 +1576,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1576 ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1577
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)
1580 {
1581 hr = DependencyPlanPackageBegin(pRegistration->fPerMachine, &pRelatedBundle->package, pPlan);
1582 ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId);
@@ -1505,7 +1592,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1592 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1593
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)
1596 {
1597 hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan);
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(
1604 PlannedExecutePackage(pPlan, &pRelatedBundle->package);
1605 }
1606 }
1520 - else if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
1607 + else if (fAddonOrPatch)
1608 {
1609 // Make sure the package is properly ref-counted even if no plan is requested.
1610 hr = DependencyPlanPackageBegin(pRegistration->fPerMachine, &pRelatedBundle->package, pPlan);
@@ -1530,7 +1617,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1617 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId);
1618 }
1619
1533 - if (fInstallingAnyPackage && BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType)
1620 + if (fInstallingAnyPackage && BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE == pRelatedBundle->planRelationType)
1621 {
1622 BURN_EXECUTE_ACTION* pAction = NULL;
1623
src/burn/engine/plan.h
+13 -3
@@ -316,6 +316,12 @@ HRESULT PlanSetVariables(
316 __in BOOTSTRAPPER_ACTION action,
317 __in BURN_VARIABLES* pVariables
318 );
319 +HRESULT 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 + );
325 HRESULT PlanDefaultPackageRequestState(
326 __in BURN_PACKAGE_TYPE packageType,
327 __in BOOTSTRAPPER_PACKAGE_STATE currentState,
@@ -383,12 +389,16 @@ HRESULT PlanExecutePackage(
389 );
390 HRESULT PlanDefaultRelatedBundleRequestState(
391 __in BOOTSTRAPPER_RELATION_TYPE commandRelationType,
386 - __in BOOTSTRAPPER_RELATION_TYPE relatedBundleRelationType,
392 + __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE relatedBundleRelationType,
393 __in BOOTSTRAPPER_ACTION action,
388 - __in VERUTIL_VERSION* pRegistrationVersion,
389 - __in VERUTIL_VERSION* pRelatedBundleVersion,
394 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState
395 );
396 +HRESULT PlanRelatedBundlesInitialize(
397 + __in BURN_USER_EXPERIENCE* pUserExperience,
398 + __in BURN_REGISTRATION* pRegistration,
399 + __in BOOTSTRAPPER_RELATION_TYPE relationType,
400 + __in BURN_PLAN* pPlan
401 + );
402 HRESULT PlanRelatedBundlesBegin(
403 __in BURN_USER_EXPERIENCE* pUserExperience,
404 __in BURN_REGISTRATION* pRegistration,
src/burn/engine/registration.cpp
+22 -1
@@ -614,7 +614,28 @@ extern "C" HRESULT RegistrationDetectRelatedBundles(
614 hr = RelatedBundlesInitializeForScope(FALSE, pRegistration, &pRegistration->relatedBundles);
615 ExitOnFailure(hr, "Failed to initialize per-user related bundles.");
616
617 - RelatedBundlesSort(&pRegistration->relatedBundles);
617 + RelatedBundlesSortDetect(&pRegistration->relatedBundles);
618 +
619 +LExit:
620 + return hr;
621 +}
622 +
623 +extern "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 + }
639
640 LExit:
641 return hr;
src/burn/engine/registration.h
+7 -1
@@ -53,7 +53,9 @@ typedef struct _BURN_UPDATE_REGISTRATION
53
54 typedef struct _BURN_RELATED_BUNDLE
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;
59 BOOL fForwardCompatible;
60
61 VERUTIL_VERSION* pVersion;
@@ -71,6 +73,7 @@ typedef struct _BURN_RELATED_BUNDLES
73 {
74 BURN_RELATED_BUNDLE* rgRelatedBundles;
75 DWORD cRelatedBundles;
76 + BURN_RELATED_BUNDLE** rgpPlanSortedRelatedBundles;
77 } BURN_RELATED_BUNDLES;
78
79 typedef struct _BURN_SOFTWARE_TAG
@@ -185,6 +188,9 @@ HRESULT RegistrationDetectResumeType(
188 HRESULT RegistrationDetectRelatedBundles(
189 __in BURN_REGISTRATION* pRegistration
190 );
191 +HRESULT RegistrationPlanInitialize(
192 + __in BURN_REGISTRATION* pRegistration
193 + );
194 HRESULT RegistrationSessionBegin(
195 __in_z LPCWSTR wzEngineWorkingPath,
196 __in BURN_REGISTRATION* pRegistration,
src/burn/engine/relatedbundle.cpp
+93 -12
@@ -10,11 +10,16 @@ typedef struct _BUNDLE_QUERY_CONTEXT
10
11 // internal function declarations
12
13 -static __callback int __cdecl CompareRelatedBundles(
13 +static __callback int __cdecl CompareRelatedBundlesDetect(
14 __in void* pvContext,
15 __in const void* pvLeft,
16 __in const void* pvRight
17 -);
17 + );
18 +static __callback int __cdecl CompareRelatedBundlesPlan(
19 + __in void* /*pvContext*/,
20 + __in const void* pvLeft,
21 + __in const void* pvRight
22 + );
23 static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback(
24 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
25 __in_opt LPVOID pvContext
@@ -88,6 +93,8 @@ extern "C" void RelatedBundlesUninitialize(
93 MemFree(pRelatedBundles->rgRelatedBundles);
94 }
95
96 + ReleaseMem(pRelatedBundles->rgpPlanSortedRelatedBundles);
97 +
98 memset(pRelatedBundles, 0, sizeof(BURN_RELATED_BUNDLES));
99 }
100
@@ -122,17 +129,24 @@ LExit:
129 return hr;
130 }
131
125 -extern "C" void RelatedBundlesSort(
132 +extern "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 +
139 +extern "C" void RelatedBundlesSortPlan(
140 __in BURN_RELATED_BUNDLES* pRelatedBundles
141 )
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);
144 }
145
146
147 // internal helper functions
148
135 -static __callback int __cdecl CompareRelatedBundles(
149 +static __callback int __cdecl CompareRelatedBundlesDetect(
150 __in void* /*pvContext*/,
151 __in const void* pvLeft,
152 __in const void* pvRight
@@ -143,18 +157,61 @@ static __callback int __cdecl CompareRelatedBundles(
157 const BURN_RELATED_BUNDLE* pBundleRight = static_cast<const BURN_RELATED_BUNDLE*>(pvRight);
158
159 // Sort by relation type, then version, then bundle id.
146 - if (pBundleLeft->relationType != pBundleRight->relationType)
160 + if (pBundleLeft->detectRelationType != pBundleRight->detectRelationType)
161 {
162 // Upgrade bundles last, everything else according to the enum.
149 - if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleLeft->relationType)
163 + if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleLeft->detectRelationType)
164 {
165 ret = 1;
166 }
153 - else if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleRight->relationType)
167 + else if (BOOTSTRAPPER_RELATION_UPGRADE == pBundleRight->detectRelationType)
168 {
169 ret = -1;
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 +
192 +static __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)
215 {
216 ret = -1;
217 }
@@ -191,6 +248,30 @@ LExit:
248 return result;
249 }
250
251 +static 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 +
275 static HRESULT LoadIfRelatedBundle(
276 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
277 __in BURN_REGISTRATION* pRegistration,
@@ -199,7 +280,7 @@ static HRESULT LoadIfRelatedBundle(
280 {
281 HRESULT hr = S_OK;
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);
284 BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
285
286 // If we found our bundle id, it's not a related bundle.
@@ -316,11 +397,11 @@ static HRESULT LoadRelatedBundleFromKey(
397 }
398 ExitOnFailure(hr, "Failed to read tag from registry for bundle: %ls", wzRelatedBundleId);
399
319 - pRelatedBundle->relationType = relationType;
400 + pRelatedBundle->detectRelationType = relationType;
401
402 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId,
403 #ifdef DEBUG
323 - pRelatedBundle->relationType,
404 + pRelatedBundle->detectRelationType,
405 #endif
406 fCached, sczCachePath, qwFileSize, pBundleDependencyProvider);
407 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId);
src/burn/engine/relatedbundle.h
+4 -1
@@ -19,7 +19,10 @@ HRESULT RelatedBundleFindById(
19 __in_z LPCWSTR wzId,
20 __out BURN_RELATED_BUNDLE** ppRelatedBundle
21 );
22 -void RelatedBundlesSort(
22 +void RelatedBundlesSortDetect(
23 + __in BURN_RELATED_BUNDLES* pRelatedBundles
24 + );
25 +void RelatedBundlesSortPlan(
26 __in BURN_RELATED_BUNDLES* pRelatedBundles
27 );
28
src/burn/engine/userexperience.cpp
+31 -1
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad(
104 args.pCommand = pCommand;
105 args.pfnBootstrapperEngineProc = EngineForApplicationProc;
106 args.pvBootstrapperEngineProcContext = pEngineContext;
107 - args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 4, 0);
107 + args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 14, 0);
108
109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS);
110
@@ -2176,6 +2176,36 @@ LExit:
2176 return hr;
2177 }
2178
2179 +EXTERN_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 +
2205 +LExit:
2206 + return hr;
2207 +}
2208 +
2209 EXTERN_C BAAPI UserExperienceOnPlanRestoreRelatedBundle(
2210 __in BURN_USER_EXPERIENCE* pUserExperience,
2211 __in_z LPCWSTR wzBundleId,
src/burn/engine/userexperience.h
+5
@@ -497,6 +497,11 @@ BAAPI UserExperienceOnPlanRelatedBundle(
497 __in_z LPCWSTR wzBundleId,
498 __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState
499 );
500 +BAAPI UserExperienceOnPlanRelatedBundleType(
501 + __in BURN_USER_EXPERIENCE* pUserExperience,
502 + __in_z LPCWSTR wzBundleId,
503 + __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType
504 + );
505 BAAPI UserExperienceOnPlanRestoreRelatedBundle(
506 __in BURN_USER_EXPERIENCE* pUserExperience,
507 __in_z LPCWSTR wzBundleId,
src/burn/test/BurnUnitTest/PlanTest.cpp
+138 -11
@@ -18,6 +18,8 @@ static BOOL vfUsePackageRequestState = FALSE;
18 static BOOTSTRAPPER_REQUEST_STATE vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
19 static BOOL vfUseRelatedBundleRequestState = FALSE;
20 static BOOTSTRAPPER_REQUEST_STATE vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
21 +static BOOL vfUseRelatedBundlePlanType = FALSE;
22 +static BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE vRelatedBundlePlanType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
23
24 static BURN_DEPENDENCY_ACTION registerActions1[] = { BURN_DEPENDENCY_ACTION_REGISTER };
25 static BURN_DEPENDENCY_ACTION unregisterActions1[] = { BURN_DEPENDENCY_ACTION_UNREGISTER };
@@ -52,7 +54,7 @@ namespace Bootstrapper
54
55 InitializeEngineStateForCorePlan(wzMsiTransactionManifestFileName, 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);
58
59 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
60 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -374,6 +376,122 @@ namespace Bootstrapper
376 ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
377 }
378
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]
496 void RelatedBundleMissingFromCacheTest()
497 {
@@ -385,7 +503,7 @@ namespace Bootstrapper
503 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
504 DetectAttachedContainerAsAttached(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);
507 pRelatedBundle->fPlannable = FALSE;
508
509 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
@@ -473,7 +591,7 @@ namespace Bootstrapper
591 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
592 DetectAttachedContainerAsAttached(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);
595
596 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_CACHE);
597 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -546,7 +664,7 @@ namespace Bootstrapper
664 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
665 DetectAttachedContainerAsAttached(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);
668
669 vfUsePackageRequestState = TRUE;
670 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT;
@@ -621,7 +739,7 @@ namespace Bootstrapper
739
740 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, 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);
743
744 vfUsePackageRequestState = TRUE;
745 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
@@ -703,7 +821,7 @@ namespace Bootstrapper
821 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
822 DetectAttachedContainerAsAttached(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);
825
826 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
827 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -1475,6 +1593,7 @@ namespace Bootstrapper
1593
1594 vfUsePackageRequestState = FALSE;
1595 vfUseRelatedBundleRequestState = FALSE;
1596 + vfUseRelatedBundlePlanType = FALSE;
1597
1598 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
1599
@@ -1686,10 +1805,11 @@ namespace Bootstrapper
1805 }
1806 }
1807
1689 - BURN_RELATED_BUNDLE* DetectUpgradeBundle(
1808 + BURN_RELATED_BUNDLE* DetectRelatedBundle(
1809 __in BURN_ENGINE_STATE* pEngineState,
1810 __in LPCWSTR wzId,
1692 - __in LPCWSTR wzVersion
1811 + __in LPCWSTR wzVersion,
1812 + __in BOOTSTRAPPER_RELATION_TYPE relationType
1813 )
1814 {
1815 HRESULT hr = S_OK;
@@ -1717,11 +1837,11 @@ namespace Bootstrapper
1837 NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion);
1838
1839 pRelatedBundle->fPlannable = TRUE;
1720 - pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1840 + pRelatedBundle->detectRelationType = relationType;
1841
1842 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, TRUE, TRUE, wzId,
1843 #ifdef DEBUG
1724 - pRelatedBundle->relationType,
1844 + pRelatedBundle->detectRelationType,
1845 #endif
1846 TRUE, wzFilePath, 0, &dependencyProvider);
1847 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
@@ -1746,7 +1866,7 @@ namespace Bootstrapper
1866 pEngineState->command.relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1867
1868 DetectPackagesAsPresentAndCached(pEngineState);
1749 - DetectUpgradeBundle(pEngineState, wzId, wzVersion);
1869 + DetectRelatedBundle(pEngineState, wzId, wzVersion, BOOTSTRAPPER_RELATION_UPGRADE);
1870
1871 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
1872 {
@@ -2199,6 +2319,13 @@ static HRESULT WINAPI PlanTestBAProc(
2319 pResults->requestedState = vRelatedBundleRequestState;
2320 }
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;
2329 }
2330
2331 return S_OK;
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+44
@@ -169,6 +169,9 @@ static LPCSTR LoggingBoolToString(
169 static LPCSTR LoggingRequestStateToString(
170 __in BOOTSTRAPPER_REQUEST_STATE requestState
171 );
172 +static LPCSTR LoggingPlanRelationTypeToString(
173 + __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE type
174 + );
175 static LPCSTR LoggingMsiFeatureStateToString(
176 __in BOOTSTRAPPER_FEATURE_STATE featureState
177 );
@@ -1436,6 +1439,12 @@ public: // IBootstrapperApplication
1439 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE:
1440 OnPlannedCompatiblePackageFallback(reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_RESULTS*>(pvResults));
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;
1448 default:
1449 #ifdef DEBUG
1450 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
@@ -1585,6 +1594,16 @@ private: // privates
1594 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState));
1595 }
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 +
1607 void OnPlanPackageBeginFallback(
1608 __in BA_ONPLANPACKAGEBEGIN_ARGS* pArgs,
1609 __inout BA_ONPLANPACKAGEBEGIN_RESULTS* pResults
@@ -4672,6 +4691,31 @@ static LPCSTR LoggingRequestStateToString(
4691 }
4692 }
4693
4694 +static 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 +
4719 static LPCSTR LoggingMsiFeatureStateToString(
4720 __in BOOTSTRAPPER_FEATURE_STATE featureState
4721 )
src/ext/Bal/wixstdba/wixstdba.mc
+7
@@ -92,3 +92,10 @@ Language=English
92 WIXSTDBA: Planned restore related bundle: %1!ls!, wixstdba requested: %2!hs!, bafunctions requested: %3!hs!
93 .
94
95 +MessageId=10
96 +Severity=Success
97 +SymbolicName=MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE_TYPE
98 +Language=English
99 +WIXSTDBA: Planned related bundle type: %1!ls!, wixstdba requested: %2!hs!, bafunctions requested: %3!hs!
100 +.
101 +
src/libs/dutil/WixToolset.DUtil/butil.cpp
+6 -6
@@ -559,7 +559,7 @@ static HRESULT DetermineRelationType(
559 {
560 ExitOnFailure(hr, "Failed to do array search for addon code match.");
561
562 - *pRelationType = BUNDLE_RELATION_DEPENDENT;
562 + *pRelationType = BUNDLE_RELATION_DEPENDENT_ADDON;
563 ExitFunction();
564 }
565
@@ -571,9 +571,9 @@ static HRESULT DetermineRelationType(
571 }
572 else
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
576 - *pRelationType = BUNDLE_RELATION_DEPENDENT;
576 + *pRelationType = BUNDLE_RELATION_DEPENDENT_PATCH;
577 ExitFunction();
578 }
579
@@ -690,7 +690,7 @@ static HRESULT DetermineRelationType(
690 {
691 ExitOnFailure(hr, "Failed to do array search for addon code match.");
692
693 - *pRelationType = BUNDLE_RELATION_DEPENDENT;
693 + *pRelationType = BUNDLE_RELATION_DEPENDENT_ADDON;
694 ExitFunction();
695 }
696
@@ -702,9 +702,9 @@ static HRESULT DetermineRelationType(
702 }
703 else
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
707 - *pRelationType = BUNDLE_RELATION_DEPENDENT;
707 + *pRelationType = BUNDLE_RELATION_DEPENDENT_PATCH;
708 ExitFunction();
709 }
710
src/libs/dutil/WixToolset.DUtil/inc/butil.h
+2 -2
@@ -25,8 +25,8 @@ typedef enum _BUNDLE_RELATION_TYPE
25 BUNDLE_RELATION_UPGRADE,
26 BUNDLE_RELATION_ADDON,
27 BUNDLE_RELATION_PATCH,
28 - BUNDLE_RELATION_DEPENDENT,
29 - BUNDLE_RELATION_UPDATE,
28 + BUNDLE_RELATION_DEPENDENT_ADDON,
29 + BUNDLE_RELATION_DEPENDENT_PATCH,
30 } BUNDLE_RELATION_TYPE;
31
32 typedef struct _BUNDLE_QUERY_RELATED_BUNDLE_RESULT