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 15, 2024
1 parent eef4ae2 commit a8595cd
Show file tree
Hide file tree
Showing 19 changed files with 282 additions and 2 deletions.
1 change: 1 addition & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- Changes by WiX up to git commit 376423b8101f4b59ee865e8a255cfe190fa5a7f1
- Build for .NET Framework 4.0
- Not overwriting log files when retrying to execute a package
- Support sending custom messages on embedded pipe

# WiX Toolset on GitHub
The WiX Toolset builds Windows installation packages from XML source code. The toolset supports a command-line environment that developers may integrate into their build processes to build Windows Installer (MSI) packages and executable bundles. The WiX GitHub project hosts the WiX source code Git repositories. The following links will take you to more details:
Expand Down
38 changes: 38 additions & 0 deletions src/burn/engine/EngineForApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,44 @@ class CEngineForApplication : public IBootstrapperEngine, public IMarshal
return hr;
}

virtual STDMETHODIMP SendEmbeddedCustomMessage(
__in DWORD dwCode,
__in_z_opt LPCWSTR wzMessage,
__out int* pnResult
)
{
HRESULT hr = S_OK;
BYTE* pbData = NULL;
DWORD cbData = 0;
DWORD dwResult = 0;

if (BURN_MODE_EMBEDDED != m_pEngineState->mode)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
ExitOnRootFailure(hr, "Application requested to send embedded custom message when not in embedded mode.");
}
if ((m_pEngineState->embeddedConnection.dwCapabilities & BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE) != BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE)
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
ExitOnRootFailure(hr, "Parent engine does not support receiving embedded custom messages.");
}

hr = BuffWriteNumber(&pbData, &cbData, dwCode);
ExitOnFailure(hr, "Failed to write code to message buffer.");

hr = BuffWriteString(&pbData, &cbData, wzMessage ? wzMessage : L"");
ExitOnFailure(hr, "Failed to write text to message buffer.");

hr = PipeSendMessage(m_pEngineState->embeddedConnection.hPipe, BURN_EMBEDDED_MESSAGE_TYPE_CUSTOM, pbData, cbData, NULL, NULL, &dwResult);
ExitOnFailure(hr, "Failed to send embedded custom message over pipe.");

*pnResult = static_cast<int>(dwResult);

LExit:
ReleaseBuffer(pbData);
return hr;
}

virtual STDMETHODIMP SetUpdate(
__in_z_opt LPCWSTR wzLocalSource,
__in_z_opt LPCWSTR wzDownloadSource,
Expand Down
4 changes: 4 additions & 0 deletions src/burn/engine/apply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,10 @@ static int GenericExecuteMessageHandler(
case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE:
nResult = pContext->pUX->pUserExperience->OnExecuteFilesInUse(pContext->pExecutingPackage->sczId, pMessage->filesInUse.cFiles, pMessage->filesInUse.rgwzFiles);
break;

case GENERIC_EXECUTE_MESSAGE_CUSTOM:
nResult = pContext->pUX->pUserExperience->OnEmbeddedCustomMessage(pContext->pExecutingPackage->sczId, pMessage->custom.dwCode, pMessage->custom.wzMessage);
break;
}

nResult = UserExperienceCheckExecuteResult(pContext->pUX, pContext->fRollback, pMessage->dwAllowedResults, nResult);
Expand Down
6 changes: 6 additions & 0 deletions src/burn/engine/apply.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ enum GENERIC_EXECUTE_MESSAGE_TYPE
GENERIC_EXECUTE_MESSAGE_ERROR,
GENERIC_EXECUTE_MESSAGE_PROGRESS,
GENERIC_EXECUTE_MESSAGE_FILES_IN_USE,
GENERIC_EXECUTE_MESSAGE_CUSTOM,
};

typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA
Expand Down Expand Up @@ -43,6 +44,11 @@ typedef struct _GENERIC_EXECUTE_MESSAGE
DWORD cFiles;
LPCWSTR* rgwzFiles;
} filesInUse;
struct
{
DWORD dwCode;
LPCWSTR wzMessage;
} custom;
};
} GENERIC_EXECUTE_MESSAGE;

