Skip to content

Commit

Permalink
Support sending custom messages on embedded pipe
Browse files Browse the repository at this point in the history
  • Loading branch information
nirbar committed May 12, 2024
1 parent b3e71d5 commit afcea91
Show file tree
Hide file tree
Showing 30 changed files with 587 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ This repository contains the PanelSwWix4: A custom WiX Toolset codebase
- Un-plan MSI transaction if it contains less than 2 packages
- Add BA methods OnPlanMsiTransaction, OnPlanMsiTransactionComplete: Let BA opt-out of MSI transactions.
- Not overwriting log files when retrying to execute a package
- Support sending custom messages on embedded pipe
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ public abstract class BootstrapperApplication : MarshalByRefObject, IDefaultBoot
/// <inheritdoc/>
public event EventHandler<ExecuteFilesInUseEventArgs> ExecuteFilesInUse;

/// <inheritdoc/>
public event EventHandler<EmbeddedCustomMessageEventArgs> EmbeddedCustomMessage;

/// <inheritdoc/>
public event EventHandler<ExecutePackageCompleteEventArgs> ExecutePackageComplete;

Expand Down Expand Up @@ -1044,6 +1047,19 @@ protected virtual void OnExecuteFilesInUse(ExecuteFilesInUseEventArgs args)
}
}

/// <summary>
/// Called when an embedded burn package sends a SendEmbeddedCustomMessage(...).
/// </summary>
/// <param name="args">Additional arguments for this event.</param>
protected virtual void OnEmbeddedCustomMessage(EmbeddedCustomMessageEventArgs args)
{
EventHandler<EmbeddedCustomMessageEventArgs> handler = this.EmbeddedCustomMessage;
if (null != handler)
{
handler(this, args);
}
}

/// <summary>
/// Called by the engine, raises the <see cref="ExecutePackageComplete"/> event.
/// </summary>
Expand Down Expand Up @@ -1933,6 +1949,15 @@ int IBootstrapperApplication.OnExecuteFilesInUse(string wzPackageId, int cFiles,
return args.HResult;
}

int IBootstrapperApplication.OnEmbeddedCustomMessage(string wzPackageId, int dwCode, string wzMessage, ref Result pResult)
{
EmbeddedCustomMessageEventArgs args = new EmbeddedCustomMessageEventArgs(wzPackageId, dwCode, wzMessage);
this.OnEmbeddedCustomMessage(args);

pResult = args.Result;
return args.HResult;
}

int IBootstrapperApplication.OnExecutePackageComplete(string wzPackageId, int hrStatus, ApplyRestart restart, BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION recommendation, ref BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION pAction)
{
ExecutePackageCompleteEventArgs args = new ExecutePackageCompleteEventArgs(wzPackageId, hrStatus, restart, recommendation, pAction);
Expand Down
8 changes: 8 additions & 0 deletions src/api/burn/WixToolset.BootstrapperApplicationApi/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,14 @@ public int SendEmbeddedProgress(int progressPercentage, int overallPercentage)
return result;
}

/// <inheritdoc/>
public int SendEmbeddedCustomMessage(int code, string message)
{
int result = 0;
this.engine.SendEmbeddedCustomMessage(code, message, out result);
return result;
}

