diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-02-10 18:09:34 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-02-10 19:51:19 -0600 |
commit | 27a0db4070a2b5756282bf15b957dd7f0021417f (patch) | |
tree | 2d0cdfe80d5ccd6d207bdf664a4f8e512281c1cf | |
parent | 091573d459d6ab4947bd39bd3bc8faee3d18b4fc (diff) | |
download | wix-27a0db4070a2b5756282bf15b957dd7f0021417f.tar.gz wix-27a0db4070a2b5756282bf15b957dd7f0021417f.tar.bz2 wix-27a0db4070a2b5756282bf15b957dd7f0021417f.zip |
When rolling back a bundle failure, reinstall all upgrade related bundles.
Fixes #3421
31 files changed, 515 insertions, 28 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h index 659901be..5c6258d0 100644 --- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h +++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h | |||
@@ -209,6 +209,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE | |||
209 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN, | 209 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN, |
210 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, | 210 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, |
211 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, | 211 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, |
212 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, | ||
212 | }; | 213 | }; |
213 | 214 | ||
214 | enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION | 215 | enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION |
@@ -1208,6 +1209,20 @@ struct BA_ONPLANRELATEDBUNDLE_RESULTS | |||
1208 | BOOTSTRAPPER_REQUEST_STATE requestedState; | 1209 | BOOTSTRAPPER_REQUEST_STATE requestedState; |
1209 | }; | 1210 | }; |
1210 | 1211 | ||
1212 | struct BA_ONPLANRESTORERELATEDBUNDLE_ARGS | ||
1213 | { | ||
1214 | DWORD cbSize; | ||
1215 | LPCWSTR wzBundleId; | ||
1216 | BOOTSTRAPPER_REQUEST_STATE recommendedState; | ||
1217 | }; | ||
1218 | |||
1219 | struct BA_ONPLANRESTORERELATEDBUNDLE_RESULTS | ||
1220 | { | ||
1221 | DWORD cbSize; | ||
1222 | BOOL fCancel; | ||
1223 | BOOTSTRAPPER_REQUEST_STATE requestedState; | ||
1224 | }; | ||
1225 | |||
1211 | struct BA_ONPLANROLLBACKBOUNDARY_ARGS | 1226 | struct BA_ONPLANROLLBACKBOUNDARY_ARGS |
1212 | { | 1227 | { |
1213 | DWORD cbSize; | 1228 | DWORD cbSize; |
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs index f277425e..b08e66c0 100644 --- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs | |||
@@ -271,6 +271,9 @@ namespace WixToolset.Mba.Core | |||
271 | /// <inheritdoc/> | 271 | /// <inheritdoc/> |
272 | public event EventHandler<SetUpdateCompleteEventArgs> SetUpdateComplete; | 272 | public event EventHandler<SetUpdateCompleteEventArgs> SetUpdateComplete; |
273 | 273 | ||
274 | /// <inheritdoc/> | ||
275 | public event EventHandler<PlanRestoreRelatedBundleEventArgs> PlanRestoreRelatedBundle; | ||
276 | |||
274 | /// <summary> | 277 | /// <summary> |
275 | /// Entry point that is called when the bootstrapper application is ready to run. | 278 | /// Entry point that is called when the bootstrapper application is ready to run. |
276 | /// </summary> | 279 | /// </summary> |
@@ -1321,6 +1324,19 @@ namespace WixToolset.Mba.Core | |||
1321 | } | 1324 | } |
1322 | } | 1325 | } |
1323 | 1326 | ||
1327 | /// <summary> | ||
1328 | /// Called by the engine, raises the <see cref="PlanRestoreRelatedBundle"/> event. | ||
1329 | /// </summary> | ||
1330 | /// <param name="args">Additional arguments for this event.</param> | ||
1331 | protected virtual void OnPlanRestoreRelatedBundle(PlanRestoreRelatedBundleEventArgs args) | ||
1332 | { | ||
1333 | EventHandler<PlanRestoreRelatedBundleEventArgs> handler = this.PlanRestoreRelatedBundle; | ||
1334 | if (null != handler) | ||
1335 | { | ||
1336 | handler(this, args); | ||
1337 | } | ||
1338 | } | ||
1339 | |||
1324 | #region IBootstrapperApplication Members | 1340 | #region IBootstrapperApplication Members |
1325 | 1341 | ||
1326 | int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext) | 1342 | int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext) |
@@ -2042,6 +2058,16 @@ namespace WixToolset.Mba.Core | |||
2042 | return args.HResult; | 2058 | return args.HResult; |
2043 | } | 2059 | } |
2044 | 2060 | ||
2061 | int IBootstrapperApplication.OnPlanRestoreRelatedBundle(string wzBundleId, RequestState recommendedState, ref RequestState pRequestedState, ref bool fCancel) | ||
2062 | { | ||
2063 | PlanRestoreRelatedBundleEventArgs args = new PlanRestoreRelatedBundleEventArgs(wzBundleId, recommendedState, pRequestedState, fCancel); | ||
2064 | this.OnPlanRestoreRelatedBundle(args); | ||
2065 | |||
2066 | pRequestedState = args.State; | ||
2067 | fCancel = args.Cancel; | ||
2068 | return args.HResult; | ||
2069 | } | ||
2070 | |||
2045 | #endregion | 2071 | #endregion |
2046 | } | 2072 | } |
2047 | } | 2073 | } |
diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs index d4d70651..2e1e1be3 100644 --- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs +++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs | |||
@@ -2402,4 +2402,35 @@ namespace WixToolset.Mba.Core | |||
2402 | /// </summary> | 2402 | /// </summary> |
2403 | public string NewPackageId { get; private set; } | 2403 | public string NewPackageId { get; private set; } |
2404 | } | 2404 | } |
2405 | |||
2406 | /// <summary> | ||
2407 | /// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanRestoreRelatedBundle"/> | ||
2408 | /// </summary> | ||
2409 | [Serializable] | ||
2410 | public class PlanRestoreRelatedBundleEventArgs : CancellableHResultEventArgs | ||
2411 | { | ||
2412 | /// <summary /> | ||
2413 | public PlanRestoreRelatedBundleEventArgs(string bundleId, RequestState recommendedState, RequestState state, bool cancelRecommendation) | ||
2414 | : base(cancelRecommendation) | ||
2415 | { | ||
2416 | this.BundleId = bundleId; | ||
2417 | this.RecommendedState = recommendedState; | ||
2418 | this.State = state; | ||
2419 | } | ||
2420 | |||
2421 | /// <summary> | ||
2422 | /// Gets the identity of the bundle to plan for. | ||
2423 | /// </summary> | ||
2424 | public string BundleId { get; private set; } | ||
2425 | |||
2426 | /// <summary> | ||
2427 | /// Gets the recommended requested state for the bundle. | ||
2428 | /// </summary> | ||
2429 | public RequestState RecommendedState { get; private set; } | ||
2430 | |||
2431 | /// <summary> | ||
2432 | /// Gets or sets the requested state for the bundle. | ||
2433 | /// </summary> | ||
2434 | public RequestState State { get; set; } | ||
2435 | } | ||
2405 | } | 2436 | } |
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs index 05f96106..4fbe5e18 100644 --- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs | |||
@@ -1136,6 +1136,18 @@ namespace WixToolset.Mba.Core | |||
1136 | [MarshalAs(UnmanagedType.LPWStr)] string wzPreviousPackageId, | 1136 | [MarshalAs(UnmanagedType.LPWStr)] string wzPreviousPackageId, |
1137 | [MarshalAs(UnmanagedType.LPWStr)] string wzNewPackageId | 1137 | [MarshalAs(UnmanagedType.LPWStr)] string wzNewPackageId |
1138 | ); | 1138 | ); |
1139 | |||
1140 | /// <summary> | ||
1141 | /// See <see cref="IDefaultBootstrapperApplication.PlanRestoreRelatedBundle"/>. | ||
1142 | /// </summary> | ||
1143 | [PreserveSig] | ||
1144 | [return: MarshalAs(UnmanagedType.I4)] | ||
1145 | int OnPlanRestoreRelatedBundle( | ||
1146 | [MarshalAs(UnmanagedType.LPWStr)] string wzBundleId, | ||
1147 | [MarshalAs(UnmanagedType.U4)] RequestState recommendedState, | ||
1148 | [MarshalAs(UnmanagedType.U4)] ref RequestState pRequestedState, | ||
1149 | [MarshalAs(UnmanagedType.Bool)] ref bool fCancel | ||
1150 | ); | ||
1139 | } | 1151 | } |
1140 | 1152 | ||
1141 | /// <summary> | 1153 | /// <summary> |
diff --git a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs index ce06408e..c237cb9d 100644 --- a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs | |||
@@ -334,6 +334,11 @@ namespace WixToolset.Mba.Core | |||
334 | event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle; | 334 | event EventHandler<PlanRelatedBundleEventArgs> PlanRelatedBundle; |
335 | 335 | ||
336 | /// <summary> | 336 | /// <summary> |
337 | /// Fired when the engine has begun planning an upgrade related bundle for restoring in case of failure. | ||
338 | /// </summary> | ||
339 | event EventHandler<PlanRestoreRelatedBundleEventArgs> PlanRestoreRelatedBundle; | ||
340 | |||
341 | /// <summary> | ||
337 | /// Fired when the engine is planning a rollback boundary. | 342 | /// Fired when the engine is planning a rollback boundary. |
338 | /// </summary> | 343 | /// </summary> |
339 | event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary; | 344 | event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary; |
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h index 84359d65..cbef88df 100644 --- a/src/api/burn/balutil/inc/BAFunctions.h +++ b/src/api/burn/balutil/inc/BAFunctions.h | |||
@@ -88,6 +88,7 @@ enum BA_FUNCTIONS_MESSAGE | |||
88 | BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN, | 88 | BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN, |
89 | BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, | 89 | BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, |
90 | BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, | 90 | BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, |
91 | BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, | ||
91 | 92 | ||
92 | BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, | 93 | BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, |
93 | BA_FUNCTIONS_MESSAGE_WNDPROC, | 94 | BA_FUNCTIONS_MESSAGE_WNDPROC, |
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h index c6d0924f..e98ebc9f 100644 --- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h +++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h | |||
@@ -849,6 +849,16 @@ public: // IBootstrapperApplication | |||
849 | return S_OK; | 849 | return S_OK; |
850 | } | 850 | } |
851 | 851 | ||
852 | virtual STDMETHODIMP OnPlanRestoreRelatedBundle( | ||
853 | __in_z LPCWSTR /*wzBundleId*/, | ||
854 | __in BOOTSTRAPPER_REQUEST_STATE /*recommendedState*/, | ||
855 | __inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestedState*/, | ||
856 | __inout BOOL* /*pfCancel*/ | ||
857 | ) | ||
858 | { | ||
859 | return S_OK; | ||
860 | } | ||
861 | |||
852 | public: // IBAFunctions | 862 | public: // IBAFunctions |
853 | virtual STDMETHODIMP OnPlan( | 863 | virtual STDMETHODIMP OnPlan( |
854 | ) | 864 | ) |
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h index 5d5ff098..09cc189e 100644 --- a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h +++ b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h | |||
@@ -159,6 +159,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc( | |||
159 | case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN: | 159 | case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN: |
160 | case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE: | 160 | case BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE: |
161 | case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: | 161 | case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: |
162 | case BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE: | ||
162 | hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); | 163 | hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); |
163 | break; | 164 | break; |
164 | case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: | 165 | case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: |
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h index e1a36fdf..6a24f24b 100644 --- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h +++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h | |||
@@ -1047,6 +1047,17 @@ public: // IBootstrapperApplication | |||
1047 | return S_OK; | 1047 | return S_OK; |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | virtual STDMETHODIMP OnPlanRestoreRelatedBundle( | ||
1051 | __in_z LPCWSTR /*wzBundleId*/, | ||
1052 | __in BOOTSTRAPPER_REQUEST_STATE /*recommendedState*/, | ||
1053 | __inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestedState*/, | ||
1054 | __inout BOOL* pfCancel | ||
1055 | ) | ||
1056 | { | ||
1057 | *pfCancel |= CheckCanceled(); | ||
1058 | return S_OK; | ||
1059 | } | ||
1060 | |||
1050 | public: //CBalBaseBootstrapperApplication | 1061 | public: //CBalBaseBootstrapperApplication |
1051 | virtual STDMETHODIMP Initialize( | 1062 | virtual STDMETHODIMP Initialize( |
1052 | __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs | 1063 | __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs |
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h index 1ee5258e..d40390e5 100644 --- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h +++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h | |||
@@ -720,6 +720,15 @@ static HRESULT BalBaseBAProcOnSetUpdateComplete( | |||
720 | return pBA->OnSetUpdateComplete(pArgs->hrStatus, pArgs->wzPreviousPackageId, pArgs->wzNewPackageId); | 720 | return pBA->OnSetUpdateComplete(pArgs->hrStatus, pArgs->wzPreviousPackageId, pArgs->wzNewPackageId); |
721 | } | 721 | } |
722 | 722 | ||
723 | static HRESULT BalBaseBAProcOnPlanRestoreRelatedBundle( | ||
724 | __in IBootstrapperApplication* pBA, | ||
725 | __in BA_ONPLANRESTORERELATEDBUNDLE_ARGS* pArgs, | ||
726 | __inout BA_ONPLANRESTORERELATEDBUNDLE_RESULTS* pResults | ||
727 | ) | ||
728 | { | ||
729 | return pBA->OnPlanRestoreRelatedBundle(pArgs->wzBundleId, pArgs->recommendedState, &pResults->requestedState, &pResults->fCancel); | ||
730 | } | ||
731 | |||
723 | /******************************************************************* | 732 | /******************************************************************* |
724 | BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. | 733 | BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. |
725 | Provides a default mapping between the new message based BA interface and | 734 | Provides a default mapping between the new message based BA interface and |
@@ -976,6 +985,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc( | |||
976 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: | 985 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: |
977 | hr = BalBaseBAProcOnPlannedCompatiblePackage(pBA, reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_RESULTS*>(pvResults)); | 986 | hr = BalBaseBAProcOnPlannedCompatiblePackage(pBA, reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANNEDCOMPATIBLEPACKAGE_RESULTS*>(pvResults)); |
978 | break; | 987 | break; |
988 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE: | ||
989 | hr = BalBaseBAProcOnPlanRestoreRelatedBundle(pBA, reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRESTORERELATEDBUNDLE_RESULTS*>(pvResults)); | ||
990 | break; | ||
979 | } | 991 | } |
980 | } | 992 | } |
981 | 993 | ||
diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h index 640f609d..5932c06e 100644 --- a/src/api/burn/balutil/inc/IBootstrapperApplication.h +++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h | |||
@@ -691,4 +691,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A | |||
691 | __in_z_opt LPCWSTR wzPreviousPackageId, | 691 | __in_z_opt LPCWSTR wzPreviousPackageId, |
692 | __in_z_opt LPCWSTR wzNewPackageId | 692 | __in_z_opt LPCWSTR wzNewPackageId |
693 | ) = 0; | 693 | ) = 0; |
694 | |||
695 | // OnPlanRestoreRelatedBundle - called when the engine begins planning an upgrade related bundle for restoring in case of failure. | ||
696 | STDMETHOD(OnPlanRestoreRelatedBundle)( | ||
697 | __in_z LPCWSTR wzBundleId, | ||
698 | __in BOOTSTRAPPER_REQUEST_STATE recommendedState, | ||
699 | __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState, | ||
700 | __inout BOOL* pfCancel | ||
701 | ) = 0; | ||
694 | }; | 702 | }; |
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index 5cc63d02..73f8fc72 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp | |||
@@ -210,6 +210,11 @@ static HRESULT ExecuteRelatedBundle( | |||
210 | __out BOOL* pfSuspend, | 210 | __out BOOL* pfSuspend, |
211 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | 211 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart |
212 | ); | 212 | ); |
213 | static HRESULT DoRestoreRelatedBundleActions( | ||
214 | __in BURN_ENGINE_STATE* pEngineState, | ||
215 | __in BURN_EXECUTE_CONTEXT* pContext, | ||
216 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
217 | ); | ||
213 | static HRESULT ExecuteExePackage( | 218 | static HRESULT ExecuteExePackage( |
214 | __in BURN_ENGINE_STATE* pEngineState, | 219 | __in BURN_ENGINE_STATE* pEngineState, |
215 | __in BURN_EXECUTE_ACTION* pExecuteAction, | 220 | __in BURN_EXECUTE_ACTION* pExecuteAction, |
@@ -788,6 +793,9 @@ extern "C" HRESULT ApplyExecute( | |||
788 | { | 793 | { |
789 | if (pCheckpoint->pActiveRollbackBoundary->fVital) | 794 | if (pCheckpoint->pActiveRollbackBoundary->fVital) |
790 | { | 795 | { |
796 | hrRollback = DoRestoreRelatedBundleActions(pEngineState, &context, pRestart); | ||
797 | IgnoreRollbackError(hrRollback, "Failed rollback actions"); | ||
798 | |||
791 | // If the rollback boundary is vital, end execution here. | 799 | // If the rollback boundary is vital, end execution here. |
792 | break; | 800 | break; |
793 | } | 801 | } |
@@ -2590,6 +2598,48 @@ LExit: | |||
2590 | return hr; | 2598 | return hr; |
2591 | } | 2599 | } |
2592 | 2600 | ||
2601 | static HRESULT DoRestoreRelatedBundleActions( | ||
2602 | __in BURN_ENGINE_STATE* pEngineState, | ||
2603 | __in BURN_EXECUTE_CONTEXT* pContext, | ||
2604 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
2605 | ) | ||
2606 | { | ||
2607 | HRESULT hr = S_OK; | ||
2608 | BOOL fRetryIgnored = FALSE; | ||
2609 | BOOL fSuspendIgnored = FALSE; | ||
2610 | |||
2611 | // execute restore related bundle actions | ||
2612 | for (DWORD i = 0; i < pEngineState->plan.cRestoreRelatedBundleActions; ++i) | ||
2613 | { | ||
2614 | BURN_EXECUTE_ACTION* pRestoreRelatedBundleAction = &pEngineState->plan.rgRestoreRelatedBundleActions[i]; | ||
2615 | if (pRestoreRelatedBundleAction->fDeleted) | ||
2616 | { | ||
2617 | continue; | ||
2618 | } | ||
2619 | |||
2620 | BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
2621 | switch (pRestoreRelatedBundleAction->type) | ||
2622 | { | ||
2623 | case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: | ||
2624 | hr = ExecuteRelatedBundle(pEngineState, pRestoreRelatedBundleAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); | ||
2625 | IgnoreRollbackError(hr, "Failed to restore related bundle package."); | ||
2626 | break; | ||
2627 | |||
2628 | default: | ||
2629 | hr = E_UNEXPECTED; | ||
2630 | ExitOnFailure(hr, "Invalid restore related bundle action: %d.", pRestoreRelatedBundleAction->type); | ||
2631 | } | ||
2632 | |||
2633 | if (*pRestart < restart) | ||
2634 | { | ||
2635 | *pRestart = restart; | ||
2636 | } | ||
2637 | } | ||
2638 | |||
2639 | LExit: | ||
2640 | return hr; | ||
2641 | } | ||
2642 | |||
2593 | static HRESULT ExecuteExePackage( | 2643 | static HRESULT ExecuteExePackage( |
2594 | __in BURN_ENGINE_STATE* pEngineState, | 2644 | __in BURN_ENGINE_STATE* pEngineState, |
2595 | __in BURN_EXECUTE_ACTION* pExecuteAction, | 2645 | __in BURN_EXECUTE_ACTION* pExecuteAction, |
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp index cd84601f..b5fc51e5 100644 --- a/src/burn/engine/bundlepackageengine.cpp +++ b/src/burn/engine/bundlepackageengine.cpp | |||
@@ -51,7 +51,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
51 | execute = BOOTSTRAPPER_ACTION_STATE_NONE; | 51 | execute = BOOTSTRAPPER_ACTION_STATE_NONE; |
52 | break; | 52 | break; |
53 | case BOOTSTRAPPER_REQUEST_STATE_REPAIR: | 53 | case BOOTSTRAPPER_REQUEST_STATE_REPAIR: |
54 | execute = pPackage->Bundle.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE; | 54 | execute = BOOTSTRAPPER_ACTION_STATE_REPAIR; |
55 | break; | 55 | break; |
56 | case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough; | 56 | case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough; |
57 | case BOOTSTRAPPER_REQUEST_STATE_CACHE: | 57 | case BOOTSTRAPPER_REQUEST_STATE_CACHE: |
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 7f7a915e..8fac7bd0 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp | |||
@@ -558,7 +558,7 @@ extern "C" HRESULT CorePlan( | |||
558 | ExitOnFailure(hr, "Failed to plan packages."); | 558 | ExitOnFailure(hr, "Failed to plan packages."); |
559 | 559 | ||
560 | // Schedule the update of related bundles last. | 560 | // Schedule the update of related bundles last. |
561 | hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, dwExecuteActionEarlyIndex); | 561 | hr = PlanRelatedBundlesComplete(&pEngineState->userExperience, &pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, dwExecuteActionEarlyIndex); |
562 | ExitOnFailure(hr, "Failed to schedule related bundles."); | 562 | ExitOnFailure(hr, "Failed to schedule related bundles."); |
563 | } | 563 | } |
564 | } | 564 | } |
@@ -2309,7 +2309,7 @@ static void LogRelatedBundles( | |||
2309 | 2309 | ||
2310 | if (pRelatedBundle->fPlannable) | 2310 | if (pRelatedBundle->fPlannable) |
2311 | { | 2311 | { |
2312 | LogId(REPORT_STANDARD, MSG_PLANNED_RELATED_BUNDLE, pPackage->sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingDependencyActionToString(pPackage->dependencyExecute)); | 2312 | 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)); |
2313 | } | 2313 | } |
2314 | } | 2314 | } |
2315 | } | 2315 | } |
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index b8c9a2d3..675a5644 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc | |||
@@ -352,13 +352,6 @@ Language=English | |||
352 | Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, default cache strategy: %7!hs!, ba requested strategy: %8!hs!, cache: %9!hs!, uncache: %10!hs!, dependency: %11!hs!, expected install registration state: %12!hs!, expected cache registration state: %13!hs! | 352 | Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, default cache strategy: %7!hs!, ba requested strategy: %8!hs!, cache: %9!hs!, uncache: %10!hs!, dependency: %11!hs!, expected install registration state: %12!hs!, expected cache registration state: %13!hs! |
353 | . | 353 | . |
354 | 354 | ||
355 | MessageId=202 | ||
356 | Severity=Success | ||
357 | SymbolicName=MSG_PLANNED_BUNDLE_UX_CHANGED_REQUEST | ||
358 | Language=English | ||
359 | Planned bundle: %1!ls!, ba requested state: %2!hs! over default: %3!hs! | ||
360 | . | ||
361 | |||
362 | MessageId=203 | 355 | MessageId=203 |
363 | Severity=Success | 356 | Severity=Success |
364 | SymbolicName=MSG_PLANNED_MSI_FEATURE | 357 | SymbolicName=MSG_PLANNED_MSI_FEATURE |
@@ -391,7 +384,7 @@ MessageId=207 | |||
391 | Severity=Success | 384 | Severity=Success |
392 | SymbolicName=MSG_PLANNED_RELATED_BUNDLE | 385 | SymbolicName=MSG_PLANNED_RELATED_BUNDLE |
393 | Language=English | 386 | Language=English |
394 | Planned related bundle: %1!ls!, type: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, dependency: %7!hs! | 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! |
395 | . | 388 | . |
396 | 389 | ||
397 | MessageId=208 | 390 | MessageId=208 |
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h index 6d1b5dd9..1e61d92b 100644 --- a/src/burn/engine/package.h +++ b/src/burn/engine/package.h | |||
@@ -309,7 +309,6 @@ typedef struct _BURN_PACKAGE | |||
309 | LPCWSTR wzAncestors; // points directly into engine state. | 309 | LPCWSTR wzAncestors; // points directly into engine state. |
310 | LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. | 310 | LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. |
311 | 311 | ||
312 | BOOL fRepairable; | ||
313 | BOOL fSupportsBurnProtocol; | 312 | BOOL fSupportsBurnProtocol; |
314 | 313 | ||
315 | BURN_EXE_EXIT_CODE* rgExitCodes; | 314 | BURN_EXE_EXIT_CODE* rgExitCodes; |
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp index f850d49c..f1fb87b8 100644 --- a/src/burn/engine/plan.cpp +++ b/src/burn/engine/plan.cpp | |||
@@ -103,6 +103,10 @@ static HRESULT AppendCleanAction( | |||
103 | __in BURN_PLAN* pPlan, | 103 | __in BURN_PLAN* pPlan, |
104 | __out BURN_CLEAN_ACTION** ppCleanAction | 104 | __out BURN_CLEAN_ACTION** ppCleanAction |
105 | ); | 105 | ); |
106 | static HRESULT AppendRestoreRelatedBundleAction( | ||
107 | __in BURN_PLAN* pPlan, | ||
108 | __out BURN_EXECUTE_ACTION** ppExecuteAction | ||
109 | ); | ||
106 | static HRESULT ProcessPayloadGroup( | 110 | static HRESULT ProcessPayloadGroup( |
107 | __in BURN_PLAN* pPlan, | 111 | __in BURN_PLAN* pPlan, |
108 | __in BURN_PAYLOAD_GROUP* pPayloadGroup | 112 | __in BURN_PAYLOAD_GROUP* pPayloadGroup |
@@ -196,6 +200,15 @@ extern "C" void PlanReset( | |||
196 | MemFree(pPlan->rgRollbackActions); | 200 | MemFree(pPlan->rgRollbackActions); |
197 | } | 201 | } |
198 | 202 | ||
203 | if (pPlan->rgRestoreRelatedBundleActions) | ||
204 | { | ||
205 | for (DWORD i = 0; i < pPlan->cRestoreRelatedBundleActions; ++i) | ||
206 | { | ||
207 | PlanUninitializeExecuteAction(&pPlan->rgRestoreRelatedBundleActions[i]); | ||
208 | } | ||
209 | MemFree(pPlan->rgRestoreRelatedBundleActions); | ||
210 | } | ||
211 | |||
199 | if (pPlan->rgCleanActions) | 212 | if (pPlan->rgCleanActions) |
200 | { | 213 | { |
201 | // Nothing needs to be freed inside clean actions today. | 214 | // Nothing needs to be freed inside clean actions today. |
@@ -1276,6 +1289,9 @@ extern "C" HRESULT PlanRelatedBundlesBegin( | |||
1276 | continue; | 1289 | continue; |
1277 | } | 1290 | } |
1278 | 1291 | ||
1292 | pRelatedBundle->defaultRequestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE; | ||
1293 | pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE; | ||
1294 | pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
1279 | pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; | 1295 | pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; |
1280 | pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; | 1296 | pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; |
1281 | 1297 | ||
@@ -1312,12 +1328,6 @@ extern "C" HRESULT PlanRelatedBundlesBegin( | |||
1312 | hr = UserExperienceOnPlanRelatedBundle(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->package.requested); | 1328 | hr = UserExperienceOnPlanRelatedBundle(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->package.requested); |
1313 | ExitOnRootFailure(hr, "BA aborted plan related bundle."); | 1329 | ExitOnRootFailure(hr, "BA aborted plan related bundle."); |
1314 | 1330 | ||
1315 | // Log when the BA changed the bundle state so the engine doesn't get blamed for planning the wrong thing. | ||
1316 | if (pRelatedBundle->package.requested != pRelatedBundle->package.defaultRequested) | ||
1317 | { | ||
1318 | LogId(REPORT_STANDARD, MSG_PLANNED_BUNDLE_UX_CHANGED_REQUEST, pRelatedBundle->package.sczId, LoggingRequestStateToString(pRelatedBundle->package.requested), LoggingRequestStateToString(pRelatedBundle->package.defaultRequested)); | ||
1319 | } | ||
1320 | |||
1321 | // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. | 1331 | // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. |
1322 | if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) | 1332 | if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) |
1323 | { | 1333 | { |
@@ -1340,6 +1350,7 @@ LExit: | |||
1340 | } | 1350 | } |
1341 | 1351 | ||
1342 | extern "C" HRESULT PlanRelatedBundlesComplete( | 1352 | extern "C" HRESULT PlanRelatedBundlesComplete( |
1353 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
1343 | __in BURN_REGISTRATION* pRegistration, | 1354 | __in BURN_REGISTRATION* pRegistration, |
1344 | __in BURN_PLAN* pPlan, | 1355 | __in BURN_PLAN* pPlan, |
1345 | __in BURN_LOGGING* pLog, | 1356 | __in BURN_LOGGING* pLog, |
@@ -1359,16 +1370,19 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1359 | ExitOnFailure(hr, "Failed to create dictionary for planned packages."); | 1370 | ExitOnFailure(hr, "Failed to create dictionary for planned packages."); |
1360 | 1371 | ||
1361 | BOOL fExecutingAnyPackage = FALSE; | 1372 | BOOL fExecutingAnyPackage = FALSE; |
1373 | BOOL fInstallingAnyPackage = FALSE; | ||
1362 | 1374 | ||
1363 | for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) | 1375 | for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) |
1364 | { | 1376 | { |
1377 | BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
1378 | |||
1365 | switch (pPlan->rgExecuteActions[i].type) | 1379 | switch (pPlan->rgExecuteActions[i].type) |
1366 | { | 1380 | { |
1367 | case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: | 1381 | case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: |
1368 | if (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].relatedBundle.action) | 1382 | packageAction = pPlan->rgExecuteActions[i].relatedBundle.action; |
1369 | { | ||
1370 | fExecutingAnyPackage = TRUE; | ||
1371 | 1383 | ||
1384 | if (BOOTSTRAPPER_ACTION_STATE_NONE != packageAction) | ||
1385 | { | ||
1372 | BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package; | 1386 | BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package; |
1373 | if (pPackage->cDependencyProviders) | 1387 | if (pPackage->cDependencyProviders) |
1374 | { | 1388 | { |
@@ -1380,21 +1394,24 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1380 | break; | 1394 | break; |
1381 | 1395 | ||
1382 | case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: | 1396 | case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: |
1383 | fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action); | 1397 | packageAction = pPlan->rgExecuteActions[i].exePackage.action; |
1384 | break; | 1398 | break; |
1385 | 1399 | ||
1386 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: | 1400 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: |
1387 | fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action); | 1401 | packageAction = pPlan->rgExecuteActions[i].msiPackage.action; |
1388 | break; | 1402 | break; |
1389 | 1403 | ||
1390 | case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: | 1404 | case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: |
1391 | fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action); | 1405 | packageAction = pPlan->rgExecuteActions[i].mspTarget.action; |
1392 | break; | 1406 | break; |
1393 | 1407 | ||
1394 | case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: | 1408 | case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: |
1395 | fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action); | 1409 | packageAction = pPlan->rgExecuteActions[i].msuPackage.action; |
1396 | break; | 1410 | break; |
1397 | } | 1411 | } |
1412 | |||
1413 | fExecutingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_NONE != packageAction; | ||
1414 | fInstallingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_INSTALL == packageAction || BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE == packageAction; | ||
1398 | } | 1415 | } |
1399 | 1416 | ||
1400 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) | 1417 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) |
@@ -1492,6 +1509,62 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1492 | hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan); | 1509 | hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan); |
1493 | ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId); | 1510 | ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId); |
1494 | } | 1511 | } |
1512 | |||
1513 | if (fInstallingAnyPackage && BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType) | ||
1514 | { | ||
1515 | BURN_EXECUTE_ACTION* pAction = NULL; | ||
1516 | |||
1517 | pRelatedBundle->defaultRequestedRestore = pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT; | ||
1518 | |||
1519 | hr = UserExperienceOnPlanRestoreRelatedBundle(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->requestedRestore); | ||
1520 | ExitOnRootFailure(hr, "BA aborted plan restore related bundle."); | ||
1521 | |||
1522 | switch (pRelatedBundle->requestedRestore) | ||
1523 | { | ||
1524 | case BOOTSTRAPPER_REQUEST_STATE_REPAIR: | ||
1525 | pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_REPAIR; | ||
1526 | break; | ||
1527 | case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough; | ||
1528 | case BOOTSTRAPPER_REQUEST_STATE_CACHE: __fallthrough; | ||
1529 | case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: | ||
1530 | pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; | ||
1531 | break; | ||
1532 | case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: | ||
1533 | pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_INSTALL; | ||
1534 | break; | ||
1535 | default: | ||
1536 | pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE; | ||
1537 | break; | ||
1538 | } | ||
1539 | |||
1540 | if (BOOTSTRAPPER_ACTION_STATE_NONE != pRelatedBundle->restore) | ||
1541 | { | ||
1542 | hr = AppendRestoreRelatedBundleAction(pPlan, &pAction); | ||
1543 | ExitOnFailure(hr, "Failed to append restore related bundle action to plan."); | ||
1544 | |||
1545 | pAction->type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE; | ||
1546 | pAction->relatedBundle.pRelatedBundle = pRelatedBundle; | ||
1547 | pAction->relatedBundle.action = pRelatedBundle->restore; | ||
1548 | |||
1549 | if (pRelatedBundle->package.Bundle.sczIgnoreDependencies) | ||
1550 | { | ||
1551 | hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pRelatedBundle->package.Bundle.sczIgnoreDependencies, 0); | ||
1552 | ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); | ||
1553 | } | ||
1554 | |||
1555 | if (pRelatedBundle->package.Bundle.wzAncestors) | ||
1556 | { | ||
1557 | hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pRelatedBundle->package.Bundle.wzAncestors, 0); | ||
1558 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); | ||
1559 | } | ||
1560 | |||
1561 | if (pRelatedBundle->package.Bundle.wzEngineWorkingDirectory) | ||
1562 | { | ||
1563 | hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pRelatedBundle->package.Bundle.wzEngineWorkingDirectory, 0); | ||
1564 | ExitOnFailure(hr, "Failed to allocate the custom working directory."); | ||
1565 | } | ||
1566 | } | ||
1567 | } | ||
1495 | } | 1568 | } |
1496 | 1569 | ||
1497 | LExit: | 1570 | LExit: |
@@ -2269,6 +2342,23 @@ LExit: | |||
2269 | return hr; | 2342 | return hr; |
2270 | } | 2343 | } |
2271 | 2344 | ||
2345 | static HRESULT AppendRestoreRelatedBundleAction( | ||
2346 | __in BURN_PLAN* pPlan, | ||
2347 | __out BURN_EXECUTE_ACTION** ppExecuteAction | ||
2348 | ) | ||
2349 | { | ||
2350 | HRESULT hr = S_OK; | ||
2351 | |||
2352 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pPlan->rgRestoreRelatedBundleActions), pPlan->cRestoreRelatedBundleActions, 1, sizeof(BURN_EXECUTE_ACTION), 5); | ||
2353 | ExitOnFailure(hr, "Failed to grow plan's array of restore related bundle actions."); | ||
2354 | |||
2355 | *ppExecuteAction = pPlan->rgRestoreRelatedBundleActions + pPlan->cRestoreRelatedBundleActions; | ||
2356 | ++pPlan->cRestoreRelatedBundleActions; | ||
2357 | |||
2358 | LExit: | ||
2359 | return hr; | ||
2360 | } | ||
2361 | |||
2272 | static HRESULT ProcessPayloadGroup( | 2362 | static HRESULT ProcessPayloadGroup( |
2273 | __in BURN_PLAN* pPlan, | 2363 | __in BURN_PLAN* pPlan, |
2274 | __in BURN_PAYLOAD_GROUP* pPayloadGroup | 2364 | __in BURN_PAYLOAD_GROUP* pPayloadGroup |
@@ -2725,6 +2815,28 @@ static void ExecuteActionLog( | |||
2725 | } | 2815 | } |
2726 | } | 2816 | } |
2727 | 2817 | ||
2818 | static void RestoreRelatedBundleActionLog( | ||
2819 | __in DWORD iAction, | ||
2820 | __in BURN_EXECUTE_ACTION* pAction | ||
2821 | ) | ||
2822 | { | ||
2823 | switch (pAction->type) | ||
2824 | { | ||
2825 | case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: | ||
2826 | LogStringLine(PlanDumpLevel, "Restore action[%u]: RELATED_BUNDLE package id: %ls, action: %hs, ignore dependencies: %ls", iAction, pAction->relatedBundle.pRelatedBundle->package.sczId, LoggingActionStateToString(pAction->relatedBundle.action), pAction->relatedBundle.sczIgnoreDependencies); | ||
2827 | break; | ||
2828 | |||
2829 | default: | ||
2830 | AssertSz(FALSE, "Unknown execute action type."); | ||
2831 | break; | ||
2832 | } | ||
2833 | |||
2834 | if (pAction->fDeleted) | ||
2835 | { | ||
2836 | LogStringLine(PlanDumpLevel, " (deleted action)"); | ||
2837 | } | ||
2838 | } | ||
2839 | |||
2728 | static void CleanActionLog( | 2840 | static void CleanActionLog( |
2729 | __in DWORD iAction, | 2841 | __in DWORD iAction, |
2730 | __in BURN_CLEAN_ACTION* pAction | 2842 | __in BURN_CLEAN_ACTION* pAction |
@@ -2784,6 +2896,11 @@ extern "C" void PlanDump( | |||
2784 | ExecuteActionLog(i, pPlan->rgRollbackActions + i, TRUE); | 2896 | ExecuteActionLog(i, pPlan->rgRollbackActions + i, TRUE); |
2785 | } | 2897 | } |
2786 | 2898 | ||
2899 | for (DWORD i = 0; i < pPlan->cRestoreRelatedBundleActions; ++i) | ||
2900 | { | ||
2901 | RestoreRelatedBundleActionLog(i, pPlan->rgRestoreRelatedBundleActions + i); | ||
2902 | } | ||
2903 | |||
2787 | for (DWORD i = 0; i < pPlan->cCleanActions; ++i) | 2904 | for (DWORD i = 0; i < pPlan->cCleanActions; ++i) |
2788 | { | 2905 | { |
2789 | CleanActionLog(i, pPlan->rgCleanActions + i); | 2906 | CleanActionLog(i, pPlan->rgCleanActions + i); |
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h index 0734e39f..3dce8e5d 100644 --- a/src/burn/engine/plan.h +++ b/src/burn/engine/plan.h | |||
@@ -280,6 +280,9 @@ typedef struct _BURN_PLAN | |||
280 | BURN_EXECUTE_ACTION* rgRollbackActions; | 280 | BURN_EXECUTE_ACTION* rgRollbackActions; |
281 | DWORD cRollbackActions; | 281 | DWORD cRollbackActions; |
282 | 282 | ||
283 | BURN_EXECUTE_ACTION* rgRestoreRelatedBundleActions; | ||
284 | DWORD cRestoreRelatedBundleActions; | ||
285 | |||
283 | BURN_CLEAN_ACTION* rgCleanActions; | 286 | BURN_CLEAN_ACTION* rgCleanActions; |
284 | DWORD cCleanActions; | 287 | DWORD cCleanActions; |
285 | 288 | ||
@@ -394,6 +397,7 @@ HRESULT PlanRelatedBundlesBegin( | |||
394 | __in BURN_PLAN* pPlan | 397 | __in BURN_PLAN* pPlan |
395 | ); | 398 | ); |
396 | HRESULT PlanRelatedBundlesComplete( | 399 | HRESULT PlanRelatedBundlesComplete( |
400 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
397 | __in BURN_REGISTRATION* pRegistration, | 401 | __in BURN_REGISTRATION* pRegistration, |
398 | __in BURN_PLAN* pPlan, | 402 | __in BURN_PLAN* pPlan, |
399 | __in BURN_LOGGING* pLog, | 403 | __in BURN_LOGGING* pLog, |
diff --git a/src/burn/engine/pseudobundle.cpp b/src/burn/engine/pseudobundle.cpp index 94b095c5..082c4487 100644 --- a/src/burn/engine/pseudobundle.cpp +++ b/src/burn/engine/pseudobundle.cpp | |||
@@ -51,7 +51,6 @@ extern "C" HRESULT PseudoBundleInitializeRelated( | |||
51 | pPackage->fVital = FALSE; | 51 | pPackage->fVital = FALSE; |
52 | 52 | ||
53 | pPackage->fPermanent = FALSE; | 53 | pPackage->fPermanent = FALSE; |
54 | pPackage->Bundle.fRepairable = TRUE; | ||
55 | pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol; | 54 | pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol; |
56 | 55 | ||
57 | hr = StrAllocString(&pPackage->sczId, wzId, 0); | 56 | hr = StrAllocString(&pPackage->sczId, wzId, 0); |
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h index 0ae61974..64191828 100644 --- a/src/burn/engine/registration.h +++ b/src/burn/engine/registration.h | |||
@@ -61,6 +61,10 @@ typedef struct _BURN_RELATED_BUNDLE | |||
61 | BOOL fPlannable; | 61 | BOOL fPlannable; |
62 | 62 | ||
63 | BURN_PACKAGE package; | 63 | BURN_PACKAGE package; |
64 | |||
65 | BOOTSTRAPPER_REQUEST_STATE defaultRequestedRestore; | ||
66 | BOOTSTRAPPER_REQUEST_STATE requestedRestore; | ||
67 | BOOTSTRAPPER_ACTION_STATE restore; | ||
64 | } BURN_RELATED_BUNDLE; | 68 | } BURN_RELATED_BUNDLE; |
65 | 69 | ||
66 | typedef struct _BURN_RELATED_BUNDLES | 70 | typedef struct _BURN_RELATED_BUNDLES |
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 1439f5f2..59988bef 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp | |||
@@ -2176,6 +2176,36 @@ LExit: | |||
2176 | return hr; | 2176 | return hr; |
2177 | } | 2177 | } |
2178 | 2178 | ||
2179 | EXTERN_C BAAPI UserExperienceOnPlanRestoreRelatedBundle( | ||
2180 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
2181 | __in_z LPCWSTR wzBundleId, | ||
2182 | __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState | ||
2183 | ) | ||
2184 | { | ||
2185 | HRESULT hr = S_OK; | ||
2186 | BA_ONPLANRESTORERELATEDBUNDLE_ARGS args = { }; | ||
2187 | BA_ONPLANRESTORERELATEDBUNDLE_RESULTS results = { }; | ||
2188 | |||
2189 | args.cbSize = sizeof(args); | ||
2190 | args.wzBundleId = wzBundleId; | ||
2191 | args.recommendedState = *pRequestedState; | ||
2192 | |||
2193 | results.cbSize = sizeof(results); | ||
2194 | results.requestedState = *pRequestedState; | ||
2195 | |||
2196 | hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, &args, &results); | ||
2197 | ExitOnFailure(hr, "BA OnPlanRestoreRelatedBundle failed."); | ||
2198 | |||
2199 | if (results.fCancel) | ||
2200 | { | ||
2201 | hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); | ||
2202 | } | ||
2203 | *pRequestedState = results.requestedState; | ||
2204 | |||
2205 | LExit: | ||
2206 | return hr; | ||
2207 | } | ||
2208 | |||
2179 | EXTERN_C BAAPI UserExperienceOnPlanRollbackBoundary( | 2209 | EXTERN_C BAAPI UserExperienceOnPlanRollbackBoundary( |
2180 | __in BURN_USER_EXPERIENCE* pUserExperience, | 2210 | __in BURN_USER_EXPERIENCE* pUserExperience, |
2181 | __in_z LPCWSTR wzRollbackBoundaryId, | 2211 | __in_z LPCWSTR wzRollbackBoundaryId, |
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index e8341120..8106d7f7 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h | |||
@@ -497,6 +497,11 @@ BAAPI UserExperienceOnPlanRelatedBundle( | |||
497 | __in_z LPCWSTR wzBundleId, | 497 | __in_z LPCWSTR wzBundleId, |
498 | __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState | 498 | __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState |
499 | ); | 499 | ); |
500 | BAAPI UserExperienceOnPlanRestoreRelatedBundle( | ||
501 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
502 | __in_z LPCWSTR wzBundleId, | ||
503 | __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState | ||
504 | ); | ||
500 | BAAPI UserExperienceOnPlanRollbackBoundary( | 505 | BAAPI UserExperienceOnPlanRollbackBoundary( |
501 | __in BURN_USER_EXPERIENCE* pUserExperience, | 506 | __in BURN_USER_EXPERIENCE* pUserExperience, |
502 | __in_z LPCWSTR wzRollbackBoundaryId, | 507 | __in_z LPCWSTR wzRollbackBoundaryId, |
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp index 99644115..81484234 100644 --- a/src/burn/test/BurnUnitTest/PlanTest.cpp +++ b/src/burn/test/BurnUnitTest/PlanTest.cpp | |||
@@ -170,6 +170,10 @@ namespace Bootstrapper | |||
170 | Assert::Equal(7ul, pPlan->cOverallProgressTicksTotal); | 170 | Assert::Equal(7ul, pPlan->cOverallProgressTicksTotal); |
171 | 171 | ||
172 | dwIndex = 0; | 172 | dwIndex = 0; |
173 | ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); | ||
174 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
175 | |||
176 | dwIndex = 0; | ||
173 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 177 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
174 | 178 | ||
175 | UINT uIndex = 0; | 179 | UINT uIndex = 0; |
@@ -277,6 +281,9 @@ namespace Bootstrapper | |||
277 | Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); | 281 | Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); |
278 | 282 | ||
279 | dwIndex = 0; | 283 | dwIndex = 0; |
284 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
285 | |||
286 | dwIndex = 0; | ||
280 | ValidateCleanAction(pPlan, dwIndex++, L"PackageC"); | 287 | ValidateCleanAction(pPlan, dwIndex++, L"PackageC"); |
281 | ValidateCleanAction(pPlan, dwIndex++, L"PackageB"); | 288 | ValidateCleanAction(pPlan, dwIndex++, L"PackageB"); |
282 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | 289 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); |
@@ -350,6 +357,9 @@ namespace Bootstrapper | |||
350 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); | 357 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); |
351 | 358 | ||
352 | dwIndex = 0; | 359 | dwIndex = 0; |
360 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
361 | |||
362 | dwIndex = 0; | ||
353 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | 363 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); |
354 | ValidateCleanCompatibleAction(pPlan, dwIndex++, L"PackageA"); | 364 | ValidateCleanCompatibleAction(pPlan, dwIndex++, L"PackageA"); |
355 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 365 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
@@ -438,6 +448,9 @@ namespace Bootstrapper | |||
438 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); | 448 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); |
439 | 449 | ||
440 | dwIndex = 0; | 450 | dwIndex = 0; |
451 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
452 | |||
453 | dwIndex = 0; | ||
441 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 454 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
442 | 455 | ||
443 | UINT uIndex = 0; | 456 | UINT uIndex = 0; |
@@ -508,6 +521,9 @@ namespace Bootstrapper | |||
508 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); | 521 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); |
509 | 522 | ||
510 | dwIndex = 0; | 523 | dwIndex = 0; |
524 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
525 | |||
526 | dwIndex = 0; | ||
511 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 527 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
512 | 528 | ||
513 | UINT uIndex = 0; | 529 | UINT uIndex = 0; |
@@ -579,6 +595,9 @@ namespace Bootstrapper | |||
579 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); | 595 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); |
580 | 596 | ||
581 | dwIndex = 0; | 597 | dwIndex = 0; |
598 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
599 | |||
600 | dwIndex = 0; | ||
582 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | 601 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); |
583 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 602 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
584 | 603 | ||
@@ -658,6 +677,10 @@ namespace Bootstrapper | |||
658 | Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); | 677 | Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); |
659 | 678 | ||
660 | dwIndex = 0; | 679 | dwIndex = 0; |
680 | ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); | ||
681 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
682 | |||
683 | dwIndex = 0; | ||
661 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 684 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
662 | 685 | ||
663 | UINT uIndex = 0; | 686 | UINT uIndex = 0; |
@@ -744,6 +767,10 @@ namespace Bootstrapper | |||
744 | Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); | 767 | Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); |
745 | 768 | ||
746 | dwIndex = 0; | 769 | dwIndex = 0; |
770 | ValidateRestoreRelatedBundle(pPlan, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); | ||
771 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
772 | |||
773 | dwIndex = 0; | ||
747 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 774 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
748 | 775 | ||
749 | UINT uIndex = 0; | 776 | UINT uIndex = 0; |
@@ -805,6 +832,9 @@ namespace Bootstrapper | |||
805 | Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); | 832 | Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); |
806 | 833 | ||
807 | dwIndex = 0; | 834 | dwIndex = 0; |
835 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
836 | |||
837 | dwIndex = 0; | ||
808 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | 838 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); |
809 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 839 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
810 | 840 | ||
@@ -879,6 +909,9 @@ namespace Bootstrapper | |||
879 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); | 909 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); |
880 | 910 | ||
881 | dwIndex = 0; | 911 | dwIndex = 0; |
912 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
913 | |||
914 | dwIndex = 0; | ||
882 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | 915 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); |
883 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 916 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
884 | 917 | ||
@@ -946,6 +979,9 @@ namespace Bootstrapper | |||
946 | Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); | 979 | Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); |
947 | 980 | ||
948 | dwIndex = 0; | 981 | dwIndex = 0; |
982 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
983 | |||
984 | dwIndex = 0; | ||
949 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 985 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
950 | 986 | ||
951 | UINT uIndex = 0; | 987 | UINT uIndex = 0; |
@@ -1057,6 +1093,9 @@ namespace Bootstrapper | |||
1057 | Assert::Equal(5ul, pPlan->cOverallProgressTicksTotal); | 1093 | Assert::Equal(5ul, pPlan->cOverallProgressTicksTotal); |
1058 | 1094 | ||
1059 | dwIndex = 0; | 1095 | dwIndex = 0; |
1096 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
1097 | |||
1098 | dwIndex = 0; | ||
1060 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 1099 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
1061 | 1100 | ||
1062 | UINT uIndex = 0; | 1101 | UINT uIndex = 0; |
@@ -1147,6 +1186,9 @@ namespace Bootstrapper | |||
1147 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); | 1186 | Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); |
1148 | 1187 | ||
1149 | dwIndex = 0; | 1188 | dwIndex = 0; |
1189 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
1190 | |||
1191 | dwIndex = 0; | ||
1150 | ValidateCleanAction(pPlan, dwIndex++, L"PatchA"); | 1192 | ValidateCleanAction(pPlan, dwIndex++, L"PatchA"); |
1151 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | 1193 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); |
1152 | Assert::Equal(dwIndex, pPlan->cCleanActions); | 1194 | Assert::Equal(dwIndex, pPlan->cCleanActions); |
@@ -1829,6 +1871,28 @@ namespace Bootstrapper | |||
1829 | NativeAssert::StringEqual(wzName, pProvider->sczName); | 1871 | NativeAssert::StringEqual(wzName, pProvider->sczName); |
1830 | } | 1872 | } |
1831 | 1873 | ||
1874 | void ValidateRestoreRelatedBundle( | ||
1875 | __in BURN_PLAN* pPlan, | ||
1876 | __in DWORD dwIndex, | ||
1877 | __in LPCWSTR wzPackageId, | ||
1878 | __in BOOTSTRAPPER_ACTION_STATE action, | ||
1879 | __in LPCWSTR wzIgnoreDependencies | ||
1880 | ) | ||
1881 | { | ||
1882 | BURN_EXECUTE_ACTION* pAction = ValidateRestoreRelatedBundleActionExists(pPlan, dwIndex); | ||
1883 | Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE, pAction->type); | ||
1884 | NativeAssert::StringEqual(wzPackageId, pAction->relatedBundle.pRelatedBundle->package.sczId); | ||
1885 | Assert::Equal<DWORD>(action, pAction->relatedBundle.action); | ||
1886 | NativeAssert::StringEqual(wzIgnoreDependencies, pAction->relatedBundle.sczIgnoreDependencies); | ||
1887 | Assert::Equal<BOOL>(FALSE, pAction->fDeleted); | ||
1888 | } | ||
1889 | |||
1890 | BURN_EXECUTE_ACTION* ValidateRestoreRelatedBundleActionExists(BURN_PLAN* pPlan, DWORD dwIndex) | ||
1891 | { | ||
1892 | Assert::InRange(dwIndex + 1ul, 1ul, pPlan->cRestoreRelatedBundleActions); | ||
1893 | return pPlan->rgRestoreRelatedBundleActions + dwIndex; | ||
1894 | } | ||
1895 | |||
1832 | void ValidateUninstallMsiCompatiblePackage( | 1896 | void ValidateUninstallMsiCompatiblePackage( |
1833 | __in BURN_PLAN* pPlan, | 1897 | __in BURN_PLAN* pPlan, |
1834 | __in BOOL fRollback, | 1898 | __in BOOL fRollback, |
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp index 02c10472..8c7bce7e 100644 --- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp | |||
@@ -2089,6 +2089,16 @@ private: // privates | |||
2089 | m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext); | 2089 | m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext); |
2090 | } | 2090 | } |
2091 | 2091 | ||
2092 | void OnPlanRestoreRelatedBundleFallback( | ||
2093 | __in BA_ONPLANRESTORERELATEDBUNDLE_ARGS* pArgs, | ||
2094 | __inout BA_ONPLANRESTORERELATEDBUNDLE_RESULTS* pResults | ||
2095 | ) | ||
2096 | { | ||
2097 | BOOTSTRAPPER_REQUEST_STATE requestedState = pResults->requestedState; | ||
2098 | m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE, pArgs, pResults, m_pvBAFunctionsProcContext); | ||
2099 | BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RESTORE_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState)); | ||
2100 | } | ||
2101 | |||
2092 | 2102 | ||
2093 | public: //CBalBaseBootstrapperApplication | 2103 | public: //CBalBaseBootstrapperApplication |
2094 | virtual STDMETHODIMP Initialize( | 2104 | virtual STDMETHODIMP Initialize( |
diff --git a/src/ext/Bal/wixstdba/wixstdba.mc b/src/ext/Bal/wixstdba/wixstdba.mc index 40acfe54..eeb69914 100644 --- a/src/ext/Bal/wixstdba/wixstdba.mc +++ b/src/ext/Bal/wixstdba/wixstdba.mc | |||
@@ -85,3 +85,10 @@ Language=English | |||
85 | WIXSTDBA: Planned rollback boundary: %1!ls!, wixstdba requested transaction: %2!hs!, bafunctions requested transaction: %3!hs! | 85 | WIXSTDBA: Planned rollback boundary: %1!ls!, wixstdba requested transaction: %2!hs!, bafunctions requested transaction: %3!hs! |
86 | . | 86 | . |
87 | 87 | ||
88 | MessageId=9 | ||
89 | Severity=Success | ||
90 | SymbolicName=MSG_WIXSTDBA_PLANNED_RESTORE_RELATED_BUNDLE | ||
91 | Language=English | ||
92 | WIXSTDBA: Planned restore related bundle: %1!ls!, wixstdba requested: %2!hs!, bafunctions requested: %3!hs! | ||
93 | . | ||
94 | |||
diff --git a/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv3/BundleAv3.wixproj b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv3/BundleAv3.wixproj new file mode 100644 index 00000000..958ceb47 --- /dev/null +++ b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv3/BundleAv3.wixproj | |||
@@ -0,0 +1,16 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <Import Project="..\BundleAv1\BundleA.props" /> | ||
4 | <PropertyGroup> | ||
5 | <Version>3.0.0.0</Version> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <ProjectReference Include="..\PackageAv3\PackageAv3.wixproj" /> | ||
9 | <ProjectReference Include="..\PackageF\PackageF.wixproj" /> | ||
10 | <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" /> | ||
11 | </ItemGroup> | ||
12 | <ItemGroup> | ||
13 | <PackageReference Include="WixToolset.Bal.wixext" /> | ||
14 | <PackageReference Include="WixToolset.NetFx.wixext" /> | ||
15 | </ItemGroup> | ||
16 | </Project> \ No newline at end of file | ||
diff --git a/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv3/BundleAv3.wxs b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv3/BundleAv3.wxs new file mode 100644 index 00000000..b969b504 --- /dev/null +++ b/src/test/burn/TestData/UpgradeRelatedBundleTests/BundleAv3/BundleAv3.wxs | |||
@@ -0,0 +1,11 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
5 | <Fragment> | ||
6 | <PackageGroup Id="BundlePackages"> | ||
7 | <MsiPackage Id="PackageA" SourceFile="$(var.PackageAv3.TargetPath)" /> | ||
8 | <MsiPackage Id="PackageF" SourceFile="$(var.PackageF.TargetPath)" /> | ||
9 | </PackageGroup> | ||
10 | </Fragment> | ||
11 | </Wix> | ||
diff --git a/src/test/burn/TestData/UpgradeRelatedBundleTests/PackageAv3/PackageAv3.wixproj b/src/test/burn/TestData/UpgradeRelatedBundleTests/PackageAv3/PackageAv3.wixproj new file mode 100644 index 00000000..f3c121af --- /dev/null +++ b/src/test/burn/TestData/UpgradeRelatedBundleTests/PackageAv3/PackageAv3.wixproj | |||
@@ -0,0 +1,7 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <Import Project="..\PackageAv1\PackageA.props" /> | ||
4 | <PropertyGroup> | ||
5 | <Version>3.0.0.0</Version> | ||
6 | </PropertyGroup> | ||
7 | </Project> \ No newline at end of file | ||
diff --git a/src/test/burn/TestData/UpgradeRelatedBundleTests/PackageF/PackageF.wixproj b/src/test/burn/TestData/UpgradeRelatedBundleTests/PackageF/PackageF.wixproj new file mode 100644 index 00000000..63d32e28 --- /dev/null +++ b/src/test/burn/TestData/UpgradeRelatedBundleTests/PackageF/PackageF.wixproj | |||
@@ -0,0 +1,12 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{8F6C8C4B-573C-416B-B1B0-467273256BD9}</UpgradeCode> | ||
5 | </PropertyGroup> | ||
6 | <ItemGroup> | ||
7 | <Compile Include="..\..\Templates\PackageFail.wxs" Link="PackageFail.wxs" /> | ||
8 | </ItemGroup> | ||
9 | <ItemGroup> | ||
10 | <PackageReference Include="WixToolset.Util.wixext" /> | ||
11 | </ItemGroup> | ||
12 | </Project> \ No newline at end of file | ||
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs index 69a1fa68..ba02d8ee 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs | |||
@@ -539,7 +539,7 @@ namespace WixToolsetTest.BurnE2E | |||
539 | } | 539 | } |
540 | } | 540 | } |
541 | 541 | ||
542 | [Fact(Skip = "https://github.com/wixtoolset/issues/issues/3421")] | 542 | [Fact] |
543 | public void DoesntLoseDependenciesOnFailedMajorUpgradeBundleFromMajorUpdateMsiFifo() | 543 | public void DoesntLoseDependenciesOnFailedMajorUpgradeBundleFromMajorUpdateMsiFifo() |
544 | { | 544 | { |
545 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); | 545 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); |
@@ -611,7 +611,7 @@ namespace WixToolsetTest.BurnE2E | |||
611 | packageGv2.VerifyInstalled(false); | 611 | packageGv2.VerifyInstalled(false); |
612 | } | 612 | } |
613 | 613 | ||
614 | [Fact(Skip = "https://github.com/wixtoolset/issues/issues/3421")] | 614 | [Fact] |
615 | public void DoesntLoseDependenciesOnFailedMajorUpgradeBundleFromMajorUpdateMsiLifo() | 615 | public void DoesntLoseDependenciesOnFailedMajorUpgradeBundleFromMajorUpdateMsiLifo() |
616 | { | 616 | { |
617 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); | 617 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); |
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs index 9eb5081e..32a04e5c 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs | |||
@@ -13,6 +13,33 @@ namespace WixToolsetTest.BurnE2E | |||
13 | public UpgradeRelatedBundleTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } | 13 | public UpgradeRelatedBundleTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } |
14 | 14 | ||
15 | [Fact] | 15 | [Fact] |
16 | public void ReinstallsOlderBundleAfterFailure() | ||
17 | { | ||
18 | var packageAv2 = this.CreatePackageInstaller("PackageAv2"); | ||
19 | var packageAv3 = this.CreatePackageInstaller("PackageAv3"); | ||
20 | var bundleAv2 = this.CreateBundleInstaller("BundleAv2"); | ||
21 | var bundleAv3 = this.CreateBundleInstaller("BundleAv3"); | ||
22 | |||
23 | packageAv2.VerifyInstalled(false); | ||
24 | packageAv3.VerifyInstalled(false); | ||
25 | |||
26 | bundleAv2.Install(); | ||
27 | bundleAv2.VerifyRegisteredAndInPackageCache(); | ||
28 | |||
29 | packageAv2.VerifyInstalled(true); | ||
30 | packageAv3.VerifyInstalled(false); | ||
31 | |||
32 | // Verify https://github.com/wixtoolset/issues/issues/3421 | ||
33 | var bundleAv3InstallLogFilePath = bundleAv3.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE); | ||
34 | bundleAv3.VerifyUnregisteredAndRemovedFromPackageCache(); | ||
35 | |||
36 | Assert.True(LogVerifier.MessageInLogFileRegex(bundleAv3InstallLogFilePath, @"Applied execute package: PackageA, result: 0x0, restart: None")); | ||
37 | |||
38 | packageAv2.VerifyInstalled(true); | ||
39 | packageAv3.VerifyInstalled(false); | ||
40 | } | ||
41 | |||
42 | [Fact] | ||
16 | public void ReportsRelatedBundleMissingFromCache() | 43 | public void ReportsRelatedBundleMissingFromCache() |
17 | { | 44 | { |
18 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); | 45 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); |