aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/pipeutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/pipeutil.cpp351
1 files changed, 306 insertions, 45 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp b/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp
index 4aa69d56..8d0a5ed0 100644
--- a/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/pipeutil.cpp
@@ -5,7 +5,7 @@
5 5
6static const DWORD PIPE_64KB = 64 * 1024; 6static const DWORD PIPE_64KB = 64 * 1024;
7static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls"; 7static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls";
8 8static const DWORD PIPE_MESSAGE_DISCONNECT = 0xFFFFFFFF;
9 9
10// Exit macros 10// Exit macros
11#define PipeExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_PIPEUTIL, x, s, __VA_ARGS__) 11#define PipeExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_PIPEUTIL, x, s, __VA_ARGS__)
@@ -113,8 +113,19 @@ DAPI_(void) PipeFreeMessage(
113 ReleaseNullMem(pMsg->pvData); 113 ReleaseNullMem(pMsg->pvData);
114 pMsg->fAllocatedData = FALSE; 114 pMsg->fAllocatedData = FALSE;
115 } 115 }
116
117 ZeroMemory(pMsg, sizeof(PIPE_MESSAGE));
116} 118}
117 119
120DAPI_(void) PipeFreeRpcResult(
121 __in PIPE_RPC_RESULT* pResult
122)
123{
124 if (pResult->pbData)
125 {
126 ReleaseNullMem(pResult->pbData);
127 }
128}
118 129
119DAPI_(HRESULT) PipeOpen( 130DAPI_(HRESULT) PipeOpen(
120 __in_z LPCWSTR wzName, 131 __in_z LPCWSTR wzName,
@@ -166,39 +177,281 @@ DAPI_(HRESULT) PipeReadMessage(
166) 177)
167{ 178{
168 HRESULT hr = S_OK; 179 HRESULT hr = S_OK;
169 BYTE pbMessageIdAndByteCount[sizeof(DWORD) + sizeof(DWORD)] = { }; 180 DWORD rgdwMessageIdAndByteCount[2] = { };
181 LPBYTE pbData = NULL;
182 DWORD cbData = 0;
170 183
171 hr = FileReadHandle(hPipe, pbMessageIdAndByteCount, sizeof(pbMessageIdAndByteCount)); 184 hr = FileReadHandle(hPipe, reinterpret_cast<LPBYTE>(rgdwMessageIdAndByteCount), sizeof(rgdwMessageIdAndByteCount));
172 if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE) == hr) 185 if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE) == hr)
173 { 186 {
174 memset(pbMessageIdAndByteCount, 0, sizeof(pbMessageIdAndByteCount)); 187 memset(rgdwMessageIdAndByteCount, 0, sizeof(rgdwMessageIdAndByteCount));
175 hr = S_FALSE; 188 hr = S_FALSE;
176 } 189 }
177 PipeExitOnFailure(hr, "Failed to read message from pipe."); 190 PipeExitOnFailure(hr, "Failed to read message from pipe.");
178 191
179 pMsg->dwMessageType = *(DWORD*)(pbMessageIdAndByteCount); 192 Trace(REPORT_STANDARD, "RPC pipe %p read message: %u recv cbData: %u", hPipe, rgdwMessageIdAndByteCount[0], rgdwMessageIdAndByteCount[1]);
180 pMsg->cbData = *(DWORD*)(pbMessageIdAndByteCount + sizeof(DWORD)); 193
181 if (pMsg->cbData) 194 cbData = rgdwMessageIdAndByteCount[1];
195 if (cbData)
182 { 196 {
183 pMsg->pvData = MemAlloc(pMsg->cbData, FALSE); 197 pbData = reinterpret_cast<LPBYTE>(MemAlloc(cbData, FALSE));
184 PipeExitOnNull(pMsg->pvData, hr, E_OUTOFMEMORY, "Failed to allocate data for message."); 198 PipeExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate data for message.");
185 199
186 hr = FileReadHandle(hPipe, reinterpret_cast<LPBYTE>(pMsg->pvData), pMsg->cbData); 200 hr = FileReadHandle(hPipe, pbData, cbData);
187 PipeExitOnFailure(hr, "Failed to read data for message."); 201 PipeExitOnFailure(hr, "Failed to read data for message.");
202 }
203
204 pMsg->dwMessageType = rgdwMessageIdAndByteCount[0];
205 pMsg->cbData = cbData;
206 pMsg->pvData = pbData;
207 pbData = NULL;
208
209 if (PIPE_MESSAGE_DISCONNECT == pMsg->dwMessageType)
210 {
211 hr = S_FALSE;
212 }
213
214LExit:
215 ReleaseMem(pbData);
216
217 return hr;
218}
219
220DAPI_(void) PipeRpcInitialize(
221 __in PIPE_RPC_HANDLE* phRpcPipe,
222 __in HANDLE hPipe,
223 __in BOOL fTakeHandleOwnership
224)
225{
226 phRpcPipe->hPipe = hPipe;
227 if (phRpcPipe->hPipe != INVALID_HANDLE_VALUE)
228 {
229 ::InitializeCriticalSection(&phRpcPipe->cs);
230 phRpcPipe->fOwnHandle = fTakeHandleOwnership;
231 phRpcPipe->fInitialized = TRUE;
232 }
233}
234
235DAPI_(BOOL) PipeRpcInitialized(
236 __in PIPE_RPC_HANDLE* phRpcPipe
237)
238{
239 return phRpcPipe->fInitialized && phRpcPipe->hPipe != INVALID_HANDLE_VALUE;
240}
241
242DAPI_(void) PipeRpcUninitiailize(
243 __in PIPE_RPC_HANDLE* phRpcPipe
244)
245{
246 if (phRpcPipe->fInitialized)
247 {
248 ::DeleteCriticalSection(&phRpcPipe->cs);
249
250 if (phRpcPipe->fOwnHandle)
251 {
252 ::CloseHandle(phRpcPipe->hPipe);
253 }
254
255 phRpcPipe->hPipe = INVALID_HANDLE_VALUE;
256 phRpcPipe->fOwnHandle = FALSE;
257 phRpcPipe->fInitialized = FALSE;
258 }
259}
260
261DAPI_(HRESULT) PipeRpcReadMessage(
262 __in PIPE_RPC_HANDLE* phRpcPipe,
263 __in PIPE_MESSAGE* pMsg
264)
265{
266 HRESULT hr = S_OK;
267
268 ::EnterCriticalSection(&phRpcPipe->cs);
269
270 hr = PipeReadMessage(phRpcPipe->hPipe, pMsg);
271 PipeExitOnFailure(hr, "Failed to read message from RPC pipe.");
272
273LExit:
274 ::LeaveCriticalSection(&phRpcPipe->cs);
275
276 return hr;
277}
278
279DAPI_(HRESULT) PipeRpcRequest(
280 __in PIPE_RPC_HANDLE* phRpcPipe,
281 __in DWORD dwMessageType,
282 __in_bcount(cbArgs) LPVOID pvArgs,
283 __in SIZE_T cbArgs,
284 __in PIPE_RPC_RESULT* pResult
285)
286{
287 HRESULT hr = S_OK;
288 HANDLE hPipe = phRpcPipe->hPipe;
289 BOOL fLocked = FALSE;
290 DWORD rgResultAndDataSize[2] = { };
291 DWORD cbData = 0;
292 LPBYTE pbData = NULL;
293
294 if (hPipe == INVALID_HANDLE_VALUE)
295 {
296 ExitFunction();
297 }
298
299 Trace(REPORT_STANDARD, "RPC pipe %p request message: %d send cbArgs: %u", hPipe, dwMessageType, cbArgs);
300
301 ::EnterCriticalSection(&phRpcPipe->cs);
302 fLocked = TRUE;
303
304 // Send the message.
305 hr = PipeRpcWriteMessage(phRpcPipe, dwMessageType, pvArgs, cbArgs);
306 PipeExitOnFailure(hr, "Failed to send RPC pipe request.");
307
308 // Read the result and size of response data.
309 hr = FileReadHandle(hPipe, reinterpret_cast<LPBYTE>(rgResultAndDataSize), sizeof(rgResultAndDataSize));
310 PipeExitOnFailure(hr, "Failed to read result and size of message.");
311
312 pResult->hr = rgResultAndDataSize[0];
313 cbData = rgResultAndDataSize[1];
314
315 Trace(REPORT_STANDARD, "RPC pipe %p request message: %d returned hr: 0x%x, cbData: %u", hPipe, dwMessageType, pResult->hr, cbData);
316 AssertSz(FAILED(pResult->hr) || pResult->hr == S_OK || pResult->hr == S_FALSE, "Unexpected HRESULT from RPC pipe request.");
317
318 if (cbData)
319 {
320 pbData = reinterpret_cast<LPBYTE>(MemAlloc(cbData, TRUE));
321 PipeExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory for RPC pipe results.");
322
323 hr = FileReadHandle(hPipe, pbData, cbData);
324 PipeExitOnFailure(hr, "Failed to read result data.");
325 }
326
327 pResult->cbData = cbData;
328 pResult->pbData = pbData;
329 pbData = NULL;
330
331 hr = pResult->hr;
332 PipeExitOnFailure(hr, "RPC pipe client reported failure.");
333
334LExit:
335 ReleaseMem(pbData);
336
337 if (fLocked)
338 {
339 ::LeaveCriticalSection(&phRpcPipe->cs);
340 }
341
342 return hr;
343}
344
345DAPI_(HRESULT) PipeRpcResponse(
346 __in PIPE_RPC_HANDLE* phRpcPipe,
347 __in DWORD
348#if DEBUG
349 dwMessageType
350#endif
351 ,
352 __in HRESULT hrResult,
353 __in_bcount(cbResult) LPVOID pvResult,
354 __in SIZE_T cbResult
355 )
356{
357 HRESULT hr = S_OK;
358 HANDLE hPipe = phRpcPipe->hPipe;
359 DWORD dwcbResult = 0;
360
361 hr = DutilSizetToDword(pvResult ? cbResult : 0, &dwcbResult);
362 PipeExitOnFailure(hr, "Pipe message is too large.");
363
364 Trace(REPORT_STANDARD, "RPC pipe %p response message: %d returned hr: 0x%x, cbResult: %u", hPipe, dwMessageType, hrResult, dwcbResult);
188 365
189 pMsg->fAllocatedData = TRUE; 366 ::EnterCriticalSection(&phRpcPipe->cs);
367
368 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(&hrResult), sizeof(hrResult));
369 PipeExitOnFailure(hr, "Failed to write RPC result code to pipe.");
370
371 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(&dwcbResult), sizeof(dwcbResult));
372 PipeExitOnFailure(hr, "Failed to write RPC result size to pipe.");
373
374 if (dwcbResult)
375 {
376 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(pvResult), dwcbResult);
377 PipeExitOnFailure(hr, "Failed to write RPC result data to pipe.");
190 } 378 }
191 379
192LExit: 380LExit:
193 if (!pMsg->fAllocatedData && pMsg->pvData) 381 ::LeaveCriticalSection(&phRpcPipe->cs);
382
383 return hr;
384}
385
386DAPI_(HRESULT) PipeRpcWriteMessage(
387 __in PIPE_RPC_HANDLE* phRpcPipe,
388 __in DWORD dwMessageType,
389 __in_bcount_opt(cbData) LPVOID pvData,
390 __in SIZE_T cbData
391)
392{
393 HRESULT hr = S_OK;
394
395 ::EnterCriticalSection(&phRpcPipe->cs);
396
397 hr = PipeWriteMessage(phRpcPipe->hPipe, dwMessageType, pvData, cbData);
398 PipeExitOnFailure(hr, "Failed to write message type to RPC pipe.");
399
400LExit:
401 ::LeaveCriticalSection(&phRpcPipe->cs);
402
403 return hr;
404}
405
406DAPI_(HRESULT) PipeRpcWriteMessageReadResponse(
407 __in PIPE_RPC_HANDLE* phRpcPipe,
408 __in DWORD dwMessageType,
409 __in_bcount_opt(cbData) LPBYTE pbArgData,
410 __in SIZE_T cbArgData,
411 __in PIPE_RPC_RESULT* pResult
412)
413{
414 HRESULT hr = S_OK;
415 DWORD rgResultAndSize[2] = { };
416 LPBYTE pbResultData = NULL;
417 DWORD cbResultData = 0;
418
419 hr = PipeWriteMessage(phRpcPipe->hPipe, dwMessageType, pbArgData, cbArgData);
420 PipeExitOnFailure(hr, "Failed to write message type to RPC pipe.");
421
422 // Read the result and size of response.
423 hr = FileReadHandle(phRpcPipe->hPipe, reinterpret_cast<LPBYTE>(rgResultAndSize), sizeof(rgResultAndSize));
424 ExitOnFailure(hr, "Failed to read result and size of message.");
425
426 pResult->hr = rgResultAndSize[0];
427 cbResultData = rgResultAndSize[1];
428
429 if (cbResultData)
194 { 430 {
195 MemFree(pMsg->pvData); 431 pbResultData = reinterpret_cast<LPBYTE>(MemAlloc(cbResultData, TRUE));
432 ExitOnNull(pbResultData, hr, E_OUTOFMEMORY, "Failed to allocate memory for BA results.");
433
434 hr = FileReadHandle(phRpcPipe->hPipe, pbResultData, cbResultData);
435 ExitOnFailure(hr, "Failed to read result and size of message.");
196 } 436 }
197 437
438 pResult->cbData = cbResultData;
439 pResult->pbData = pbResultData;
440 pbResultData = NULL;
441
442 hr = pResult->hr;
443 ExitOnFailure(hr, "BA reported failure.");
444
445LExit:
446 ReleaseMem(pbResultData);
447
448 ::LeaveCriticalSection(&phRpcPipe->cs);
449
198 return hr; 450 return hr;
199} 451}
200 452
201DAPI_(HRESULT) PipeServerWaitForClientConnect( 453DAPI_(HRESULT) PipeServerWaitForClientConnect(
454 __in HANDLE hClientProcess,
202 __in HANDLE hPipe 455 __in HANDLE hPipe
203) 456)
204{ 457{
@@ -206,13 +459,13 @@ DAPI_(HRESULT) PipeServerWaitForClientConnect(
206 DWORD dwPipeState = PIPE_READMODE_BYTE | PIPE_NOWAIT; 459 DWORD dwPipeState = PIPE_READMODE_BYTE | PIPE_NOWAIT;
207 460
208 // Temporarily make the pipe non-blocking so we will not get stuck in ::ConnectNamedPipe() forever 461 // Temporarily make the pipe non-blocking so we will not get stuck in ::ConnectNamedPipe() forever
209 // if the child decides not to show up. 462 // if the client decides not to show up.
210 if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL)) 463 if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL))
211 { 464 {
212 PipeExitWithLastError(hr, "Failed to set pipe to non-blocking."); 465 PipeExitWithLastError(hr, "Failed to set pipe to non-blocking.");
213 } 466 }
214 467
215 // Loop for a while waiting for a connection from child process. 468 // Loop for a while waiting for a connection from client process.
216 DWORD cRetry = 0; 469 DWORD cRetry = 0;
217 do 470 do
218 { 471 {
@@ -237,7 +490,19 @@ DAPI_(HRESULT) PipeServerWaitForClientConnect(
237 } 490 }
238 491
239 ++cRetry; 492 ++cRetry;
240 ::Sleep(PIPE_WAIT_FOR_CONNECTION); 493
494 // Ensure the client is still around.
495 hr = ::AppWaitForSingleObject(hClientProcess, PIPE_WAIT_FOR_CONNECTION);
496 if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr)
497 {
498 // Timeout out means the process is still there, that's good.
499 hr = HRESULT_FROM_WIN32(ERROR_PIPE_LISTENING);
500 }
501 else if (SUCCEEDED(hr))
502 {
503 // Success means the process is gone, that's bad.
504 hr = HRESULT_FROM_WIN32(WAIT_ABANDONED);
505 }
241 } 506 }
242 else 507 else
243 { 508 {
@@ -259,6 +524,26 @@ LExit:
259 return hr; 524 return hr;
260} 525}
261 526
527DAPI_(HRESULT) PipeWriteDisconnect(
528 __in HANDLE hPipe
529 )
530{
531 HRESULT hr = S_OK;
532 LPVOID pv = NULL;
533 SIZE_T cb = 0;
534
535 hr = AllocatePipeMessage(PIPE_MESSAGE_DISCONNECT, NULL, 0, &pv, &cb);
536 ExitOnFailure(hr, "Failed to allocate message to write.");
537
538 // Write the message.
539 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(pv), cb);
540 ExitOnFailure(hr, "Failed to write message type to pipe.");
541
542LExit:
543 ReleaseMem(pv);
544 return hr;
545}
546
262DAPI_(HRESULT) PipeWriteMessage( 547DAPI_(HRESULT) PipeWriteMessage(
263 __in HANDLE hPipe, 548 __in HANDLE hPipe,
264 __in DWORD dwMessageType, 549 __in DWORD dwMessageType,
@@ -266,22 +551,6 @@ DAPI_(HRESULT) PipeWriteMessage(
266 __in SIZE_T cbData 551 __in SIZE_T cbData
267) 552)
268{ 553{
269// HRESULT hr = S_OK;
270//
271// hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(&dwMessageType), sizeof(dwMessageType));
272// PipeExitOnFailure(hr, "Failed to write message id to pipe.");
273//
274// hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(&cbData), sizeof(cbData));
275// PipeExitOnFailure(hr, "Failed to write message data size to pipe.");
276//
277// if (pvData && cbData)
278// {
279// hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(pvData), cbData);
280// PipeExitOnFailure(hr, "Failed to write message data to pipe.");
281// }
282//
283//LExit:
284// return hr;
285 HRESULT hr = S_OK; 554 HRESULT hr = S_OK;
286 LPVOID pv = NULL; 555 LPVOID pv = NULL;
287 SIZE_T cb = 0; 556 SIZE_T cb = 0;
@@ -295,6 +564,7 @@ DAPI_(HRESULT) PipeWriteMessage(
295 564
296LExit: 565LExit:
297 ReleaseMem(pv); 566 ReleaseMem(pv);
567
298 return hr; 568 return hr;
299} 569}
300 570
@@ -302,7 +572,7 @@ static HRESULT AllocatePipeMessage(
302 __in DWORD dwMessageType, 572 __in DWORD dwMessageType,
303 __in_bcount_opt(cbData) LPVOID pvData, 573 __in_bcount_opt(cbData) LPVOID pvData,
304 __in SIZE_T cbData, 574 __in SIZE_T cbData,
305 __out_bcount(cb) LPVOID* ppvMessage, 575 __out_bcount(*pcbMessage) LPVOID* ppvMessage,
306 __out SIZE_T* pcbMessage 576 __out SIZE_T* pcbMessage
307) 577)
308{ 578{
@@ -311,21 +581,12 @@ static HRESULT AllocatePipeMessage(
311 size_t cb = 0; 581 size_t cb = 0;
312 DWORD dwcbData = 0; 582 DWORD dwcbData = 0;
313 583
314 // If no data was provided, ensure the count of bytes is zero. 584 hr = DutilSizetToDword(pvData ? cbData : 0, &dwcbData);
315 if (!pvData) 585 PipeExitOnFailure(hr, "Pipe message is too large.");
316 {
317 cbData = 0;
318 }
319 else if (MAXDWORD < cbData)
320 {
321 ExitWithRootFailure(hr, E_INVALIDDATA, "Pipe message is too large.");
322 }
323 586
324 hr = ::SizeTAdd(sizeof(dwMessageType) + sizeof(dwcbData), cbData, &cb); 587 hr = ::SizeTAdd(sizeof(dwMessageType) + sizeof(dwcbData), dwcbData, &cb);
325 ExitOnRootFailure(hr, "Failed to calculate total pipe message size"); 588 ExitOnRootFailure(hr, "Failed to calculate total pipe message size");
326 589
327 dwcbData = (DWORD)cbData;
328
329 // Allocate the message. 590 // Allocate the message.
330 pv = MemAlloc(cb, FALSE); 591 pv = MemAlloc(cb, FALSE);
331 ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for message."); 592 ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for message.");