From 780cd25e41f2d2982807a0a2a24a734684d27fe6 Mon Sep 17 00:00:00 2001 From: Sean Hall <r.sean.hall@gmail.com> Date: Fri, 15 May 2020 13:48:38 +1000 Subject: WIXFEAT:6164 Add OnPlanMsiPackage. --- src/WixToolset.Mba.Core/BootstrapperApplication.cs | 34 ++++++- src/WixToolset.Mba.Core/EventArgs.cs | 74 +++++++++++++- .../IBootstrapperApplication.cs | 109 +++++++++++++++++++++ src/balutil/inc/BAFunctions.h | 1 + src/balutil/inc/BalBaseBAFunctions.h | 15 +++ src/balutil/inc/BalBaseBAFunctionsProc.h | 1 + src/balutil/inc/BalBaseBootstrapperApplication.h | 16 +++ .../inc/BalBaseBootstrapperApplicationProc.h | 14 ++- src/balutil/inc/IBootstrapperApplication.h | 14 +++ 9 files changed, 274 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/WixToolset.Mba.Core/BootstrapperApplication.cs index 249c17c9..9ee909dc 100644 --- a/src/WixToolset.Mba.Core/BootstrapperApplication.cs +++ b/src/WixToolset.Mba.Core/BootstrapperApplication.cs @@ -161,6 +161,11 @@ namespace WixToolset.Mba.Core /// </summary> public event EventHandler<PlanMsiFeatureEventArgs> PlanMsiFeature; + /// <summary> + /// Fired when the engine is planning an MSI or MSP package. + /// </summary> + public event EventHandler<PlanMsiPackageEventArgs> PlanMsiPackage; + /// <summary> /// Fired when the engine has completed planning the installation of a specific package. /// </summary> @@ -658,6 +663,19 @@ namespace WixToolset.Mba.Core } } + /// <summary> + /// Called when the engine is planning an MSI or MSP package. + /// </summary> + /// <param name="args">Additional arguments for this event.</param> + protected virtual void OnPlanMsiPackage(PlanMsiPackageEventArgs args) + { + EventHandler<PlanMsiPackageEventArgs> handler = this.PlanMsiPackage; + if (null != handler) + { + handler(this, args); + } + } + /// <summary> /// Called when then engine has completed planning the installation of a specific package. /// </summary> @@ -1288,6 +1306,18 @@ namespace WixToolset.Mba.Core return args.HResult; } + int IBootstrapperApplication.OnPlanMsiPackage(string wzPackageId, bool fExecute, ActionState action, ref bool fCancel, ref BURN_MSI_PROPERTY actionMsiProperty, ref INSTALLUILEVEL uiLevel, ref bool fDisableExternalUiHandler) + { + PlanMsiPackageEventArgs args = new PlanMsiPackageEventArgs(wzPackageId, fExecute, action, fCancel, actionMsiProperty, uiLevel, fDisableExternalUiHandler); + this.OnPlanMsiPackage(args); + + fCancel = args.Cancel; + actionMsiProperty = args.ActionMsiProperty; + uiLevel = args.UiLevel; + fDisableExternalUiHandler = args.DisableExternalUiHandler; + return args.HResult; + } + int IBootstrapperApplication.OnPlanPackageComplete(string wzPackageId, int hrStatus, PackageState state, RequestState requested, ActionState execute, ActionState rollback) { var args = new PlanPackageCompleteEventArgs(wzPackageId, hrStatus, state, requested, execute, rollback); @@ -1466,9 +1496,9 @@ namespace WixToolset.Mba.Core return args.HResult; } - int IBootstrapperApplication.OnExecutePackageBegin(string wzPackageId, bool fExecute, ActionState action, ref bool fCancel) + int IBootstrapperApplication.OnExecutePackageBegin(string wzPackageId, bool fExecute, ActionState action, INSTALLUILEVEL uiLevel, bool fDisableExternalUiHandler, ref bool fCancel) { - ExecutePackageBeginEventArgs args = new ExecutePackageBeginEventArgs(wzPackageId, fExecute, action, fCancel); + ExecutePackageBeginEventArgs args = new ExecutePackageBeginEventArgs(wzPackageId, fExecute, action, uiLevel, fDisableExternalUiHandler, fCancel); this.OnExecutePackageBegin(args); fCancel = args.Cancel; diff --git a/src/WixToolset.Mba.Core/EventArgs.cs b/src/WixToolset.Mba.Core/EventArgs.cs index ca0fa173..e739a853 100644 --- a/src/WixToolset.Mba.Core/EventArgs.cs +++ b/src/WixToolset.Mba.Core/EventArgs.cs @@ -995,6 +995,64 @@ namespace WixToolset.Mba.Core public FeatureState State { get; set; } } + /// <summary> + /// Additional arguments used when the engine is planning an MSI or MSP package. + /// </summary> + [Serializable] + public class PlanMsiPackageEventArgs : CancellableHResultEventArgs + { + /// <summary> + /// Creates a new instance of the <see cref="PlanMsiPackageEventArgs"/> class. + /// </summary> + /// <param name="packageId">The identity of the package planned for.</param> + /// <param name="shouldExecute">Whether the package is planned to execute or roll back.</param> + /// <param name="action">The action planned for the package.</param> + /// <param name="cancelRecommendation">The recommendation from the engine.</param> + /// <param name="actionMsiProperty">The requested MSI property to add.</param> + /// <param name="uiLevel">The requested internal UI level.</param> + /// <param name="disableExternalUiHandler">Whether Burn is requested to set up an external UI handler.</param> + public PlanMsiPackageEventArgs(string packageId, bool shouldExecute, ActionState action, bool cancelRecommendation, BURN_MSI_PROPERTY actionMsiProperty, INSTALLUILEVEL uiLevel, bool disableExternalUiHandler) + : base(cancelRecommendation) + { + this.PackageId = packageId; + this.ShouldExecute = shouldExecute; + this.Action = action; + this.ActionMsiProperty = actionMsiProperty; + this.UiLevel = uiLevel; + this.DisableExternalUiHandler = disableExternalUiHandler; + } + + /// <summary> + /// Gets identity of the package planned for. + /// </summary> + public string PackageId { get; private set; } + + /// <summary> + /// Gets whether the package is planned to execute or roll back. + /// </summary> + public bool ShouldExecute { get; private set; } + + /// <summary> + /// Gets the action planned for the package. + /// </summary> + public ActionState Action { get; private set; } + + /// <summary> + /// Gets or sets the requested MSI property to add. + /// </summary> + public BURN_MSI_PROPERTY ActionMsiProperty { get; set; } + + /// <summary> + /// Gets or sets the requested internal UI level. + /// </summary> + public INSTALLUILEVEL UiLevel { get; set; } + + /// <summary> + /// Gets or sets whether Burn is requested to set up an external UI handler. + /// </summary> + public bool DisableExternalUiHandler { get; set; } + } + /// <summary> /// Additional arguments used when then engine has completed planning the installation of a specific package. /// </summary> @@ -1503,13 +1561,17 @@ namespace WixToolset.Mba.Core /// <param name="packageId">The identity of the package to act on.</param> /// <param name="shouldExecute">Whether the package is being executed or rolled back.</param> /// <param name="action">The action about to be executed.</param> + /// <param name="uiLevel">The internal UI level (if this is an MSI or MSP package).</param> + /// <param name="disableExternalUiHandler">Whether Burn will set up an external UI handler (if this is an MSI or MSP package).</param> /// <param name="cancelRecommendation">The recommendation from the engine.</param> - public ExecutePackageBeginEventArgs(string packageId, bool shouldExecute, ActionState action, bool cancelRecommendation) + public ExecutePackageBeginEventArgs(string packageId, bool shouldExecute, ActionState action, INSTALLUILEVEL uiLevel, bool disableExternalUiHandler, bool cancelRecommendation) : base(cancelRecommendation) { this.PackageId = packageId; this.ShouldExecute = shouldExecute; this.Action = action; + this.UiLevel = uiLevel; + this.DisableExternalUiHandler = disableExternalUiHandler; } /// <summary> @@ -1526,6 +1588,16 @@ namespace WixToolset.Mba.Core /// Gets the action about to be executed. /// </summary> public ActionState Action { get; private set; } + + /// <summary> + /// Gets the internal UI level (if this is an MSI or MSP package). + /// </summary> + public INSTALLUILEVEL UiLevel { get; private set; } + + /// <summary> + /// Gets whether Burn will set up an external UI handler (if this is an MSI or MSP package). + /// </summary> + public bool DisableExternalUiHandler { get; private set; } } /// <summary> diff --git a/src/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/WixToolset.Mba.Core/IBootstrapperApplication.cs index c4daaf32..fa655282 100644 --- a/src/WixToolset.Mba.Core/IBootstrapperApplication.cs +++ b/src/WixToolset.Mba.Core/IBootstrapperApplication.cs @@ -219,6 +219,18 @@ namespace WixToolset.Mba.Core [MarshalAs(UnmanagedType.Bool)] ref bool fCancel ); + [PreserveSig] + [return: MarshalAs(UnmanagedType.I4)] + int OnPlanMsiPackage( + [MarshalAs(UnmanagedType.LPWStr)] string wzPackageId, + [MarshalAs(UnmanagedType.Bool)] bool fExecute, + [MarshalAs(UnmanagedType.U4)] ActionState action, + [MarshalAs(UnmanagedType.Bool)] ref bool fCancel, + [MarshalAs(UnmanagedType.U4)] ref BURN_MSI_PROPERTY actionMsiProperty, + [MarshalAs(UnmanagedType.U4)] ref INSTALLUILEVEL uiLevel, + [MarshalAs(UnmanagedType.Bool)] ref bool fDisableExternalUiHandler + ); + [PreserveSig] [return: MarshalAs(UnmanagedType.I4)] int OnPlanPackageComplete( @@ -393,6 +405,8 @@ namespace WixToolset.Mba.Core [MarshalAs(UnmanagedType.LPWStr)] string wzPackageId, [MarshalAs(UnmanagedType.Bool)] bool fExecute, [MarshalAs(UnmanagedType.U4)] ActionState action, + [MarshalAs(UnmanagedType.U4)] INSTALLUILEVEL uiLevel, + [MarshalAs(UnmanagedType.Bool)] bool fDisableExternalUiHandler, [MarshalAs(UnmanagedType.Bool)] ref bool fCancel ); @@ -832,4 +846,99 @@ namespace WixToolset.Mba.Core Restart, ReloadBootstrapper, } + + /// <summary> + /// The property Burn will add so the MSI can know the planned action for the package. + /// </summary> + public enum BURN_MSI_PROPERTY + { + /// <summary> + /// No property will be added. + /// </summary> + None, + + /// <summary> + /// Add BURNMSIINSTALL=1 + /// </summary> + Install, + + /// <summary> + /// Add BURNMSIMODFIY=1 + /// </summary> + Modify, + + /// <summary> + /// Add BURNMSIREPAIR=1 + /// </summary> + Repair, + + /// <summary> + /// Add BURNMSIUNINSTALL=1 + /// </summary> + Uninstall, + } + + /// <summary> + /// From msi.h + /// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisetinternalui + /// </summary> + [Flags] + public enum INSTALLUILEVEL + { + /// <summary> + /// UI level is unchanged + /// </summary> + NoChange = 0, + + /// <summary> + /// default UI is used + /// </summary> + Default = 1, + + /// <summary> + /// completely silent installation + /// </summary> + None = 2, + + /// <summary> + /// simple progress and error handling + /// </summary> + Basic = 3, + + /// <summary> + /// authored UI, wizard dialogs suppressed + /// </summary> + Reduced = 4, + + /// <summary> + /// authored UI with wizards, progress, errors + /// </summary> + Full = 5, + + /// <summary> + /// display success/failure dialog at end of install + /// </summary> + EndDialog = 0x80, + + /// <summary> + /// display only progress dialog + /// </summary> + ProgressOnly = 0x40, + + /// <summary> + /// do not display the cancel button in basic UI + /// </summary> + HideCancel = 0x20, + + /// <summary> + /// force display of source resolution even if quiet + /// </summary> + SourceResOnly = 0x100, + + /// <summary> + /// show UAC prompt even if quiet + /// Can only be used if on Windows Installer 5.0 or later + /// </summary> + UacOnly = 0x200, + } } diff --git a/src/balutil/inc/BAFunctions.h b/src/balutil/inc/BAFunctions.h index 1338253d..8101afdb 100644 --- a/src/balutil/inc/BAFunctions.h +++ b/src/balutil/inc/BAFunctions.h @@ -64,6 +64,7 @@ enum BA_FUNCTIONS_MESSAGE BA_FUNCTIONS_MESSAGE_ONAPPLYCOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYCOMPLETE, BA_FUNCTIONS_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN = BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN, BA_FUNCTIONS_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE, + BA_FUNCTIONS_MESSAGE_ONPLANMSIPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANMSIPACKAGE, BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, BA_FUNCTIONS_MESSAGE_WNDPROC, diff --git a/src/balutil/inc/BalBaseBAFunctions.h b/src/balutil/inc/BalBaseBAFunctions.h index 411524fb..4e095fb8 100644 --- a/src/balutil/inc/BalBaseBAFunctions.h +++ b/src/balutil/inc/BalBaseBAFunctions.h @@ -298,6 +298,19 @@ public: // IBootstrapperApplication return S_OK; } + virtual STDMETHODIMP OnPlanMsiPackage( + __in_z LPCWSTR /*wzPackageId*/, + __in BOOL /*fExecute*/, + __in BOOTSTRAPPER_ACTION_STATE /*action*/, + __inout BOOL* /*pfCancel*/, + __inout BURN_MSI_PROPERTY* /*pActionMsiProperty*/, + __inout INSTALLUILEVEL* /*pUiLevel*/, + __inout BOOL* /*pfDisableExternalUiHandler*/ + ) + { + return S_OK; + } + virtual STDMETHODIMP OnPlanPackageComplete( __in_z LPCWSTR /*wzPackageId*/, __in HRESULT /*hrStatus*/, @@ -490,6 +503,8 @@ public: // IBootstrapperApplication __in_z LPCWSTR /*wzPackageId*/, __in BOOL /*fExecute*/, __in BOOTSTRAPPER_ACTION_STATE /*action*/, + __in INSTALLUILEVEL /*uiLevel*/, + __in BOOL /*fDisableExternalUiHandler*/, __inout BOOL* /*pfCancel*/ ) { diff --git a/src/balutil/inc/BalBaseBAFunctionsProc.h b/src/balutil/inc/BalBaseBAFunctionsProc.h index da0a71f7..f6ebd9f6 100644 --- a/src/balutil/inc/BalBaseBAFunctionsProc.h +++ b/src/balutil/inc/BalBaseBAFunctionsProc.h @@ -99,6 +99,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc( case BA_FUNCTIONS_MESSAGE_ONAPPLYCOMPLETE: case BA_FUNCTIONS_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN: case BA_FUNCTIONS_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE: + case BA_FUNCTIONS_MESSAGE_ONPLANMSIPACKAGE: hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); break; case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: diff --git a/src/balutil/inc/BalBaseBootstrapperApplication.h b/src/balutil/inc/BalBaseBootstrapperApplication.h index 269777a6..1d014419 100644 --- a/src/balutil/inc/BalBaseBootstrapperApplication.h +++ b/src/balutil/inc/BalBaseBootstrapperApplication.h @@ -311,6 +311,20 @@ public: // IBootstrapperApplication return S_OK; } + virtual STDMETHODIMP OnPlanMsiPackage( + __in_z LPCWSTR /*wzPackageId*/, + __in BOOL /*fExecute*/, + __in BOOTSTRAPPER_ACTION_STATE /*action*/, + __inout BOOL* pfCancel, + __inout BURN_MSI_PROPERTY* /*pActionMsiProperty*/, + __inout INSTALLUILEVEL* /*pUiLevel*/, + __inout BOOL* /*pfDisableExternalUiHandler*/ + ) + { + *pfCancel |= CheckCanceled(); + return S_OK; + } + virtual STDMETHODIMP OnPlanPackageComplete( __in_z LPCWSTR /*wzPackageId*/, __in HRESULT /*hrStatus*/, @@ -604,6 +618,8 @@ public: // IBootstrapperApplication __in_z LPCWSTR wzPackageId, __in BOOL fExecute, __in BOOTSTRAPPER_ACTION_STATE /*action*/, + __in INSTALLUILEVEL /*uiLevel*/, + __in BOOL /*fDisableExternalUiHandler*/, __inout BOOL* pfCancel ) { diff --git a/src/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/balutil/inc/BalBaseBootstrapperApplicationProc.h index 35bc0a9e..d25af1f7 100644 --- a/src/balutil/inc/BalBaseBootstrapperApplicationProc.h +++ b/src/balutil/inc/BalBaseBootstrapperApplicationProc.h @@ -402,7 +402,7 @@ static HRESULT BalBaseBAProcOnExecutePackageBegin( __inout BA_ONEXECUTEPACKAGEBEGIN_RESULTS* pResults ) { - return pBA->OnExecutePackageBegin(pArgs->wzPackageId, pArgs->fExecute, pArgs->action, &pResults->fCancel); + return pBA->OnExecutePackageBegin(pArgs->wzPackageId, pArgs->fExecute, pArgs->action, pArgs->uiLevel, pArgs->fDisableExternalUiHandler, &pResults->fCancel); } static HRESULT BalBaseBAProcOnExecutePatchTarget( @@ -504,6 +504,15 @@ static HRESULT BalBaseBAProcOnLaunchApprovedExeComplete( return pBA->OnLaunchApprovedExeComplete(pArgs->hrStatus, pArgs->dwProcessId); } +static HRESULT BalBaseBAProcOnPlanMsiPackage( + __in IBootstrapperApplication* pBA, + __in BA_ONPLANMSIPACKAGE_ARGS* pArgs, + __inout BA_ONPLANMSIPACKAGE_RESULTS* pResults + ) +{ + return pBA->OnPlanMsiPackage(pArgs->wzPackageId, pArgs->fExecute, pArgs->action, &pResults->fCancel, &pResults->actionMsiProperty, &pResults->uiLevel, &pResults->fDisableExternalUiHandler); +} + /******************************************************************* BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. Provides a default mapping between the new message based BA interface and @@ -689,6 +698,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc( case BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE: hr = BalBaseBAProcOnLaunchApprovedExeComplete(pBA, reinterpret_cast<BA_ONLAUNCHAPPROVEDEXECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONLAUNCHAPPROVEDEXECOMPLETE_RESULTS*>(pvResults)); break; + case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANMSIPACKAGE: + hr = BalBaseBAProcOnPlanMsiPackage(pBA, reinterpret_cast<BA_ONPLANMSIPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANMSIPACKAGE_RESULTS*>(pvResults)); + break; } } diff --git a/src/balutil/inc/IBootstrapperApplication.h b/src/balutil/inc/IBootstrapperApplication.h index 30b456c7..e17d2589 100644 --- a/src/balutil/inc/IBootstrapperApplication.h +++ b/src/balutil/inc/IBootstrapperApplication.h @@ -194,6 +194,18 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A __inout BOOL* pfCancel ) = 0; + // OnPlanMsiPackage - called when the engine plans an MSI or MSP package. + // + STDMETHOD(OnPlanMsiPackage)( + __in_z LPCWSTR wzPackageId, + __in BOOL fExecute, // false means rollback. + __in BOOTSTRAPPER_ACTION_STATE action, + __inout BOOL* pfCancel, + __inout BURN_MSI_PROPERTY* pActionMsiProperty, + __inout INSTALLUILEVEL* pUiLevel, + __inout BOOL* pfDisableExternalUiHandler + ) = 0; + // OnPlanPackageComplete - called after the engine plans a package. // STDMETHOD(OnPlanPackageComplete)( @@ -390,6 +402,8 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A __in_z LPCWSTR wzPackageId, __in BOOL fExecute, // false means rollback. __in BOOTSTRAPPER_ACTION_STATE action, + __in INSTALLUILEVEL uiLevel, + __in BOOL fDisableExternalUiHandler, __inout BOOL* pfCancel ) = 0; -- cgit v1.2.3-55-g6feb