Expand Down
11 changes: 11 additions & 0 deletions src/burn/engine/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,17 @@ static HRESULT ParseCommandLine(

i += 2;
}
else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED_CAPABILITIES, -1))
{
if (i + 1 >= argc)
{
ExitOnRootFailure(hr = E_INVALIDARG, "Must specify the embedded capabilities.");
}
++i;

hr = StrStringToUInt32(argv[i], 0, reinterpret_cast<UINT*>(&pEmbeddedConnection->dwCapabilities));
ExitOnFailure(hr, "Failed to parse parent pipe capabilities.");
}
else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DETECT, -1))
{
pCommand->relationType = BOOTSTRAPPER_RELATION_DETECT;
Expand Down
1 change: 1 addition & 0 deletions src/burn/engine/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT_NONE = L"parent:none";
const LPCWSTR BURN_COMMANDLINE_SWITCH_CLEAN_ROOM = L"burn.clean.room";
const LPCWSTR BURN_COMMANDLINE_SWITCH_ELEVATED = L"burn.elevated";
const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED = L"burn.embedded";
const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED_CAPABILITIES = L"burn.embedded.capabilities";
const LPCWSTR BURN_COMMANDLINE_SWITCH_RUNONCE = L"burn.runonce";
const LPCWSTR BURN_COMMANDLINE_SWITCH_LOG_APPEND = L"burn.log.append";
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DETECT = L"burn.related.detect";
Expand Down
28 changes: 27 additions & 1 deletion src/burn/engine/elevation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE

BURN_ELEVATION_TRANSACTION_BEGIN,
BURN_ELEVATION_TRANSACTION_COMMIT,
BURN_ELEVATION_TRANSACTION_ROLLBACK
BURN_ELEVATION_TRANSACTION_ROLLBACK,

BURN_ELEVATION_MESSAGE_TYPE_EMBEDDED_CUSTOM,

} BURN_ELEVATION_MESSAGE_TYPE;

Expand Down Expand Up @@ -1378,6 +1380,19 @@ static HRESULT ProcessGenericExecuteMessages(
message.error.wzMessage = sczMessage;
break;

case BURN_ELEVATION_MESSAGE_TYPE_EMBEDDED_CUSTOM:
message.type = GENERIC_EXECUTE_MESSAGE_CUSTOM;
message.dwAllowedResults = 0xFFFFFFFF;

hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.custom.dwCode);
ExitOnFailure(hr, "Failed to read custom code from buffer.");

hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage);
ExitOnFailure(hr, "Failed to read custom message from buffer.");

message.custom.wzMessage = sczMessage;
break;

case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE:
message.type = GENERIC_EXECUTE_MESSAGE_FILES_IN_USE;

Expand Down Expand Up @@ -2681,6 +2696,17 @@ static int GenericExecuteMessageHandler(
dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR;
break;

case GENERIC_EXECUTE_MESSAGE_CUSTOM:
// serialize message data
hr = BuffWriteNumber(&pbData, &cbData, pMessage->custom.dwCode);
ExitOnFailure(hr, "Failed to write code to message buffer.");

hr = BuffWriteString(&pbData, &cbData, pMessage->custom.wzMessage);
ExitOnFailure(hr, "Failed to write message to message buffer.");

dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EMBEDDED_CUSTOM;
break;

case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE:
hr = BuffWriteNumber(&pbData, &cbData, pMessage->filesInUse.cFiles);
ExitOnFailure(hr, "Failed to count of files in use to message buffer.");
Expand Down
46 changes: 45 additions & 1 deletion src/burn/engine/embedded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ static HRESULT OnEmbeddedProgress(
__in DWORD cbData,
__out DWORD* pdwResult
);
static HRESULT OnEmbeddedCustomMessage(
__in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
__in LPVOID pvContext,
__in_bcount(cbData) BYTE* pbData,
__in DWORD cbData,
__out DWORD* pdwResult
);

// function definitions

Expand Down Expand Up @@ -68,7 +75,7 @@ extern "C" HRESULT EmbeddedRunBundle(
hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent);
ExitOnFailure(hr, "Failed to create embedded pipe.");

hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u -%ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId, BURN_COMMANDLINE_SWITCH_EMBEDDED_CAPABILITIES, BURN_PIPE_CAPABILITIES_ALL);
ExitOnFailure(hr, "Failed to allocate embedded command.");

