Skip to content

Commit a8595cd

Browse files
committed
Support sending custom messages on embedded pipe
1 parent eef4ae2 commit a8595cd

19 files changed

+282
-2
lines changed

Readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
- Changes by WiX up to git commit 376423b8101f4b59ee865e8a255cfe190fa5a7f1
3636
- Build for .NET Framework 4.0
3737
- Not overwriting log files when retrying to execute a package
38+
- Support sending custom messages on embedded pipe
3839

3940
# WiX Toolset on GitHub
4041
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:

src/burn/engine/EngineForApplication.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,44 @@ class CEngineForApplication : public IBootstrapperEngine, public IMarshal
370370
return hr;
371371
}
372372

373+
virtual STDMETHODIMP SendEmbeddedCustomMessage(
374+
__in DWORD dwCode,
375+
__in_z_opt LPCWSTR wzMessage,
376+
__out int* pnResult
377+
)
378+
{
379+
HRESULT hr = S_OK;
380+
BYTE* pbData = NULL;
381+
DWORD cbData = 0;
382+
DWORD dwResult = 0;
383+
384+
if (BURN_MODE_EMBEDDED != m_pEngineState->mode)
385+
{
386+
hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
387+
ExitOnRootFailure(hr, "Application requested to send embedded custom message when not in embedded mode.");
388+
}
389+
if ((m_pEngineState->embeddedConnection.dwCapabilities & BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE) != BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE)
390+
{
391+
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
392+
ExitOnRootFailure(hr, "Parent engine does not support receiving embedded custom messages.");
393+
}
394+
395+
hr = BuffWriteNumber(&pbData, &cbData, dwCode);
396+
ExitOnFailure(hr, "Failed to write code to message buffer.");
397+
398+
hr = BuffWriteString(&pbData, &cbData, wzMessage ? wzMessage : L"");
399+
ExitOnFailure(hr, "Failed to write text to message buffer.");
400+
401+
hr = PipeSendMessage(m_pEngineState->embeddedConnection.hPipe, BURN_EMBEDDED_MESSAGE_TYPE_CUSTOM, pbData, cbData, NULL, NULL, &dwResult);
402+
ExitOnFailure(hr, "Failed to send embedded custom message over pipe.");
403+
404+
*pnResult = static_cast<int>(dwResult);
405+
406+
LExit:
407+
ReleaseBuffer(pbData);
408+
return hr;
409+
}
410+
373411
virtual STDMETHODIMP SetUpdate(
374412
__in_z_opt LPCWSTR wzLocalSource,
375413
__in_z_opt LPCWSTR wzDownloadSource,

src/burn/engine/apply.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2492,6 +2492,10 @@ static int GenericExecuteMessageHandler(
24922492
case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE:
24932493
nResult = pContext->pUX->pUserExperience->OnExecuteFilesInUse(pContext->pExecutingPackage->sczId, pMessage->filesInUse.cFiles, pMessage->filesInUse.rgwzFiles);
24942494
break;
2495+
2496+
case GENERIC_EXECUTE_MESSAGE_CUSTOM:
2497+
nResult = pContext->pUX->pUserExperience->OnEmbeddedCustomMessage(pContext->pExecutingPackage->sczId, pMessage->custom.dwCode, pMessage->custom.wzMessage);
2498+
break;
24952499
}
24962500

24972501
nResult = UserExperienceCheckExecuteResult(pContext->pUX, pContext->fRollback, pMessage->dwAllowedResults, nResult);

src/burn/engine/apply.h

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum GENERIC_EXECUTE_MESSAGE_TYPE
1313
GENERIC_EXECUTE_MESSAGE_ERROR,
1414
GENERIC_EXECUTE_MESSAGE_PROGRESS,
1515
GENERIC_EXECUTE_MESSAGE_FILES_IN_USE,
16+
GENERIC_EXECUTE_MESSAGE_CUSTOM,
1617
};
1718

1819
typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA
@@ -43,6 +44,11 @@ typedef struct _GENERIC_EXECUTE_MESSAGE
4344
DWORD cFiles;
4445
LPCWSTR* rgwzFiles;
4546
} filesInUse;
47+
struct
48+
{
49+
DWORD dwCode;
50+
LPCWSTR wzMessage;
51+
} custom;
4652
};
4753
} GENERIC_EXECUTE_MESSAGE;
4854

