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