if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
Expand Down Expand Up @@ -127,6 +134,11 @@ static HRESULT ProcessEmbeddedMessages(
ExitOnFailure(hr, "Failed to process embedded progress message.");
break;

case BURN_EMBEDDED_MESSAGE_TYPE_CUSTOM:
hr = OnEmbeddedCustomMessage(pContext->pfnGenericMessageHandler, pContext->pvContext, static_cast<BYTE*>(pMsg->pvData), pMsg->cbData, &dwResult);
ExitOnFailure(hr, "Failed to process embedded custom message.");
break;

default:
hr = E_INVALIDARG;
ExitOnRootFailure1(hr, "Unexpected embedded message sent to child process, msg: %u", pMsg->dwMessage);
Expand Down Expand Up @@ -172,6 +184,38 @@ static HRESULT OnEmbeddedErrorMessage(
return hr;
}

static HRESULT OnEmbeddedCustomMessage(
__in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
__in LPVOID pvContext,
__in_bcount(cbData) BYTE* pbData,
__in DWORD cbData,
__out DWORD* pdwResult
)
{
HRESULT hr = S_OK;
DWORD iData = 0;
GENERIC_EXECUTE_MESSAGE message = { };
LPWSTR sczMessage = NULL;

message.type = GENERIC_EXECUTE_MESSAGE_CUSTOM;
message.dwAllowedResults = 0xFFFFFFFF;

hr = BuffReadNumber(pbData, cbData, &iData, &message.custom.dwCode);
ExitOnFailure(hr, "Failed to read custom code from buffer.");

hr = BuffReadString(pbData, cbData, &iData, &sczMessage);
ExitOnFailure(hr, "Failed to read custom message from buffer.");

message.custom.wzMessage = sczMessage;

*pdwResult = (DWORD)pfnMessageHandler(&message, pvContext);

LExit:
ReleaseStr(sczMessage);

return hr;
}

static HRESULT OnEmbeddedProgress(
__in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
__in LPVOID pvContext,
Expand Down
1 change: 1 addition & 0 deletions src/burn/engine/embedded.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ typedef enum _BURN_EMBEDDED_MESSAGE_TYPE
BURN_EMBEDDED_MESSAGE_TYPE_UNKNOWN,
BURN_EMBEDDED_MESSAGE_TYPE_ERROR,
BURN_EMBEDDED_MESSAGE_TYPE_PROGRESS,
BURN_EMBEDDED_MESSAGE_TYPE_CUSTOM = 1000, // Allow enough room for standard WiX values
} BURN_EMBEDDED_MESSAGE_TYPE;


Expand Down
11 changes: 11 additions & 0 deletions src/burn/engine/pipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@
extern "C" {
#endif


enum BURN_PIPE_CAPABILITIES
{
BURN_PIPE_CAPABILITIES_NONE = 0,
BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE = 1,

// All the capabilities that this engine supports, used when creating capabilities command line for the embedded bundle
BURN_PIPE_CAPABILITIES_ALL = BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE,
};

typedef struct _BURN_PIPE_CONNECTION
{
LPWSTR sczName;
LPWSTR sczSecret;
DWORD dwProcessId;
DWORD dwCapabilities; // Capabilities of the engine that created the pipe

HANDLE hProcess;
HANDLE hPipe;
Expand Down
10 changes: 10 additions & 0 deletions src/burn/inc/IBootstrapperApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,16 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
__in DWORD cFiles,
__in_ecount_z(cFiles) LPCWSTR* rgwzFiles
) = 0;

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

// OnExecutePackageComplete - called when a package execution is complete.
//
Expand Down
6 changes: 6 additions & 0 deletions src/burn/inc/IBootstrapperEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,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
26 changes: 26 additions & 0 deletions src/ext/BalExtension/mba/core/BootstrapperApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,11 @@ protected BootstrapperApplication()
/// </summary>
public event EventHandler<ExecuteFilesInUseEventArgs> ExecuteFilesInUse;

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

/// <summary>
/// Fired when the engine has completed installing a specific package.
/// </summary>
Expand Down Expand Up @@ -1141,6 +1146,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 when the engine has completed installing a specific package.
/// </summary>
Expand Down Expand Up @@ -1638,6 +1656,14 @@ Result IBootstrapperApplication.OnExecuteFilesInUse(string wzPackageId, int cFil
return args.Result;
}

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

return args.Result;
}

Result IBootstrapperApplication.OnExecutePackageComplete(string wzPackageId, int hrExitCode, ApplyRestart restart, int nRecommendation)
{
ExecutePackageCompleteEventArgs args = new ExecutePackageCompleteEventArgs(wzPackageId, hrExitCode, restart, nRecommendation);
Expand Down
15 changes: 15 additions & 0 deletions src/ext/BalExtension/mba/core/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,21 @@ public int SendEmbeddedProgress(int progressPercentage, int overallPercentage)
return result;
}

/// <summary>
/// Sends a custom embedded message.
/// </summary>
/// <param name="code">Custom message code.</param>
/// <param name="message">Optional text.</param>
/// <exception cref="System.NotSupportedException">
/// Thrown when the parent burn engine does not support receiving custom messages
/// </exception>
public int SendEmbeddedCustomMessage(int code, string message)
{
int result = 0;
this.engine.SendEmbeddedCustomMessage(code, message, out result);
return result;
}

/// <summary>
/// Shuts down the engine.
/// </summary>
Expand Down
Loading

0 comments on commit a8595cd

Please sign in to comment.