src/burn/engine/core.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,17 @@ static HRESULT ParseCommandLine(
14301430

14311431
i += 2;
14321432
}
1433+
else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED_CAPABILITIES, -1))
1434+
{
1435+
if (i + 1 >= argc)
1436+
{
1437+
ExitOnRootFailure(hr = E_INVALIDARG, "Must specify the embedded capabilities.");
1438+
}
1439+
++i;
1440+
1441+
hr = StrStringToUInt32(argv[i], 0, reinterpret_cast<UINT*>(&pEmbeddedConnection->dwCapabilities));
1442+
ExitOnFailure(hr, "Failed to parse parent pipe capabilities.");
1443+
}
14331444
else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DETECT, -1))
14341445
{
14351446
pCommand->relationType = BOOTSTRAPPER_RELATION_DETECT;

src/burn/engine/core.h

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT_NONE = L"parent:none";
1616
const LPCWSTR BURN_COMMANDLINE_SWITCH_CLEAN_ROOM = L"burn.clean.room";
1717
const LPCWSTR BURN_COMMANDLINE_SWITCH_ELEVATED = L"burn.elevated";
1818
const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED = L"burn.embedded";
19+
const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED_CAPABILITIES = L"burn.embedded.capabilities";
1920
const LPCWSTR BURN_COMMANDLINE_SWITCH_RUNONCE = L"burn.runonce";
2021
const LPCWSTR BURN_COMMANDLINE_SWITCH_LOG_APPEND = L"burn.log.append";
2122
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DETECT = L"burn.related.detect";

src/burn/engine/elevation.cpp

+27-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
3737

3838
BURN_ELEVATION_TRANSACTION_BEGIN,
3939
BURN_ELEVATION_TRANSACTION_COMMIT,
40-
BURN_ELEVATION_TRANSACTION_ROLLBACK
40+
BURN_ELEVATION_TRANSACTION_ROLLBACK,
41+
42+
BURN_ELEVATION_MESSAGE_TYPE_EMBEDDED_CUSTOM,
4143

4244
} BURN_ELEVATION_MESSAGE_TYPE;
4345

@@ -1378,6 +1380,19 @@ static HRESULT ProcessGenericExecuteMessages(
13781380
message.error.wzMessage = sczMessage;
13791381
break;
13801382

1383+
case BURN_ELEVATION_MESSAGE_TYPE_EMBEDDED_CUSTOM:
1384+
message.type = GENERIC_EXECUTE_MESSAGE_CUSTOM;
1385+
message.dwAllowedResults = 0xFFFFFFFF;
1386+
1387+
hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.custom.dwCode);
1388+
ExitOnFailure(hr, "Failed to read custom code from buffer.");
1389+
1390+
hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage);
1391+
ExitOnFailure(hr, "Failed to read custom message from buffer.");
1392+
1393+
message.custom.wzMessage = sczMessage;
1394+
break;
1395+
13811396
case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE:
13821397
message.type = GENERIC_EXECUTE_MESSAGE_FILES_IN_USE;
13831398

@@ -2681,6 +2696,17 @@ static int GenericExecuteMessageHandler(
26812696
dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR;
26822697
break;
26832698

2699+
case GENERIC_EXECUTE_MESSAGE_CUSTOM:
2700+
// serialize message data
2701+
hr = BuffWriteNumber(&pbData, &cbData, pMessage->custom.dwCode);
2702+
ExitOnFailure(hr, "Failed to write code to message buffer.");
2703+
2704+
hr = BuffWriteString(&pbData, &cbData, pMessage->custom.wzMessage);
2705+
ExitOnFailure(hr, "Failed to write message to message buffer.");
2706+
2707+
dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EMBEDDED_CUSTOM;
2708+
break;
2709+
26842710
case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE:
26852711
hr = BuffWriteNumber(&pbData, &cbData, pMessage->filesInUse.cFiles);
26862712
ExitOnFailure(hr, "Failed to count of files in use to message buffer.");

src/burn/engine/embedded.cpp

+45-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ static HRESULT OnEmbeddedProgress(
3232
__in DWORD cbData,
3333
__out DWORD* pdwResult
3434
);
35+
static HRESULT OnEmbeddedCustomMessage(
36+
__in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
37+
__in LPVOID pvContext,
38+
__in_bcount(cbData) BYTE* pbData,
39+
__in DWORD cbData,
40+
__out DWORD* pdwResult
41+
);
3542

3643
// function definitions
3744

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

71-
hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
78+
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);
7279
ExitOnFailure(hr, "Failed to allocate embedded command.");
7380

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