/// <inheritdoc/>
public void Quit(int exitCode)
{
Expand Down
49 changes: 49 additions & 0 deletions src/api/burn/WixToolset.BootstrapperApplicationApi/EventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,55 @@ public ExecuteFilesInUseEventArgs(string packageId, string[] files, Result recom
public FilesInUseType Source { get; private set; }
}

/// <summary>
/// Additional arugments used for embedded custom messages.
/// </summary>
[Serializable]
public class EmbeddedCustomMessageEventArgs : ResultEventArgs
{
private string packageId;
private int code;
private string message;

/// <summary>
/// Creates a new instance of the <see cref="EmbeddedCustomMessageEventArgs"/> class.
/// </summary>
/// <param name="packageId">The identity of the package that yielded the files in use message.</param>
/// <param name="code">Message code.</param>
/// <param name="message">Message text.</param>
public EmbeddedCustomMessageEventArgs(string packageId, int code, string message)
: base(Result.None, Result.None)
{
this.packageId = packageId;
this.code = code;
this.message = message;
}

/// <summary>
/// Gets the identity of the package that yielded the files in use message.
/// </summary>
public string PackageId
{
get { return this.packageId; }
}

/// <summary>
/// Gets the message code.
/// </summary>
public int Code
{
get { return this.code; }
}

/// <summary>
/// Gets the message text.
/// </summary>
public string Message
{
get { return this.message; }
}
}

/// <summary>
/// Event arguments for <see cref="IDefaultBootstrapperApplication.ExecutePackageComplete"/>
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,18 @@ int hrStatus
[MarshalAs(UnmanagedType.I4)] ref Result pResult
);

/// <summary>
/// See <see cref="IDefaultBootstrapperApplication.EmbeddedCustomMessage"/>.
/// </summary>
[PreserveSig]
[return: MarshalAs(UnmanagedType.I4)]
int OnEmbeddedCustomMessage(
[MarshalAs(UnmanagedType.LPWStr)] string wzPackageId,
[MarshalAs(UnmanagedType.U4)] int dwCode,
[MarshalAs(UnmanagedType.LPWStr)] string wzMessage,
[MarshalAs(UnmanagedType.I4)] ref Result pResult
);

/// <summary>
/// See <see cref="IDefaultBootstrapperApplication.ExecutePackageComplete"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ public interface IBootstrapperEngine
[MarshalAs(UnmanagedType.I4)] out int pnResult
);

/// <summary>
/// See <see cref="IEngine.SendEmbeddedCustomMessage(int, string)"/>.
/// </summary>
void SendEmbeddedCustomMessage(
[MarshalAs(UnmanagedType.U4)] int dwCode,
[MarshalAs(UnmanagedType.LPWStr)] string wzMessage,
[MarshalAs(UnmanagedType.I4)] out int pnResult
);

/// <summary>
/// See <see cref="IEngine.SetUpdate(string, string, long, UpdateHashType, string, string)"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ public interface IDefaultBootstrapperApplication : IBootstrapperApplication
/// </summary>
event EventHandler<ExecuteFilesInUseEventArgs> ExecuteFilesInUse;

/// <summary>
/// Fired when an embedded burn package sends a SendEmbeddedCustomMessage(...).
/// </summary>
event EventHandler<EmbeddedCustomMessageEventArgs> EmbeddedCustomMessage;

/// <summary>
/// Fired when Windows Installer sends an installation message.
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions src/api/burn/WixToolset.BootstrapperApplicationApi/IEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,16 @@ public interface IEngine
/// <param name="overallPercentage">Overall percentage completed.</param>
int SendEmbeddedProgress(int progressPercentage, int overallPercentage);

/// <summary>
/// Send a custom embedded message.
/// </summary>
/// <param name="code">Message code.</param>
/// <param name="message">Error text.</param>
/// <exception cref="System.NotSupportedException">
/// Thrown when the parent burn engine does not support receiving custom messages
/// </exception>
int SendEmbeddedCustomMessage(int code, string message);

/// <summary>
/// Shuts down the engine.
/// </summary>
Expand Down
58 changes: 58 additions & 0 deletions src/api/burn/balutil/BalBootstrapperEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,64 @@ class CBalBootstrapperEngine : public IBootstrapperEngine
return hr;
}

