diff options
20 files changed, 373 insertions, 41 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h index b507b167..0b81b35a 100644 --- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h +++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h | |||
@@ -223,6 +223,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE | |||
223 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, | 223 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, |
224 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, | 224 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, |
225 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE, | 225 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE, |
226 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE, | ||
226 | }; | 227 | }; |
227 | 228 | ||
228 | enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION | 229 | enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION |
@@ -354,6 +355,18 @@ struct BA_ONAPPLYCOMPLETE_RESULTS | |||
354 | BOOTSTRAPPER_APPLYCOMPLETE_ACTION action; | 355 | BOOTSTRAPPER_APPLYCOMPLETE_ACTION action; |
355 | }; | 356 | }; |
356 | 357 | ||
358 | struct BA_ONAPPLYDOWNGRADE_ARGS | ||
359 | { | ||
360 | DWORD cbSize; | ||
361 | HRESULT hrRecommended; | ||
362 | }; | ||
363 | |||
364 | struct BA_ONAPPLYDOWNGRADE_RESULTS | ||
365 | { | ||
366 | DWORD cbSize; | ||
367 | HRESULT hrStatus; | ||
368 | }; | ||
369 | |||
357 | struct BA_ONBEGINMSITRANSACTIONBEGIN_ARGS | 370 | struct BA_ONBEGINMSITRANSACTIONBEGIN_ARGS |
358 | { | 371 | { |
359 | DWORD cbSize; | 372 | DWORD cbSize; |
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs index fd36cf26..8a2e0e93 100644 --- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs | |||
@@ -209,6 +209,9 @@ namespace WixToolset.Mba.Core | |||
209 | public event EventHandler<ApplyCompleteEventArgs> ApplyComplete; | 209 | public event EventHandler<ApplyCompleteEventArgs> ApplyComplete; |
210 | 210 | ||
211 | /// <inheritdoc/> | 211 | /// <inheritdoc/> |
212 | public event EventHandler<ApplyDowngradeEventArgs> ApplyDowngrade; | ||
213 | |||
214 | /// <inheritdoc/> | ||
212 | public event EventHandler<ExecuteProgressEventArgs> ExecuteProgress; | 215 | public event EventHandler<ExecuteProgressEventArgs> ExecuteProgress; |
213 | 216 | ||
214 | /// <inheritdoc/> | 217 | /// <inheritdoc/> |
@@ -1056,6 +1059,19 @@ namespace WixToolset.Mba.Core | |||
1056 | } | 1059 | } |
1057 | 1060 | ||
1058 | /// <summary> | 1061 | /// <summary> |
1062 | /// Called by the engine, raises the <see cref="ApplyDowngrade"/> event. | ||
1063 | /// </summary> | ||
1064 | /// <param name="args">Additional arguments for this event.</param> | ||
1065 | protected virtual void OnApplyDowngrade(ApplyDowngradeEventArgs args) | ||
1066 | { | ||
1067 | EventHandler<ApplyDowngradeEventArgs> handler = this.ApplyDowngrade; | ||
1068 | if (null != handler) | ||
1069 | { | ||
1070 | handler(this, args); | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | /// <summary> | ||
1059 | /// Called by the engine, raises the <see cref="ExecuteProgress"/> event. | 1075 | /// Called by the engine, raises the <see cref="ExecuteProgress"/> event. |
1060 | /// </summary> | 1076 | /// </summary> |
1061 | /// <param name="args">Additional arguments for this event.</param> | 1077 | /// <param name="args">Additional arguments for this event.</param> |
@@ -1907,6 +1923,15 @@ namespace WixToolset.Mba.Core | |||
1907 | return args.HResult; | 1923 | return args.HResult; |
1908 | } | 1924 | } |
1909 | 1925 | ||
1926 | int IBootstrapperApplication.OnApplyDowngrade(int hrRecommendation, ref int hrStatus) | ||
1927 | { | ||
1928 | ApplyDowngradeEventArgs args = new ApplyDowngradeEventArgs(hrRecommendation, hrStatus); | ||
1929 | this.OnApplyDowngrade(args); | ||
1930 | |||
1931 | hrStatus = args.Status; | ||
1932 | return args.HResult; | ||
1933 | } | ||
1934 | |||
1910 | int IBootstrapperApplication.OnLaunchApprovedExeBegin(ref bool fCancel) | 1935 | int IBootstrapperApplication.OnLaunchApprovedExeBegin(ref bool fCancel) |
1911 | { | 1936 | { |
1912 | LaunchApprovedExeBeginEventArgs args = new LaunchApprovedExeBeginEventArgs(fCancel); | 1937 | LaunchApprovedExeBeginEventArgs args = new LaunchApprovedExeBeginEventArgs(fCancel); |
diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs index d8ec7998..c93c2885 100644 --- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs +++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs | |||
@@ -1859,6 +1859,30 @@ namespace WixToolset.Mba.Core | |||
1859 | } | 1859 | } |
1860 | 1860 | ||
1861 | /// <summary> | 1861 | /// <summary> |
1862 | /// Event arguments for <see cref="IDefaultBootstrapperApplication.ApplyDowngrade"/> | ||
1863 | /// </summary> | ||
1864 | [Serializable] | ||
1865 | public class ApplyDowngradeEventArgs : HResultEventArgs | ||
1866 | { | ||
1867 | /// <summary /> | ||
1868 | public ApplyDowngradeEventArgs(int hrRecommendation, int hrStatus) | ||
1869 | { | ||
1870 | this.Recommendation = hrRecommendation; | ||
1871 | this.Status = hrStatus; | ||
1872 | } | ||
1873 | |||
1874 | /// <summary> | ||
1875 | /// Gets the recommended HRESULT. | ||
1876 | /// </summary> | ||
1877 | public int Recommendation { get; private set; } | ||
1878 | |||
1879 | /// <summary> | ||
1880 | /// Gets or sets the HRESULT for Apply. | ||
1881 | /// </summary> | ||
1882 | public int Status { get; set; } | ||
1883 | } | ||
1884 | |||
1885 | /// <summary> | ||
1862 | /// EventArgs for <see cref="IDefaultBootstrapperApplication.CacheAcquireResolving"/>. | 1886 | /// EventArgs for <see cref="IDefaultBootstrapperApplication.CacheAcquireResolving"/>. |
1863 | /// </summary> | 1887 | /// </summary> |
1864 | [Serializable] | 1888 | [Serializable] |
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs index 4ab0f8d9..d4fe8320 100644 --- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs | |||
@@ -1160,6 +1160,16 @@ namespace WixToolset.Mba.Core | |||
1160 | [MarshalAs(UnmanagedType.U4)] ref RelatedBundlePlanType pRequestedType, | 1160 | [MarshalAs(UnmanagedType.U4)] ref RelatedBundlePlanType pRequestedType, |
1161 | [MarshalAs(UnmanagedType.Bool)] ref bool fCancel | 1161 | [MarshalAs(UnmanagedType.Bool)] ref bool fCancel |
1162 | ); | 1162 | ); |
1163 | |||
1164 | /// <summary> | ||
1165 | /// See <see cref="IDefaultBootstrapperApplication.ApplyDowngrade"/>. | ||
1166 | /// </summary> | ||
1167 | [PreserveSig] | ||
1168 | [return: MarshalAs(UnmanagedType.I4)] | ||
1169 | int OnApplyDowngrade( | ||
1170 | [MarshalAs(UnmanagedType.I4)] int hrRecommended, | ||
1171 | [MarshalAs(UnmanagedType.I4)] ref int hrStatus | ||
1172 | ); | ||
1163 | } | 1173 | } |
1164 | 1174 | ||
1165 | /// <summary> | 1175 | /// <summary> |
diff --git a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs index ebd1580b..c9284b69 100644 --- a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs | |||
@@ -20,6 +20,11 @@ namespace WixToolset.Mba.Core | |||
20 | event EventHandler<ApplyCompleteEventArgs> ApplyComplete; | 20 | event EventHandler<ApplyCompleteEventArgs> ApplyComplete; |
21 | 21 | ||
22 | /// <summary> | 22 | /// <summary> |
23 | /// Fired when the plan determined that nothing should happen to prevent downgrading. | ||
24 | /// </summary> | ||
25 | event EventHandler<ApplyDowngradeEventArgs> ApplyDowngrade; | ||
26 | |||
27 | /// <summary> | ||
23 | /// Fired when the engine is about to begin an MSI transaction. | 28 | /// Fired when the engine is about to begin an MSI transaction. |
24 | /// </summary> | 29 | /// </summary> |
25 | event EventHandler<BeginMsiTransactionBeginEventArgs> BeginMsiTransactionBegin; | 30 | event EventHandler<BeginMsiTransactionBeginEventArgs> BeginMsiTransactionBegin; |
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h index f772eb3f..58c26166 100644 --- a/src/api/burn/balutil/inc/BAFunctions.h +++ b/src/api/burn/balutil/inc/BAFunctions.h | |||
@@ -90,6 +90,7 @@ enum BA_FUNCTIONS_MESSAGE | |||
90 | BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, | 90 | BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE, |
91 | BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, | 91 | BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRESTORERELATEDBUNDLE, |
92 | BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE, | 92 | BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE, |
93 | BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE, | ||
93 | 94 | ||
94 | BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, | 95 | BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, |
95 | BA_FUNCTIONS_MESSAGE_WNDPROC, | 96 | BA_FUNCTIONS_MESSAGE_WNDPROC, |
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h index f558828f..fe5c99ba 100644 --- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h +++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h | |||
@@ -869,6 +869,14 @@ public: // IBootstrapperApplication | |||
869 | return S_OK; | 869 | return S_OK; |
870 | } | 870 | } |
871 | 871 | ||
872 | virtual STDMETHODIMP OnApplyDowngrade( | ||
873 | __in HRESULT /*hrRecommended*/, | ||
874 | __in HRESULT* /*phrStatus*/ | ||
875 | ) | ||
876 | { | ||
877 | return S_OK; | ||
878 | } | ||
879 | |||
872 | public: // IBAFunctions | 880 | public: // IBAFunctions |
873 | virtual STDMETHODIMP OnPlan( | 881 | virtual STDMETHODIMP OnPlan( |
874 | ) | 882 | ) |
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h index ede00f28..100e5c30 100644 --- a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h +++ b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h | |||
@@ -161,6 +161,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc( | |||
161 | case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: | 161 | case BA_FUNCTIONS_MESSAGE_ONPLANNEDCOMPATIBLEPACKAGE: |
162 | case BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE: | 162 | case BA_FUNCTIONS_MESSAGE_ONPLANRESTORERELATEDBUNDLE: |
163 | case BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE: | 163 | case BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLETYPE: |
164 | case BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE: | ||
164 | hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); | 165 | hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); |
165 | break; | 166 | break; |
166 | case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: | 167 | case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: |
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h index 49f4b7ca..fd06a83f 100644 --- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h +++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h | |||
@@ -1069,6 +1069,14 @@ public: // IBootstrapperApplication | |||
1069 | return S_OK; | 1069 | return S_OK; |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | virtual STDMETHODIMP OnApplyDowngrade( | ||
1073 | __in HRESULT /*hrRecommended*/, | ||
1074 | __in HRESULT* /*phrStatus*/ | ||
1075 | ) | ||
1076 | { | ||
1077 | return S_OK; | ||
1078 | } | ||
1079 | |||
1072 | public: //CBalBaseBootstrapperApplication | 1080 | public: //CBalBaseBootstrapperApplication |
1073 | virtual STDMETHODIMP Initialize( | 1081 | virtual STDMETHODIMP Initialize( |
1074 | __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs | 1082 | __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 698349f7..4e413e4e 100644 --- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h +++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h | |||
@@ -738,6 +738,15 @@ static HRESULT BalBaseBAProcOnPlanRelatedBundleType( | |||
738 | return pBA->OnPlanRelatedBundleType(pArgs->wzBundleId, pArgs->recommendedType, &pResults->requestedType, &pResults->fCancel); | 738 | return pBA->OnPlanRelatedBundleType(pArgs->wzBundleId, pArgs->recommendedType, &pResults->requestedType, &pResults->fCancel); |
739 | } | 739 | } |
740 | 740 | ||
741 | static HRESULT BalBaseBAProcOnApplyDowngrade( | ||
742 | __in IBootstrapperApplication* pBA, | ||
743 | __in BA_ONAPPLYDOWNGRADE_ARGS* pArgs, | ||
744 | __inout BA_ONAPPLYDOWNGRADE_RESULTS* pResults | ||
745 | ) | ||
746 | { | ||
747 | return pBA->OnApplyDowngrade(pArgs->hrRecommended, &pResults->hrStatus); | ||
748 | } | ||
749 | |||
741 | /******************************************************************* | 750 | /******************************************************************* |
742 | BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. | 751 | BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. |
743 | Provides a default mapping between the new message based BA interface and | 752 | Provides a default mapping between the new message based BA interface and |
@@ -1000,6 +1009,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc( | |||
1000 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE: | 1009 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE: |
1001 | hr = BalBaseBAProcOnPlanRelatedBundleType(pBA, reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults)); | 1010 | hr = BalBaseBAProcOnPlanRelatedBundleType(pBA, reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults)); |
1002 | break; | 1011 | break; |
1012 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE: | ||
1013 | hr = BalBaseBAProcOnApplyDowngrade(pBA, reinterpret_cast<BA_ONAPPLYDOWNGRADE_ARGS*>(pvArgs), reinterpret_cast<BA_ONAPPLYDOWNGRADE_RESULTS*>(pvResults)); | ||
1014 | break; | ||
1003 | } | 1015 | } |
1004 | } | 1016 | } |
1005 | 1017 | ||
diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h index 462df0cc..c9cf3126 100644 --- a/src/api/burn/balutil/inc/IBootstrapperApplication.h +++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h | |||
@@ -707,4 +707,11 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A | |||
707 | __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType, | 707 | __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType, |
708 | __inout BOOL* pfCancel | 708 | __inout BOOL* pfCancel |
709 | ) = 0; | 709 | ) = 0; |
710 | |||
711 | // OnApplyDowngrade - called when the plan determined that nothing should happen to prevent downgrading. | ||
712 | // | ||
713 | STDMETHOD(OnApplyDowngrade)( | ||
714 | __in HRESULT hrRecommended, | ||
715 | __inout HRESULT* phrStatus | ||
716 | ) = 0; | ||
710 | }; | 717 | }; |
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 9d4ea43e..37872e52 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp | |||
@@ -527,8 +527,15 @@ extern "C" HRESULT CorePlan( | |||
527 | hr = PlanRelatedBundlesInitialize(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); | 527 | hr = PlanRelatedBundlesInitialize(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); |
528 | ExitOnFailure(hr, "Failed to initialize related bundles for plan."); | 528 | ExitOnFailure(hr, "Failed to initialize related bundles for plan."); |
529 | 529 | ||
530 | hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, &pEngineState->dependencies, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning); | 530 | if (pEngineState->plan.fDowngrade) |
531 | ExitOnFailure(hr, "Failed to plan registration."); | 531 | { |
532 | fContinuePlanning = FALSE; | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, &pEngineState->dependencies, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning); | ||
537 | ExitOnFailure(hr, "Failed to plan registration."); | ||
538 | } | ||
532 | 539 | ||
533 | if (fContinuePlanning) | 540 | if (fContinuePlanning) |
534 | { | 541 | { |
@@ -615,6 +622,7 @@ extern "C" HRESULT CoreApply( | |||
615 | { | 622 | { |
616 | HRESULT hr = S_OK; | 623 | HRESULT hr = S_OK; |
617 | HANDLE hLock = NULL; | 624 | HANDLE hLock = NULL; |
625 | BOOL fApplyBegan = FALSE; | ||
618 | BOOL fApplyInitialize = FALSE; | 626 | BOOL fApplyInitialize = FALSE; |
619 | BOOL fElevated = FALSE; | 627 | BOOL fElevated = FALSE; |
620 | BOOL fRegistered = FALSE; | 628 | BOOL fRegistered = FALSE; |
@@ -627,8 +635,6 @@ extern "C" HRESULT CoreApply( | |||
627 | DWORD dwPhaseCount = 0; | 635 | DWORD dwPhaseCount = 0; |
628 | BOOTSTRAPPER_APPLYCOMPLETE_ACTION applyCompleteAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE; | 636 | BOOTSTRAPPER_APPLYCOMPLETE_ACTION applyCompleteAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE; |
629 | 637 | ||
630 | LogId(REPORT_STANDARD, MSG_APPLY_BEGIN); | ||
631 | |||
632 | if (!pEngineState->fPlanned) | 638 | if (!pEngineState->fPlanned) |
633 | { | 639 | { |
634 | ExitOnFailure(hr = E_INVALIDSTATE, "Apply cannot be done without a successful Plan."); | 640 | ExitOnFailure(hr = E_INVALIDSTATE, "Apply cannot be done without a successful Plan."); |
@@ -638,6 +644,10 @@ extern "C" HRESULT CoreApply( | |||
638 | ExitOnFailure(hr = E_INVALIDSTATE, "Plans cannot be applied multiple times."); | 644 | ExitOnFailure(hr = E_INVALIDSTATE, "Plans cannot be applied multiple times."); |
639 | } | 645 | } |
640 | 646 | ||
647 | fApplyBegan = TRUE; | ||
648 | |||
649 | LogId(REPORT_STANDARD, MSG_APPLY_BEGIN); | ||
650 | |||
641 | // Ensure any previous attempts to execute are reset. | 651 | // Ensure any previous attempts to execute are reset. |
642 | ApplyReset(&pEngineState->userExperience, &pEngineState->packages); | 652 | ApplyReset(&pEngineState->userExperience, &pEngineState->packages); |
643 | 653 | ||
@@ -653,6 +663,14 @@ extern "C" HRESULT CoreApply( | |||
653 | hr = UserExperienceOnApplyBegin(&pEngineState->userExperience, dwPhaseCount); | 663 | hr = UserExperienceOnApplyBegin(&pEngineState->userExperience, dwPhaseCount); |
654 | ExitOnRootFailure(hr, "BA aborted apply begin."); | 664 | ExitOnRootFailure(hr, "BA aborted apply begin."); |
655 | 665 | ||
666 | if (pEngineState->plan.fDowngrade) | ||
667 | { | ||
668 | hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION); | ||
669 | UserExperienceOnApplyDowngrade(&pEngineState->userExperience, &hr); | ||
670 | |||
671 | ExitFunction(); | ||
672 | } | ||
673 | |||
656 | pEngineState->plan.fAffectedMachineState = pEngineState->plan.fCanAffectMachineState; | 674 | pEngineState->plan.fAffectedMachineState = pEngineState->plan.fCanAffectMachineState; |
657 | 675 | ||
658 | hr = ApplyLock(FALSE, &hLock); | 676 | hr = ApplyLock(FALSE, &hLock); |
@@ -804,13 +822,16 @@ LExit: | |||
804 | DeleteCriticalSection(&applyContext.csApply); | 822 | DeleteCriticalSection(&applyContext.csApply); |
805 | } | 823 | } |
806 | 824 | ||
807 | UserExperienceOnApplyComplete(&pEngineState->userExperience, hr, restart, &applyCompleteAction); | 825 | if (fApplyBegan) |
808 | if (BOOTSTRAPPER_APPLYCOMPLETE_ACTION_RESTART == applyCompleteAction) | ||
809 | { | 826 | { |
810 | pEngineState->fRestart = TRUE; | 827 | UserExperienceOnApplyComplete(&pEngineState->userExperience, hr, restart, &applyCompleteAction); |
811 | } | 828 | if (BOOTSTRAPPER_APPLYCOMPLETE_ACTION_RESTART == applyCompleteAction) |
829 | { | ||
830 | pEngineState->fRestart = TRUE; | ||
831 | } | ||
812 | 832 | ||
813 | LogId(REPORT_STANDARD, MSG_APPLY_COMPLETE, hr, LoggingRestartToString(restart), LoggingBoolToString(pEngineState->fRestart)); | 833 | LogId(REPORT_STANDARD, MSG_APPLY_COMPLETE, hr, LoggingRestartToString(restart), LoggingBoolToString(pEngineState->fRestart)); |
834 | } | ||
814 | 835 | ||
815 | return hr; | 836 | return hr; |
816 | } | 837 | } |
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index a5c4e2ba..53e6b256 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc | |||
@@ -499,6 +499,20 @@ Language=English | |||
499 | Ignoring bundle dependents due to action UnsafeUninstall... | 499 | Ignoring bundle dependents due to action UnsafeUninstall... |
500 | . | 500 | . |
501 | 501 | ||
502 | MessageId=224 | ||
503 | Severity=Warning | ||
504 | SymbolicName=MSG_PLAN_SKIPPED_DUE_TO_DOWNGRADE | ||
505 | Language=English | ||
506 | Plan skipped due to related bundle of plan type Downgrade: | ||
507 | . | ||
508 | |||
509 | MessageId=225 | ||
510 | Severity=Warning | ||
511 | SymbolicName=MSG_UPGRADE_BUNDLE_DOWNGRADE | ||
512 | Language=English | ||
513 | id: %1!ls!, version: %2!ls! | ||
514 | . | ||
515 | |||
502 | MessageId=299 | 516 | MessageId=299 |
503 | Severity=Success | 517 | Severity=Success |
504 | SymbolicName=MSG_PLAN_COMPLETE | 518 | SymbolicName=MSG_PLAN_COMPLETE |
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp index dcb919c7..46680636 100644 --- a/src/burn/engine/plan.cpp +++ b/src/burn/engine/plan.cpp | |||
@@ -1328,11 +1328,12 @@ LExit: | |||
1328 | extern "C" HRESULT PlanRelatedBundlesInitialize( | 1328 | extern "C" HRESULT PlanRelatedBundlesInitialize( |
1329 | __in BURN_USER_EXPERIENCE* pUserExperience, | 1329 | __in BURN_USER_EXPERIENCE* pUserExperience, |
1330 | __in BURN_REGISTRATION* pRegistration, | 1330 | __in BURN_REGISTRATION* pRegistration, |
1331 | __in BOOTSTRAPPER_RELATION_TYPE /*relationType*/, | 1331 | __in BOOTSTRAPPER_RELATION_TYPE relationType, |
1332 | __in BURN_PLAN* /*pPlan*/ | 1332 | __in BURN_PLAN* pPlan |
1333 | ) | 1333 | ) |
1334 | { | 1334 | { |
1335 | HRESULT hr = S_OK; | 1335 | HRESULT hr = S_OK; |
1336 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action; | ||
1336 | 1337 | ||
1337 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) | 1338 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) |
1338 | { | 1339 | { |
@@ -1356,6 +1357,19 @@ extern "C" HRESULT PlanRelatedBundlesInitialize( | |||
1356 | 1357 | ||
1357 | hr = UserExperienceOnPlanRelatedBundleType(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->planRelationType); | 1358 | hr = UserExperienceOnPlanRelatedBundleType(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->planRelationType); |
1358 | ExitOnRootFailure(hr, "BA aborted plan related bundle type."); | 1359 | ExitOnRootFailure(hr, "BA aborted plan related bundle type."); |
1360 | |||
1361 | if (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DOWNGRADE == pRelatedBundle->planRelationType && | ||
1362 | pRelatedBundle->fPlannable && !fUninstalling && BOOTSTRAPPER_RELATION_UPGRADE != relationType) | ||
1363 | { | ||
1364 | if (!pPlan->fDowngrade) | ||
1365 | { | ||
1366 | pPlan->fDowngrade = TRUE; | ||
1367 | |||
1368 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DOWNGRADE); | ||
1369 | } | ||
1370 | |||
1371 | LogId(REPORT_VERBOSE, MSG_UPGRADE_BUNDLE_DOWNGRADE, pRelatedBundle->package.sczId, pRelatedBundle->pVersion->sczVersion); | ||
1372 | } | ||
1359 | } | 1373 | } |
1360 | 1374 | ||
1361 | RelatedBundlesSortPlan(&pRegistration->relatedBundles); | 1375 | RelatedBundlesSortPlan(&pRegistration->relatedBundles); |
@@ -3011,6 +3025,7 @@ extern "C" void PlanDump( | |||
3011 | LogStringLine(PlanDumpLevel, " can affect machine state: %hs", LoggingTrueFalseToString(pPlan->fCanAffectMachineState)); | 3025 | LogStringLine(PlanDumpLevel, " can affect machine state: %hs", LoggingTrueFalseToString(pPlan->fCanAffectMachineState)); |
3012 | LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback)); | 3026 | LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback)); |
3013 | LogStringLine(PlanDumpLevel, " disallow-removal: %hs", LoggingTrueFalseToString(pPlan->fDisallowRemoval)); | 3027 | LogStringLine(PlanDumpLevel, " disallow-removal: %hs", LoggingTrueFalseToString(pPlan->fDisallowRemoval)); |
3028 | LogStringLine(PlanDumpLevel, " downgrade: %hs", LoggingTrueFalseToString(pPlan->fDowngrade)); | ||
3014 | LogStringLine(PlanDumpLevel, " registration options: %hs", LoggingRegistrationOptionsToString(pPlan->dwRegistrationOperations)); | 3029 | LogStringLine(PlanDumpLevel, " registration options: %hs", LoggingRegistrationOptionsToString(pPlan->dwRegistrationOperations)); |
3015 | LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize); | 3030 | LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize); |
3016 | if (pPlan->sczLayoutDirectory) | 3031 | if (pPlan->sczLayoutDirectory) |
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h index 1f3fe07c..e73cbcfa 100644 --- a/src/burn/engine/plan.h +++ b/src/burn/engine/plan.h | |||
@@ -250,6 +250,7 @@ typedef struct _BURN_PLAN | |||
250 | BOOL fAffectedMachineState; | 250 | BOOL fAffectedMachineState; |
251 | LPWSTR sczLayoutDirectory; | 251 | LPWSTR sczLayoutDirectory; |
252 | BOOL fPlanPackageCacheRollback; | 252 | BOOL fPlanPackageCacheRollback; |
253 | BOOL fDowngrade; | ||
253 | 254 | ||
254 | DWORD64 qwCacheSizeTotal; | 255 | DWORD64 qwCacheSizeTotal; |
255 | 256 | ||
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 8668cf6f..81ce8bb9 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp | |||
@@ -335,6 +335,30 @@ LExit: | |||
335 | return hr; | 335 | return hr; |
336 | } | 336 | } |
337 | 337 | ||
338 | EXTERN_C BAAPI UserExperienceOnApplyDowngrade( | ||
339 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
340 | __inout HRESULT* phrStatus | ||
341 | ) | ||
342 | { | ||
343 | HRESULT hr = S_OK; | ||
344 | BA_ONAPPLYDOWNGRADE_ARGS args = { }; | ||
345 | BA_ONAPPLYDOWNGRADE_RESULTS results = { }; | ||
346 | |||
347 | args.cbSize = sizeof(args); | ||
348 | args.hrRecommended = *phrStatus; | ||
349 | |||
350 | results.cbSize = sizeof(results); | ||
351 | results.hrStatus = *phrStatus; | ||
352 | |||
353 | hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE, &args, &results); | ||
354 | ExitOnFailure(hr, "BA OnApplyDowngrade failed."); | ||
355 | |||
356 | *phrStatus = results.hrStatus; | ||
357 | |||
358 | LExit: | ||
359 | return hr; | ||
360 | } | ||
361 | |||
338 | EXTERN_C BAAPI UserExperienceOnBeginMsiTransactionBegin( | 362 | EXTERN_C BAAPI UserExperienceOnBeginMsiTransactionBegin( |
339 | __in BURN_USER_EXPERIENCE* pUserExperience, | 363 | __in BURN_USER_EXPERIENCE* pUserExperience, |
340 | __in LPCWSTR wzTransactionId | 364 | __in LPCWSTR wzTransactionId |
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index 11344365..2f18acdd 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h | |||
@@ -110,6 +110,10 @@ BAAPI UserExperienceOnApplyComplete( | |||
110 | __in BOOTSTRAPPER_APPLY_RESTART restart, | 110 | __in BOOTSTRAPPER_APPLY_RESTART restart, |
111 | __inout BOOTSTRAPPER_APPLYCOMPLETE_ACTION* pAction | 111 | __inout BOOTSTRAPPER_APPLYCOMPLETE_ACTION* pAction |
112 | ); | 112 | ); |
113 | BAAPI UserExperienceOnApplyDowngrade( | ||
114 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
115 | __inout HRESULT* phrStatus | ||
116 | ); | ||
113 | BAAPI UserExperienceOnBeginMsiTransactionBegin( | 117 | BAAPI UserExperienceOnBeginMsiTransactionBegin( |
114 | __in BURN_USER_EXPERIENCE* pUserExperience, | 118 | __in BURN_USER_EXPERIENCE* pUserExperience, |
115 | __in LPCWSTR wzTransactionId | 119 | __in LPCWSTR wzTransactionId |
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp index a3b58426..0a8ac369 100644 --- a/src/burn/test/BurnUnitTest/PlanTest.cpp +++ b/src/burn/test/BurnUnitTest/PlanTest.cpp | |||
@@ -67,6 +67,7 @@ namespace Bootstrapper | |||
67 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 67 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
68 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 68 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
69 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 69 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
70 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
70 | 71 | ||
71 | BOOL fRollback = FALSE; | 72 | BOOL fRollback = FALSE; |
72 | DWORD dwIndex = 0; | 73 | DWORD dwIndex = 0; |
@@ -226,6 +227,7 @@ namespace Bootstrapper | |||
226 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 227 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
227 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 228 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
228 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 229 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
230 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
229 | 231 | ||
230 | BOOL fRollback = FALSE; | 232 | BOOL fRollback = FALSE; |
231 | DWORD dwIndex = 0; | 233 | DWORD dwIndex = 0; |
@@ -358,6 +360,7 @@ namespace Bootstrapper | |||
358 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 360 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
359 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 361 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
360 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 362 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
363 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
361 | 364 | ||
362 | BOOL fRollback = FALSE; | 365 | BOOL fRollback = FALSE; |
363 | DWORD dwIndex = 0; | 366 | DWORD dwIndex = 0; |
@@ -457,6 +460,7 @@ namespace Bootstrapper | |||
457 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 460 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
458 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 461 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
459 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 462 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
463 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
460 | 464 | ||
461 | BOOL fRollback = FALSE; | 465 | BOOL fRollback = FALSE; |
462 | DWORD dwIndex = 0; | 466 | DWORD dwIndex = 0; |
@@ -575,6 +579,7 @@ namespace Bootstrapper | |||
575 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 579 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
576 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 580 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
577 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 581 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
582 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
578 | 583 | ||
579 | BOOL fRollback = FALSE; | 584 | BOOL fRollback = FALSE; |
580 | DWORD dwIndex = 0; | 585 | DWORD dwIndex = 0; |
@@ -677,6 +682,7 @@ namespace Bootstrapper | |||
677 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 682 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
678 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 683 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
679 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 684 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
685 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
680 | 686 | ||
681 | BOOL fRollback = FALSE; | 687 | BOOL fRollback = FALSE; |
682 | DWORD dwIndex = 0; | 688 | DWORD dwIndex = 0; |
@@ -742,6 +748,76 @@ namespace Bootstrapper | |||
742 | } | 748 | } |
743 | 749 | ||
744 | [Fact] | 750 | [Fact] |
751 | void SingleMsiDowngradeTest() | ||
752 | { | ||
753 | HRESULT hr = S_OK; | ||
754 | BURN_ENGINE_STATE engineState = { }; | ||
755 | BURN_ENGINE_STATE* pEngineState = &engineState; | ||
756 | BURN_PLAN* pPlan = &engineState.plan; | ||
757 | |||
758 | InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); | ||
759 | DetectAttachedContainerAsAttached(pEngineState); | ||
760 | DetectPackagesAsAbsent(pEngineState); | ||
761 | DetectRelatedBundle(pEngineState, L"{AF8355C9-CCDD-4D61-BF5F-EA5F948D8F01}", L"1.1.0.0", BOOTSTRAPPER_RELATION_UPGRADE); | ||
762 | |||
763 | hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL); | ||
764 | NativeAssert::Succeeded(hr, "CorePlan failed"); | ||
765 | |||
766 | Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action); | ||
767 | NativeAssert::StringEqual(L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", pPlan->wzBundleId); | ||
768 | NativeAssert::StringEqual(L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", pPlan->wzBundleProviderKey); | ||
769 | Assert::Equal<BOOL>(FALSE, pPlan->fEnabledForwardCompatibleBundle); | ||
770 | Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine); | ||
771 | Assert::Equal<BOOL>(FALSE, pPlan->fCanAffectMachineState); | ||
772 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | ||
773 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | ||
774 | Assert::Equal<BOOL>(TRUE, pPlan->fDowngrade); | ||
775 | |||
776 | BOOL fRollback = FALSE; | ||
777 | DWORD dwIndex = 0; | ||
778 | Assert::Equal(dwIndex, pPlan->cRegistrationActions); | ||
779 | |||
780 | fRollback = TRUE; | ||
781 | dwIndex = 0; | ||
782 | Assert::Equal(dwIndex, pPlan->cRollbackRegistrationActions); | ||
783 | |||
784 | fRollback = FALSE; | ||
785 | dwIndex = 0; | ||
786 | Assert::Equal(dwIndex, pPlan->cCacheActions); | ||
787 | |||
788 | fRollback = TRUE; | ||
789 | dwIndex = 0; | ||
790 | Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); | ||
791 | |||
792 | Assert::Equal(0ull, pPlan->qwEstimatedSize); | ||
793 | Assert::Equal(0ull, pPlan->qwCacheSizeTotal); | ||
794 | |||
795 | fRollback = FALSE; | ||
796 | dwIndex = 0; | ||
797 | Assert::Equal(dwIndex, pPlan->cExecuteActions); | ||
798 | |||
799 | fRollback = TRUE; | ||
800 | dwIndex = 0; | ||
801 | Assert::Equal(dwIndex, pPlan->cRollbackActions); | ||
802 | |||
803 | Assert::Equal(0ul, pPlan->cExecutePackagesTotal); | ||
804 | Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); | ||
805 | |||
806 | dwIndex = 0; | ||
807 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
808 | |||
809 | dwIndex = 0; | ||
810 | Assert::Equal(dwIndex, pPlan->cCleanActions); | ||
811 | |||
812 | UINT uIndex = 0; | ||
813 | ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL); | ||
814 | Assert::Equal(uIndex, pPlan->cPlannedProviders); | ||
815 | |||
816 | Assert::Equal(1ul, pEngineState->packages.cPackages); | ||
817 | ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN); | ||
818 | } | ||
819 | |||
820 | [Fact] | ||
745 | void SingleMsiForceAbsentTest() | 821 | void SingleMsiForceAbsentTest() |
746 | { | 822 | { |
747 | HRESULT hr = S_OK; | 823 | HRESULT hr = S_OK; |
@@ -770,6 +846,7 @@ namespace Bootstrapper | |||
770 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 846 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
771 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 847 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
772 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 848 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
849 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
773 | 850 | ||
774 | BOOL fRollback = FALSE; | 851 | BOOL fRollback = FALSE; |
775 | DWORD dwIndex = 0; | 852 | DWORD dwIndex = 0; |
@@ -858,6 +935,7 @@ namespace Bootstrapper | |||
858 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 935 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
859 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 936 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
860 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 937 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
938 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
861 | 939 | ||
862 | BOOL fRollback = FALSE; | 940 | BOOL fRollback = FALSE; |
863 | DWORD dwIndex = 0; | 941 | DWORD dwIndex = 0; |
@@ -948,6 +1026,7 @@ namespace Bootstrapper | |||
948 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1026 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
949 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1027 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
950 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1028 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1029 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
951 | 1030 | ||
952 | BOOL fRollback = FALSE; | 1031 | BOOL fRollback = FALSE; |
953 | DWORD dwIndex = 0; | 1032 | DWORD dwIndex = 0; |
@@ -1053,6 +1132,7 @@ namespace Bootstrapper | |||
1053 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1132 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1054 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1133 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1055 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1134 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1135 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1056 | 1136 | ||
1057 | BOOL fRollback = FALSE; | 1137 | BOOL fRollback = FALSE; |
1058 | DWORD dwIndex = 0; | 1138 | DWORD dwIndex = 0; |
@@ -1131,6 +1211,7 @@ namespace Bootstrapper | |||
1131 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1211 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1132 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1212 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1133 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1213 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1214 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1134 | 1215 | ||
1135 | BOOL fRollback = FALSE; | 1216 | BOOL fRollback = FALSE; |
1136 | DWORD dwIndex = 0; | 1217 | DWORD dwIndex = 0; |
@@ -1225,6 +1306,7 @@ namespace Bootstrapper | |||
1225 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1306 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1226 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1307 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1227 | Assert::Equal<BOOL>(TRUE, pPlan->fDisallowRemoval); | 1308 | Assert::Equal<BOOL>(TRUE, pPlan->fDisallowRemoval); |
1309 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1228 | 1310 | ||
1229 | BOOL fRollback = FALSE; | 1311 | BOOL fRollback = FALSE; |
1230 | DWORD dwIndex = 0; | 1312 | DWORD dwIndex = 0; |
@@ -1294,6 +1376,7 @@ namespace Bootstrapper | |||
1294 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1376 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1295 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1377 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1296 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1378 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1379 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1297 | 1380 | ||
1298 | BOOL fRollback = FALSE; | 1381 | BOOL fRollback = FALSE; |
1299 | DWORD dwIndex = 0; | 1382 | DWORD dwIndex = 0; |
@@ -1377,6 +1460,7 @@ namespace Bootstrapper | |||
1377 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1460 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1378 | Assert::Equal<BOOL>(TRUE, pPlan->fDisableRollback); | 1461 | Assert::Equal<BOOL>(TRUE, pPlan->fDisableRollback); |
1379 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1462 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1463 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1380 | 1464 | ||
1381 | BOOL fRollback = FALSE; | 1465 | BOOL fRollback = FALSE; |
1382 | DWORD dwIndex = 0; | 1466 | DWORD dwIndex = 0; |
@@ -1471,6 +1555,7 @@ namespace Bootstrapper | |||
1471 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1555 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1472 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1556 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1473 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1557 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1558 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1474 | 1559 | ||
1475 | BOOL fRollback = FALSE; | 1560 | BOOL fRollback = FALSE; |
1476 | DWORD dwIndex = 0; | 1561 | DWORD dwIndex = 0; |
@@ -1601,6 +1686,7 @@ namespace Bootstrapper | |||
1601 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1686 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1602 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1687 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1603 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1688 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1689 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1604 | 1690 | ||
1605 | BOOL fRollback = FALSE; | 1691 | BOOL fRollback = FALSE; |
1606 | DWORD dwIndex = 0; | 1692 | DWORD dwIndex = 0; |
@@ -1716,6 +1802,7 @@ namespace Bootstrapper | |||
1716 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1802 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1717 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1803 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1718 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1804 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1805 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1719 | 1806 | ||
1720 | BOOL fRollback = FALSE; | 1807 | BOOL fRollback = FALSE; |
1721 | DWORD dwIndex = 0; | 1808 | DWORD dwIndex = 0; |
@@ -1810,6 +1897,7 @@ namespace Bootstrapper | |||
1810 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); | 1897 | Assert::Equal<BOOL>(TRUE, pPlan->fCanAffectMachineState); |
1811 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); | 1898 | Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); |
1812 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); | 1899 | Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); |
1900 | Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); | ||
1813 | 1901 | ||
1814 | BOOL fRollback = FALSE; | 1902 | BOOL fRollback = FALSE; |
1815 | DWORD dwIndex = 0; | 1903 | DWORD dwIndex = 0; |
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp index 91033a26..2a5d839a 100644 --- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp | |||
@@ -254,7 +254,6 @@ public: // IBootstrapperApplication | |||
254 | ) | 254 | ) |
255 | { | 255 | { |
256 | BAL_INFO_PACKAGE* pPackage = NULL; | 256 | BAL_INFO_PACKAGE* pPackage = NULL; |
257 | int nCompare = 0; | ||
258 | 257 | ||
259 | if (!fMissingFromCache) | 258 | if (!fMissingFromCache) |
260 | { | 259 | { |
@@ -262,14 +261,6 @@ public: // IBootstrapperApplication | |||
262 | { | 261 | { |
263 | InitializePackageInfoForPackage(pPackage); | 262 | InitializePackageInfoForPackage(pPackage); |
264 | } | 263 | } |
265 | |||
266 | // If we're not doing a prerequisite install, remember when our bundle would cause a downgrade. | ||
267 | if (!m_fPrereq && BOOTSTRAPPER_RELATION_UPGRADE == relationType && | ||
268 | SUCCEEDED(m_pEngine->CompareVersions(m_sczBundleVersion, wzVersion, &nCompare)) && 0 > nCompare) | ||
269 | { | ||
270 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version (v%ls) of this product is installed.", wzVersion); | ||
271 | m_fDowngrading = TRUE; | ||
272 | } | ||
273 | } | 264 | } |
274 | 265 | ||
275 | return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel); | 266 | return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel); |
@@ -345,23 +336,6 @@ public: // IBootstrapperApplication | |||
345 | } | 336 | } |
346 | } | 337 | } |
347 | } | 338 | } |
348 | else if (m_fDowngrading && BOOTSTRAPPER_ACTION_UNINSTALL < m_command.action) | ||
349 | { | ||
350 | if (m_fSuppressDowngradeFailure) | ||
351 | { | ||
352 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Downgrade failure has been suppressed; exiting bundle."); | ||
353 | |||
354 | hr = S_OK; | ||
355 | SetState(WIXSTDBA_STATE_APPLIED, hr); | ||
356 | ExitFunction(); | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | // If we are going to apply a downgrade, bail. | ||
361 | hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION); | ||
362 | BalExitOnFailure(hr, "Cannot install a product when a newer version is installed."); | ||
363 | } | ||
364 | } | ||
365 | } | 339 | } |
366 | 340 | ||
367 | SetState(WIXSTDBA_STATE_DETECTED, hrStatus); | 341 | SetState(WIXSTDBA_STATE_DETECTED, hrStatus); |
@@ -371,7 +345,6 @@ public: // IBootstrapperApplication | |||
371 | ::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action); | 345 | ::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action); |
372 | } | 346 | } |
373 | 347 | ||
374 | LExit: | ||
375 | return hr; | 348 | return hr; |
376 | } | 349 | } |
377 | 350 | ||
@@ -1092,6 +1065,20 @@ public: // IBootstrapperApplication | |||
1092 | return hr; | 1065 | return hr; |
1093 | } | 1066 | } |
1094 | 1067 | ||
1068 | virtual STDMETHODIMP OnApplyDowngrade( | ||
1069 | __in HRESULT /*hrRecommendation*/, | ||
1070 | __in HRESULT* phrStatus | ||
1071 | ) | ||
1072 | { | ||
1073 | HRESULT hr = S_OK; | ||
1074 | |||
1075 | if (m_fSuppressDowngradeFailure) | ||
1076 | { | ||
1077 | *phrStatus = S_OK; | ||
1078 | } | ||
1079 | |||
1080 | return hr; | ||
1081 | } | ||
1095 | 1082 | ||
1096 | virtual STDMETHODIMP OnApplyComplete( | 1083 | virtual STDMETHODIMP OnApplyComplete( |
1097 | __in HRESULT hrStatus, | 1084 | __in HRESULT hrStatus, |
@@ -1445,6 +1432,9 @@ public: // IBootstrapperApplication | |||
1445 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE: | 1432 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLETYPE: |
1446 | OnPlanRelatedBundleTypeFallback(reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults)); | 1433 | OnPlanRelatedBundleTypeFallback(reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLETYPE_RESULTS*>(pvResults)); |
1447 | break; | 1434 | break; |
1435 | case BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE: | ||
1436 | OnApplyDowngradeFallback(reinterpret_cast<BA_ONAPPLYDOWNGRADE_ARGS*>(pvArgs), reinterpret_cast<BA_ONAPPLYDOWNGRADE_RESULTS*>(pvResults)); | ||
1437 | break; | ||
1448 | default: | 1438 | default: |
1449 | #ifdef DEBUG | 1439 | #ifdef DEBUG |
1450 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message); | 1440 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message); |
@@ -2118,6 +2108,14 @@ private: // privates | |||
2118 | BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RESTORE_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState)); | 2108 | BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RESTORE_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState)); |
2119 | } | 2109 | } |
2120 | 2110 | ||
2111 | void OnApplyDowngradeFallback( | ||
2112 | __in BA_ONAPPLYDOWNGRADE_ARGS* pArgs, | ||
2113 | __inout BA_ONAPPLYDOWNGRADE_RESULTS* pResults | ||
2114 | ) | ||
2115 | { | ||
2116 | m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE, pArgs, pResults, m_pvBAFunctionsProcContext); | ||
2117 | } | ||
2118 | |||
2121 | 2119 | ||
2122 | public: //CBalBaseBootstrapperApplication | 2120 | public: //CBalBaseBootstrapperApplication |
2123 | virtual STDMETHODIMP Initialize( | 2121 | virtual STDMETHODIMP Initialize( |
@@ -4195,7 +4193,7 @@ public: | |||
4195 | __in BOOL fPrereq, | 4193 | __in BOOL fPrereq, |
4196 | __in HRESULT hrHostInitialization, | 4194 | __in HRESULT hrHostInitialization, |
4197 | __in IBootstrapperEngine* pEngine | 4195 | __in IBootstrapperEngine* pEngine |
4198 | ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000) | 4196 | ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000) |
4199 | { | 4197 | { |
4200 | THEME_ASSIGN_CONTROL_ID* pAssignControl = NULL; | 4198 | THEME_ASSIGN_CONTROL_ID* pAssignControl = NULL; |
4201 | 4199 | ||
@@ -4224,7 +4222,6 @@ public: | |||
4224 | m_state = WIXSTDBA_STATE_INITIALIZING; | 4222 | m_state = WIXSTDBA_STATE_INITIALIZING; |
4225 | m_hrFinal = hrHostInitialization; | 4223 | m_hrFinal = hrHostInitialization; |
4226 | 4224 | ||
4227 | m_fDowngrading = FALSE; | ||
4228 | m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; | 4225 | m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; |
4229 | m_fRestartRequired = FALSE; | 4226 | m_fRestartRequired = FALSE; |
4230 | m_fShouldRestart = FALSE; | 4227 | m_fShouldRestart = FALSE; |
@@ -4529,7 +4526,6 @@ private: | |||
4529 | DWORD m_dwCalculatedCacheProgress; | 4526 | DWORD m_dwCalculatedCacheProgress; |
4530 | DWORD m_dwCalculatedExecuteProgress; | 4527 | DWORD m_dwCalculatedExecuteProgress; |
4531 | 4528 | ||
4532 | BOOL m_fDowngrading; | ||
4533 | BOOTSTRAPPER_APPLY_RESTART m_restartResult; | 4529 | BOOTSTRAPPER_APPLY_RESTART m_restartResult; |
4534 | BOOL m_fRestartRequired; | 4530 | BOOL m_fRestartRequired; |
4535 | BOOL m_fShouldRestart; | 4531 | BOOL m_fShouldRestart; |
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/WixStdBaTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/WixStdBaTests.cs new file mode 100644 index 00000000..e3418cc1 --- /dev/null +++ b/src/test/burn/WixToolsetTest.BurnE2E/WixStdBaTests.cs | |||
@@ -0,0 +1,55 @@ | |||
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 | namespace WixToolsetTest.BurnE2E | ||
4 | { | ||
5 | using WixTestTools; | ||
6 | using Xunit; | ||
7 | using Xunit.Abstractions; | ||
8 | |||
9 | public class WixStdBaTests : BurnE2ETests | ||
10 | { | ||
11 | public WixStdBaTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } | ||
12 | |||
13 | [Fact] | ||
14 | public void ExitsWithErrorWhenDowngradingWithoutSuppression() | ||
15 | { | ||
16 | var packageA = this.CreatePackageInstaller("PackageA"); | ||
17 | var bundle1v10 = this.CreateBundleInstaller("WixStdBaTest1_v10"); | ||
18 | var bundle1v11 = this.CreateBundleInstaller("WixStdBaTest1_v11"); | ||
19 | |||
20 | packageA.VerifyInstalled(false); | ||
21 | |||
22 | bundle1v11.Install(); | ||
23 | bundle1v11.VerifyRegisteredAndInPackageCache(); | ||
24 | |||
25 | packageA.VerifyInstalled(true); | ||
26 | |||
27 | bundle1v10.Install((int)MSIExec.MSIExecReturnCode.ERROR_PRODUCT_VERSION); | ||
28 | bundle1v10.VerifyUnregisteredAndRemovedFromPackageCache(); | ||
29 | bundle1v11.VerifyRegisteredAndInPackageCache(); | ||
30 | |||
31 | packageA.VerifyInstalled(true); | ||
32 | } | ||
33 | |||
34 | [Fact] | ||
35 | public void ExitsWithoutErrorWhenDowngradingWithSuppression() | ||
36 | { | ||
37 | var packageA = this.CreatePackageInstaller("PackageA"); | ||
38 | var bundle1v11 = this.CreateBundleInstaller("WixStdBaTest1_v11"); | ||
39 | var bundle1v12 = this.CreateBundleInstaller("WixStdBaTest1_v12"); | ||
40 | |||
41 | packageA.VerifyInstalled(false); | ||
42 | |||
43 | bundle1v12.Install(); | ||
44 | bundle1v12.VerifyRegisteredAndInPackageCache(); | ||
45 | |||
46 | packageA.VerifyInstalled(true); | ||
47 | |||
48 | bundle1v11.Install(); | ||
49 | bundle1v11.VerifyUnregisteredAndRemovedFromPackageCache(); | ||
50 | bundle1v12.VerifyRegisteredAndInPackageCache(); | ||
51 | |||
52 | packageA.VerifyInstalled(true); | ||
53 | } | ||
54 | } | ||
55 | } | ||