aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/embedded.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/embedded.cpp')
-rw-r--r--src/burn/engine/embedded.cpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/src/burn/engine/embedded.cpp b/src/burn/engine/embedded.cpp
new file mode 100644
index 00000000..03898ebd
--- /dev/null
+++ b/src/burn/engine/embedded.cpp
@@ -0,0 +1,197 @@
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#include "precomp.h"
4
5
6// struct
7
8struct BURN_EMBEDDED_CALLBACK_CONTEXT
9{
10 PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler;
11 LPVOID pvContext;
12};
13
14// internal function declarations
15
16static HRESULT ProcessEmbeddedMessages(
17 __in BURN_PIPE_MESSAGE* pMsg,
18 __in_opt LPVOID pvContext,
19 __out DWORD* pdwResult
20 );
21static HRESULT OnEmbeddedErrorMessage(
22 __in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
23 __in LPVOID pvContext,
24 __in_bcount(cbData) BYTE* pbData,
25 __in SIZE_T cbData,
26 __out DWORD* pdwResult
27 );
28static HRESULT OnEmbeddedProgress(
29 __in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
30 __in LPVOID pvContext,
31 __in_bcount(cbData) BYTE* pbData,
32 __in SIZE_T cbData,
33 __out DWORD* pdwResult
34 );
35
36// function definitions
37
38/*******************************************************************
39 EmbeddedLaunchChildProcess -
40
41*******************************************************************/
42extern "C" HRESULT EmbeddedRunBundle(
43 __in LPCWSTR wzExecutablePath,
44 __in LPCWSTR wzArguments,
45 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
46 __in LPVOID pvContext,
47 __out DWORD* pdwExitCode
48 )
49{
50 HRESULT hr = S_OK;
51 DWORD dwCurrentProcessId = ::GetCurrentProcessId();
52 HANDLE hCreatedPipesEvent = NULL;
53 LPWSTR sczCommand = NULL;
54 STARTUPINFOW si = { };
55 PROCESS_INFORMATION pi = { };
56 BURN_PIPE_RESULT result = { };
57
58 BURN_PIPE_CONNECTION connection = { };
59 PipeConnectionInitialize(&connection);
60
61 BURN_EMBEDDED_CALLBACK_CONTEXT context = { };
62 context.pfnGenericMessageHandler = pfnGenericMessageHandler;
63 context.pvContext = pvContext;
64
65 hr = PipeCreateNameAndSecret(&connection.sczName, &connection.sczSecret);
66 ExitOnFailure(hr, "Failed to create embedded pipe name and client token.");
67
68 hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent);
69 ExitOnFailure(hr, "Failed to create embedded pipe.");
70
71 hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
72 ExitOnFailure(hr, "Failed to allocate embedded command.");
73
74 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
75 {
76 ExitWithLastError(hr, "Failed to create embedded process at path: %ls", wzExecutablePath);
77 }
78
79 connection.dwProcessId = ::GetProcessId(pi.hProcess);
80 connection.hProcess = pi.hProcess;
81 pi.hProcess = NULL;
82
83 hr = PipeWaitForChildConnect(&connection);
84 ExitOnFailure(hr, "Failed to wait for embedded process to connect to pipe.");
85
86 hr = PipePumpMessages(connection.hPipe, ProcessEmbeddedMessages, &context, &result);
87 ExitOnFailure(hr, "Failed to process messages from embedded message.");
88
89 // Get the return code from the embedded process.
90 hr = ProcWaitForCompletion(connection.hProcess, INFINITE, pdwExitCode);
91 ExitOnFailure(hr, "Failed to wait for embedded executable: %ls", wzExecutablePath);
92
93LExit:
94 ReleaseHandle(pi.hThread);
95 ReleaseHandle(pi.hProcess);
96
97 StrSecureZeroFreeString(sczCommand);
98 ReleaseHandle(hCreatedPipesEvent);
99 PipeConnectionUninitialize(&connection);
100
101 return hr;
102}
103
104
105// internal function definitions
106
107static HRESULT ProcessEmbeddedMessages(
108 __in BURN_PIPE_MESSAGE* pMsg,
109 __in_opt LPVOID pvContext,
110 __out DWORD* pdwResult
111 )
112{
113 HRESULT hr = S_OK;
114 BURN_EMBEDDED_CALLBACK_CONTEXT* pContext = static_cast<BURN_EMBEDDED_CALLBACK_CONTEXT*>(pvContext);
115 DWORD dwResult = 0;
116
117 // Process the message.
118 switch (pMsg->dwMessage)
119 {
120 case BURN_EMBEDDED_MESSAGE_TYPE_ERROR:
121 hr = OnEmbeddedErrorMessage(pContext->pfnGenericMessageHandler, pContext->pvContext, static_cast<BYTE*>(pMsg->pvData), pMsg->cbData, &dwResult);
122 ExitOnFailure(hr, "Failed to process embedded error message.");
123 break;
124
125 case BURN_EMBEDDED_MESSAGE_TYPE_PROGRESS:
126 hr = OnEmbeddedProgress(pContext->pfnGenericMessageHandler, pContext->pvContext, static_cast<BYTE*>(pMsg->pvData), pMsg->cbData, &dwResult);
127 ExitOnFailure(hr, "Failed to process embedded progress message.");
128 break;
129
130 default:
131 hr = E_INVALIDARG;
132 ExitOnRootFailure(hr, "Unexpected embedded message sent to child process, msg: %u", pMsg->dwMessage);
133 }
134
135 *pdwResult = dwResult;
136
137LExit:
138 return hr;
139}
140
141static HRESULT OnEmbeddedErrorMessage(
142 __in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
143 __in LPVOID pvContext,
144 __in_bcount(cbData) BYTE* pbData,
145 __in SIZE_T cbData,
146 __out DWORD* pdwResult
147 )
148{
149 HRESULT hr = S_OK;
150 SIZE_T iData = 0;
151 GENERIC_EXECUTE_MESSAGE message = { };
152 LPWSTR sczMessage = NULL;
153
154 message.type = GENERIC_EXECUTE_MESSAGE_ERROR;
155
156 hr = BuffReadNumber(pbData, cbData, &iData, &message.error.dwErrorCode);
157 ExitOnFailure(hr, "Failed to read error code from buffer.");
158
159 hr = BuffReadString(pbData, cbData, &iData, &sczMessage);
160 ExitOnFailure(hr, "Failed to read error message from buffer.");
161
162 message.error.wzMessage = sczMessage;
163
164 hr = BuffReadNumber(pbData, cbData, &iData, &message.dwAllowedResults);
165 ExitOnFailure(hr, "Failed to read UI hint from buffer.");
166
167 *pdwResult = (DWORD)pfnMessageHandler(&message, pvContext);
168
169LExit:
170 ReleaseStr(sczMessage);
171
172 return hr;
173}
174
175static HRESULT OnEmbeddedProgress(
176 __in PFN_GENERICMESSAGEHANDLER pfnMessageHandler,
177 __in LPVOID pvContext,
178 __in_bcount(cbData) BYTE* pbData,
179 __in SIZE_T cbData,
180 __out DWORD* pdwResult
181 )
182{
183 HRESULT hr = S_OK;
184 SIZE_T iData = 0;
185 GENERIC_EXECUTE_MESSAGE message = { };
186
187 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
188 message.dwAllowedResults = MB_OKCANCEL;
189
190 hr = BuffReadNumber(pbData, cbData, &iData, &message.progress.dwPercentage);
191 ExitOnFailure(hr, "Failed to read progress from buffer.");
192
193 *pdwResult = (DWORD)pfnMessageHandler(&message, pvContext);
194
195LExit:
196 return hr;
197}