virtual STDMETHODIMP SendEmbeddedCustomMessage(
__in DWORD dwCode,
__in_z_opt LPCWSTR wzMessage,
__out int* pnResult
)
{
HRESULT hr = S_OK;
BAENGINE_SENDEMBEDDEDCUSTOMMESSAGE_ARGS args = { };
BAENGINE_SENDEMBEDDEDCUSTOMMESSAGE_RESULTS results = { };
BUFF_BUFFER bufferArgs = { };
BUFF_BUFFER bufferResults = { };
PIPE_RPC_RESULT rpc = { };
SIZE_T iBuffer = 0;

ExitOnNull(pnResult, hr, E_INVALIDARG, "pnResult is required");

// Init send structs.
args.dwApiVersion = WIX_5_BOOTSTRAPPER_APPLICATION_API_VERSION;
args.dwCode = dwCode;
args.wzMessage = wzMessage;

results.dwApiVersion = WIX_5_BOOTSTRAPPER_APPLICATION_API_VERSION;

// Send args.
hr = BuffWriteNumberToBuffer(&bufferArgs, args.dwApiVersion);
ExitOnFailure(hr, "Failed to write API version of SendEmbeddedCustomMessage args.");

hr = BuffWriteNumberToBuffer(&bufferArgs, args.dwCode);
ExitOnFailure(hr, "Failed to write progress of SendEmbeddedCustomMessage args.");

hr = BuffWriteStringToBuffer(&bufferArgs, args.wzMessage);
ExitOnFailure(hr, "Failed to write overall progress of SendEmbeddedCustomMessage args.");

// Send results.
hr = BuffWriteNumberToBuffer(&bufferResults, results.dwApiVersion);
ExitOnFailure(hr, "Failed to write API version of SendEmbeddedCustomMessage results.");

// Get results.
hr = SendRequest(BOOTSTRAPPER_ENGINE_MESSAGE_SENDEMBEDDEDCUSTOMMESSAGE, &bufferArgs, &bufferResults, &rpc);
ExitOnFailure(hr, "BA SendEmbeddedCustomMessage failed.");

// Read results.
hr = BuffReadNumber(rpc.pbData, rpc.cbData, &iBuffer, &results.dwApiVersion);
ExitOnFailure(hr, "Failed to read size from SendEmbeddedCustomMessage results.");

hr = BuffReadNumber(rpc.pbData, rpc.cbData, &iBuffer, reinterpret_cast<DWORD*>(&results.nResult));
ExitOnFailure(hr, "Failed to read result from SendEmbeddedCustomMessage results.");

*pnResult = results.nResult;

LExit:
PipeFreeRpcResult(&rpc);
ReleaseBuffer(bufferResults);
ReleaseBuffer(bufferArgs);

return hr;
}

virtual STDMETHODIMP SetUpdate(
__in_z_opt LPCWSTR wzLocalSource,
__in_z_opt LPCWSTR wzDownloadSource,
Expand Down
15 changes: 15 additions & 0 deletions src/api/burn/balutil/inc/BootstrapperApplicationBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,21 @@ class CBootstrapperApplicationBase : public IBootstrapperApplication
return S_OK;
}

virtual STDMETHODIMP OnEmbeddedCustomMessage(
__in_z LPCWSTR /*wzPackageId*/,
__in DWORD /*dwCode*/,
__in_z LPCWSTR /*wzMessage*/,
__inout int* pResult
)
{
if (CheckCanceled())
{
*pResult = IDCANCEL;
}

return S_OK;
}

virtual STDMETHODIMP OnExecutePackageComplete(
__in_z LPCWSTR wzPackageId,
__in HRESULT hrStatus,
Expand Down
10 changes: 10 additions & 0 deletions src/api/burn/balutil/inc/IBootstrapperApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
__inout int* pResult
) = 0;

// OnEmbeddedCustomMessage - called when an embedded burn package send a SendEmbeddedCustomMessage(...).
//
// Return any code that the sender and recipient agree on.
STDMETHOD(OnEmbeddedCustomMessage)(
__in_z LPCWSTR wzPackageId,
__in DWORD dwCode,
__in_z LPCWSTR wzMessage,
__inout int* pResult
) = 0;

// OnExecutePackageComplete - called when a package execution is complete.
//
STDMETHOD(OnExecutePackageComplete)(
Expand Down
6 changes: 6 additions & 0 deletions src/api/burn/balutil/inc/IBootstrapperEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperEngine, IUnknown, "6480D616-27A0-44D7-905B-8
__out int* pnResult
) = 0;