137+
case BURN_EMBEDDED_MESSAGE_TYPE_CUSTOM:
138+
hr = OnEmbeddedCustomMessage(pContext->pfnGenericMessageHandler, pContext->pvContext, static_cast<BYTE*>(pMsg->pvData), pMsg->cbData, &dwResult);
139+
ExitOnFailure(hr, "Failed to process embedded custom message.");
140+
break;
141+
130142
default:
131143
hr = E_INVALIDARG;
132144
ExitOnRootFailure1(hr, "Unexpected embedded message sent to child process, msg: %u", pMsg->dwMessage);
@@ -172,6 +184,38 @@ static HRESULT OnEmbeddedErrorMessage(
172184
return hr;
173185
}
174186

187+
static HRESULT OnEmbeddedCustomMessage(
188+
__in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
189+
__in LPVOID pvContext,
190+
__in_bcount(cbData) BYTE* pbData,
191+
__in DWORD cbData,
192+
__out DWORD* pdwResult
193+
)
194+
{
195+
HRESULT hr = S_OK;
196+
DWORD iData = 0;
197+
GENERIC_EXECUTE_MESSAGE message = { };
198+
LPWSTR sczMessage = NULL;
199+
200+
message.type = GENERIC_EXECUTE_MESSAGE_CUSTOM;
201+
message.dwAllowedResults = 0xFFFFFFFF;
202+
203+
hr = BuffReadNumber(pbData, cbData, &iData, &message.custom.dwCode);
204+
ExitOnFailure(hr, "Failed to read custom code from buffer.");
205+
206+
hr = BuffReadString(pbData, cbData, &iData, &sczMessage);
207+
ExitOnFailure(hr, "Failed to read custom message from buffer.");
208+
209+
message.custom.wzMessage = sczMessage;
210+
211+
*pdwResult = (DWORD)pfnMessageHandler(&message, pvContext);
212+
213+
LExit:
214+
ReleaseStr(sczMessage);
215+
216+
return hr;
217+
}
218+
175219
static HRESULT OnEmbeddedProgress(
176220
__in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
177221
__in LPVOID pvContext,

src/burn/engine/embedded.h

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ typedef enum _BURN_EMBEDDED_MESSAGE_TYPE
1111
BURN_EMBEDDED_MESSAGE_TYPE_UNKNOWN,
1212
BURN_EMBEDDED_MESSAGE_TYPE_ERROR,
1313
BURN_EMBEDDED_MESSAGE_TYPE_PROGRESS,
14+
BURN_EMBEDDED_MESSAGE_TYPE_CUSTOM = 1000, // Allow enough room for standard WiX values
1415
} BURN_EMBEDDED_MESSAGE_TYPE;
1516

1617

src/burn/engine/pipe.h

+11
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,22 @@
66
extern "C" {
77
#endif
88

9+
10+
enum BURN_PIPE_CAPABILITIES
11+
{
12+
BURN_PIPE_CAPABILITIES_NONE = 0,
13+
BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE = 1,
14+
15+
// All the capabilities that this engine supports, used when creating capabilities command line for the embedded bundle
16+
BURN_PIPE_CAPABILITIES_ALL = BURN_PIPE_CAPABILITIES_CUSTOM_MESSAGE,
17+
};
18+
919
typedef struct _BURN_PIPE_CONNECTION
1020
{
1121
LPWSTR sczName;
1222
LPWSTR sczSecret;
1323
DWORD dwProcessId;
24+
DWORD dwCapabilities; // Capabilities of the engine that created the pipe
1425

1526
HANDLE hProcess;
1627
HANDLE hPipe;

src/burn/inc/IBootstrapperApplication.h

+10
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,16 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
725725
__in DWORD cFiles,
726726
__in_ecount_z(cFiles) LPCWSTR* rgwzFiles
727727
) = 0;
728+
729+
// OnEmbeddedCustomMessage - called when an embedded burn package send a SendEmbeddedCustomMessage(...).
730+
//
731+
// Return:
732+
// Any code that the sender and recipient agree on.
733+
STDMETHOD_(int, OnEmbeddedCustomMessage)(
734+
__in_z LPCWSTR wzPackageId,
735+
__in DWORD dwCode,
736+
__in_z LPCWSTR wzMessage
737+
) = 0;
728738

729739
// OnExecutePackageComplete - called when a package execution is complete.
730740
//

src/burn/inc/IBootstrapperEngine.h

+6
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperEngine, IUnknown, "6480D616-27A0-44D7-905B-8
158158
__out int* pnResult
159159
) = 0;
160160