STDMETHOD(SendEmbeddedCustomMessage)(
__in DWORD dwCode,
__in_z_opt LPCWSTR wzMessage,
__out int* pnResult
) = 0;

STDMETHOD(SetUpdate)(
__in_z_opt LPCWSTR wzLocalSource,
__in_z_opt LPCWSTR wzDownloadSource,
Expand Down
65 changes: 65 additions & 0 deletions src/api/burn/balutil/msg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2645,6 +2645,67 @@ static HRESULT OnError(
return hr;
}

static HRESULT OnEmbeddedCustomMessage(
__in IBootstrapperApplication* pApplication,
__in BUFF_READER* pReaderArgs,
__in BUFF_READER* pReaderResults,
__in BUFF_BUFFER* pBuffer
)
{
HRESULT hr = S_OK;
BA_ONEMBEDDEDCUSTOMMESSAGE_ARGS args = { };
BA_ONEMBEDDEDCUSTOMMESSAGE_RESULTS results = { };
LPWSTR sczPackageId = NULL;
LPWSTR sczMessage = NULL;

// Read args.
hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion);
ExitOnFailure(hr, "Failed to read API version of OnEmbeddedCustomMessage args.");

hr = BuffReaderReadString(pReaderArgs, &sczPackageId);
ExitOnFailure(hr, "Failed to read package id of OnEmbeddedCustomMessage args.");

args.wzPackageId = sczPackageId;

hr = BuffReaderReadNumber(pReaderArgs, &args.dwCode);
ExitOnFailure(hr, "Failed to read code of OnEmbeddedCustomMessage args.");

hr = BuffReaderReadString(pReaderArgs, &sczMessage);
ExitOnFailure(hr, "Failed to read error of OnEmbeddedCustomMessage args.");

args.wzMessage = sczMessage;

// Read results.
hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion);
ExitOnFailure(hr, "Failed to read API version of OnEmbeddedCustomMessage results.");

hr = BuffReaderReadNumber(pReaderResults, reinterpret_cast<DWORD*>(&results.nResult));
ExitOnFailure(hr, "Failed to read cancel of OnEmbeddedCustomMessage results.");

// Callback.
hr = pApplication->BAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONEMBEDDEDCUSTOMMESSAGE, &args, &results);

if (E_NOTIMPL == hr)
{
hr = pApplication->OnEmbeddedCustomMessage(args.wzPackageId, args.dwCode, args.wzMessage, &results.nResult);
}

pApplication->BAProcFallback(BOOTSTRAPPER_APPLICATION_MESSAGE_ONEMBEDDEDCUSTOMMESSAGE, &args, &results, &hr);
BalExitOnFailure(hr, "BA OnEmbeddedCustomMessage failed.");

// Write results.
hr = BuffWriteNumberToBuffer(pBuffer, results.dwApiVersion);
ExitOnFailure(hr, "Failed to write size of OnEmbeddedCustomMessage struct.");

hr = BuffWriteNumberToBuffer(pBuffer, results.nResult);
ExitOnFailure(hr, "Failed to write result of OnEmbeddedCustomMessage struct.");

LExit:
ReleaseStr(sczMessage);
ReleaseStr(sczPackageId);
return hr;
}

static HRESULT OnExecuteBegin(
__in IBootstrapperApplication* pApplication,
__in BUFF_READER* pReaderArgs,
Expand Down Expand Up @@ -5039,6 +5100,10 @@ static HRESULT ProcessMessage(
hr = OnError(pApplication, &readerArgs, &readerResults, &bufferResponse);
break;

case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEMBEDDEDCUSTOMMESSAGE:
hr = OnEmbeddedCustomMessage(pApplication, &readerArgs, &readerResults, &bufferResponse);
break;

case BOOTSTRAPPER_APPLICATION_MESSAGE_ONREGISTERBEGIN:
hr = OnRegisterBegin(pApplication, &readerArgs, &readerResults, &bufferResponse);
break;
Expand Down
Loading

0 comments on commit afcea91

Please sign in to comment.