161+
STDMETHOD(SendEmbeddedCustomMessage)(
162+
__in DWORD dwCode,
163+
__in_z_opt LPCWSTR wzMessage,
164+
__out int* pnResult
165+
) = 0;
166+
161167
STDMETHOD(SetUpdate)(
162168
__in_z_opt LPCWSTR wzLocalSource,
163169
__in_z_opt LPCWSTR wzDownloadSource,

src/ext/BalExtension/mba/core/BootstrapperApplication.cs

+26
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ protected BootstrapperApplication()
315315
/// </summary>
316316
public event EventHandler<ExecuteFilesInUseEventArgs> ExecuteFilesInUse;
317317

318+
/// <summary>
319+
/// Fired when an embedded burn package sends a SendEmbeddedCustomMessage(...)
320+
/// </summary>
321+
public event EventHandler<EmbeddedCustomMessageEventArgs> EmbeddedCustomMessage;
322+
318323
/// <summary>
319324
/// Fired when the engine has completed installing a specific package.
320325
/// </summary>
@@ -1141,6 +1146,19 @@ protected virtual void OnExecuteFilesInUse(ExecuteFilesInUseEventArgs args)
11411146
}
11421147
}
11431148

1149+
/// <summary>
1150+
/// Called when an embedded burn package sends a SendEmbeddedCustomMessage(...).
1151+
/// </summary>
1152+
/// <param name="args">Additional arguments for this event.</param>
1153+
protected virtual void OnEmbeddedCustomMessage(EmbeddedCustomMessageEventArgs args)
1154+
{
1155+
EventHandler<EmbeddedCustomMessageEventArgs> handler = this.EmbeddedCustomMessage;
1156+
if (null != handler)
1157+
{
1158+
handler(this, args);
1159+
}
1160+
}
1161+
11441162
/// <summary>
11451163
/// Called when the engine has completed installing a specific package.
11461164
/// </summary>
@@ -1638,6 +1656,14 @@ Result IBootstrapperApplication.OnExecuteFilesInUse(string wzPackageId, int cFil
16381656
return args.Result;
16391657
}
16401658

1659+
Result IBootstrapperApplication.OnEmbeddedCustomMessage(string wzPackageId, int dwCode, string wzMessage)
1660+
{
1661+
EmbeddedCustomMessageEventArgs args = new EmbeddedCustomMessageEventArgs(wzPackageId, dwCode, wzMessage);
1662+
this.OnEmbeddedCustomMessage(args);
1663+
1664+
return args.Result;
1665+
}
1666+
16411667
Result IBootstrapperApplication.OnExecutePackageComplete(string wzPackageId, int hrExitCode, ApplyRestart restart, int nRecommendation)
16421668
{
16431669
ExecutePackageCompleteEventArgs args = new ExecutePackageCompleteEventArgs(wzPackageId, hrExitCode, restart, nRecommendation);

src/ext/BalExtension/mba/core/Engine.cs

+15
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,21 @@ public int SendEmbeddedProgress(int progressPercentage, int overallPercentage)
440440
return result;
441441
}
442442

443+
/// <summary>
444+
/// Sends a custom embedded message.
445+
/// </summary>
446+
/// <param name="code">Custom message code.</param>
447+
/// <param name="message">Optional text.</param>
448+
/// <exception cref="System.NotSupportedException">
449+
/// Thrown when the parent burn engine does not support receiving custom messages
450+
/// </exception>
451+
public int SendEmbeddedCustomMessage(int code, string message)
452+
{
453+
int result = 0;
454+
this.engine.SendEmbeddedCustomMessage(code, message, out result);
455+
return result;
456+
}
457+
443458
/// <summary>
444459
/// Shuts down the engine.
445460
/// </summary>

0 commit comments

Comments
 (0)