aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/burnpipe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/burnpipe.cpp')
-rw-r--r--src/burn/engine/burnpipe.cpp317
1 files changed, 41 insertions, 276 deletions
diff --git a/src/burn/engine/burnpipe.cpp b/src/burn/engine/burnpipe.cpp
index 5003622c..297dc77a 100644
--- a/src/burn/engine/burnpipe.cpp
+++ b/src/burn/engine/burnpipe.cpp
@@ -2,34 +2,9 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5static const DWORD PIPE_64KB = 64 * 1024; 5static const LPCWSTR CACHE_PIPE_NAME_FORMAT_STRING = L"%ls.Cache";
6static const DWORD PIPE_WAIT_FOR_CONNECTION = 100; // wait a 10th of a second, 6static const LPCWSTR LOGGING_PIPE_NAME_FORMAT_STRING = L"%ls.Log";
7static const DWORD PIPE_RETRY_FOR_CONNECTION = 1800; // for up to 3 minutes.
8 7
9static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls";
10static const LPCWSTR CACHE_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Cache";
11static const LPCWSTR LOGGING_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Log";
12
13static HRESULT AllocatePipeMessage(
14 __in DWORD dwMessage,
15 __in_bcount_opt(cbData) LPVOID pvData,
16 __in SIZE_T cbData,
17 __out_bcount(cb) LPVOID* ppvMessage,
18 __out SIZE_T* pcbMessage
19 );
20static void FreePipeMessage(
21 __in BURN_PIPE_MESSAGE *pMsg
22 );
23static HRESULT WritePipeMessage(
24 __in HANDLE hPipe,
25 __in DWORD dwMessage,
26 __in_bcount_opt(cbData) LPVOID pvData,
27 __in SIZE_T cbData
28 );
29static HRESULT GetPipeMessage(
30 __in HANDLE hPipe,
31 __in BURN_PIPE_MESSAGE* pMsg
32 );
33static HRESULT ChildPipeConnected( 8static HRESULT ChildPipeConnected(
34 __in HANDLE hPipe, 9 __in HANDLE hPipe,
35 __in_z LPCWSTR wzSecret, 10 __in_z LPCWSTR wzSecret,
@@ -37,7 +12,6 @@ static HRESULT ChildPipeConnected(
37 ); 12 );
38 13
39 14
40
41/******************************************************************* 15/*******************************************************************
42 PipeConnectionInitialize - initialize pipe connection data. 16 PipeConnectionInitialize - initialize pipe connection data.
43 17
@@ -60,9 +34,9 @@ void PipeConnectionUninitialize(
60 __in BURN_PIPE_CONNECTION* pConnection 34 __in BURN_PIPE_CONNECTION* pConnection
61 ) 35 )
62{ 36{
63 ReleaseFileHandle(pConnection->hLoggingPipe); 37 ReleasePipeHandle(pConnection->hLoggingPipe);
64 ReleaseFileHandle(pConnection->hCachePipe); 38 ReleasePipeHandle(pConnection->hCachePipe);
65 ReleaseFileHandle(pConnection->hPipe); 39 ReleasePipeHandle(pConnection->hPipe);
66 ReleaseHandle(pConnection->hProcess); 40 ReleaseHandle(pConnection->hProcess);
67 ReleaseStr(pConnection->sczSecret); 41 ReleaseStr(pConnection->sczSecret);
68 ReleaseStr(pConnection->sczName); 42 ReleaseStr(pConnection->sczName);
@@ -71,7 +45,7 @@ void PipeConnectionUninitialize(
71} 45}
72 46
73/******************************************************************* 47/*******************************************************************
74 PipeSendMessage - 48 PipeSendMessage -
75 49
76*******************************************************************/ 50*******************************************************************/
77extern "C" HRESULT PipeSendMessage( 51extern "C" HRESULT PipeSendMessage(
@@ -87,7 +61,7 @@ extern "C" HRESULT PipeSendMessage(
87 HRESULT hr = S_OK; 61 HRESULT hr = S_OK;
88 BURN_PIPE_RESULT result = { }; 62 BURN_PIPE_RESULT result = { };
89 63
90 hr = WritePipeMessage(hPipe, dwMessage, pvData, cbData); 64 hr = PipeWriteMessage(hPipe, dwMessage, pvData, cbData);
91 ExitOnFailure(hr, "Failed to write send message to pipe."); 65 ExitOnFailure(hr, "Failed to write send message to pipe.");
92 66
93 hr = PipePumpMessages(hPipe, pfnCallback, pvContext, &result); 67 hr = PipePumpMessages(hPipe, pfnCallback, pvContext, &result);
@@ -100,7 +74,7 @@ LExit:
100} 74}
101 75
102/******************************************************************* 76/*******************************************************************
103 PipePumpMessages - 77 PipePumpMessages -
104 78
105*******************************************************************/ 79*******************************************************************/
106extern "C" HRESULT PipePumpMessages( 80extern "C" HRESULT PipePumpMessages(
@@ -111,15 +85,15 @@ extern "C" HRESULT PipePumpMessages(
111 ) 85 )
112{ 86{
113 HRESULT hr = S_OK; 87 HRESULT hr = S_OK;
114 BURN_PIPE_MESSAGE msg = { }; 88 PIPE_MESSAGE msg = { };
115 SIZE_T iData = 0; 89 SIZE_T iData = 0;
116 LPSTR sczMessage = NULL; 90 LPSTR sczMessage = NULL;
117 DWORD dwResult = 0; 91 DWORD dwResult = 0;
118 92
119 // Pump messages from child process. 93 // Pump messages from child process.
120 while (S_OK == (hr = GetPipeMessage(hPipe, &msg))) 94 while (S_OK == (hr = PipeReadMessage(hPipe, &msg)))
121 { 95 {
122 switch (msg.dwMessage) 96 switch (msg.dwMessageType)
123 { 97 {
124 case BURN_PIPE_MESSAGE_TYPE_LOG: 98 case BURN_PIPE_MESSAGE_TYPE_LOG:
125 iData = 0; 99 iData = 0;
@@ -166,15 +140,15 @@ extern "C" HRESULT PipePumpMessages(
166 { 140 {
167 hr = E_INVALIDARG; 141 hr = E_INVALIDARG;
168 } 142 }
169 ExitOnFailure(hr, "Failed to process message: %u", msg.dwMessage); 143 ExitOnFailure(hr, "Failed to process message: %u", msg.dwMessageType);
170 break; 144 break;
171 } 145 }
172 146
173 // post result 147 // post result
174 hr = WritePipeMessage(hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_COMPLETE), &dwResult, sizeof(dwResult)); 148 hr = PipeWriteMessage(hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_COMPLETE), &dwResult, sizeof(dwResult));
175 ExitOnFailure(hr, "Failed to post result to child process."); 149 ExitOnFailure(hr, "Failed to post result to child process.");
176 150
177 FreePipeMessage(&msg); 151 ReleasePipeMessage(&msg);
178 } 152 }
179 ExitOnFailure(hr, "Failed to get message over pipe"); 153 ExitOnFailure(hr, "Failed to get message over pipe");
180 154
@@ -185,13 +159,13 @@ extern "C" HRESULT PipePumpMessages(
185 159
186LExit: 160LExit:
187 ReleaseStr(sczMessage); 161 ReleaseStr(sczMessage);
188 FreePipeMessage(&msg); 162 ReleasePipeMessage(&msg);
189 163
190 return hr; 164 return hr;
191} 165}
192 166
193/******************************************************************* 167/*******************************************************************
194 PipeCreateNameAndSecret - 168 PipeCreateNameAndSecret -
195 169
196*******************************************************************/ 170*******************************************************************/
197extern "C" HRESULT PipeCreateNameAndSecret( 171extern "C" HRESULT PipeCreateNameAndSecret(
@@ -247,7 +221,7 @@ extern "C" HRESULT PipeCreatePipes(
247 HRESULT hr = S_OK; 221 HRESULT hr = S_OK;
248 PSECURITY_DESCRIPTOR psd = NULL; 222 PSECURITY_DESCRIPTOR psd = NULL;
249 SECURITY_ATTRIBUTES sa = { }; 223 SECURITY_ATTRIBUTES sa = { };
250 LPWSTR sczFullPipeName = NULL; 224 LPWSTR sczPipeName = NULL;
251 HANDLE hPipe = INVALID_HANDLE_VALUE; 225 HANDLE hPipe = INVALID_HANDLE_VALUE;
252 HANDLE hCachePipe = INVALID_HANDLE_VALUE; 226 HANDLE hCachePipe = INVALID_HANDLE_VALUE;
253 HANDLE hLoggingPipe = INVALID_HANDLE_VALUE; 227 HANDLE hLoggingPipe = INVALID_HANDLE_VALUE;
@@ -269,37 +243,24 @@ extern "C" HRESULT PipeCreatePipes(
269 } 243 }
270 244
271 // Create the pipe. 245 // Create the pipe.
272 hr = StrAllocFormatted(&sczFullPipeName, PIPE_NAME_FORMAT_STRING, pConnection->sczName); 246 hr = PipeCreate(pConnection->sczName, psd ? &sa : NULL, &hPipe);
273 ExitOnFailure(hr, "Failed to allocate full name of pipe: %ls", pConnection->sczName); 247 ExitOnFailure(hr, "Failed to create pipe: %ls", pConnection->sczName);
274
275 // TODO: consider using overlapped IO to do waits on the pipe and still be able to cancel and such.
276 hPipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, psd ? &sa : NULL);
277 if (INVALID_HANDLE_VALUE == hPipe)
278 {
279 ExitWithLastError(hr, "Failed to create pipe: %ls", sczFullPipeName);
280 }
281 248
282 if (fCompanion) 249 if (fCompanion)
283 { 250 {
284 // Create the cache pipe. 251 // Create the cache pipe.
285 hr = StrAllocFormatted(&sczFullPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName); 252 hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
286 ExitOnFailure(hr, "Failed to allocate full name of cache pipe: %ls", pConnection->sczName); 253 ExitOnFailure(hr, "Failed to allocate full name of cache pipe: %ls", pConnection->sczName);
287 254
288 hCachePipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, NULL); 255 hr = PipeCreate(sczPipeName, NULL, &hCachePipe);
289 if (INVALID_HANDLE_VALUE == hCachePipe) 256 ExitOnFailure(hr, "Failed to create cache pipe: %ls", sczPipeName);
290 {
291 ExitWithLastError(hr, "Failed to create cache pipe: %ls", sczFullPipeName);
292 }
293 257
294 // Create the logging pipe. 258 // Create the logging pipe.
295 hr = StrAllocFormatted(&sczFullPipeName, LOGGING_PIPE_NAME_FORMAT_STRING, pConnection->sczName); 259 hr = StrAllocFormatted(&sczPipeName, LOGGING_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
296 ExitOnFailure(hr, "Failed to allocate full name of logging pipe: %ls", pConnection->sczName); 260 ExitOnFailure(hr, "Failed to allocate full name of logging pipe: %ls", pConnection->sczName);
297 261
298 hLoggingPipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, NULL); 262 hr = PipeCreate(sczPipeName, NULL, &hLoggingPipe);
299 if (INVALID_HANDLE_VALUE == hLoggingPipe) 263 ExitOnFailure(hr, "Failed to create logging pipe: %ls", sczPipeName);
300 {
301 ExitWithLastError(hr, "Failed to create logging pipe: %ls", sczFullPipeName);
302 }
303 } 264 }
304 265
305 pConnection->hLoggingPipe = hLoggingPipe; 266 pConnection->hLoggingPipe = hLoggingPipe;
@@ -312,10 +273,10 @@ extern "C" HRESULT PipeCreatePipes(
312 hPipe = INVALID_HANDLE_VALUE; 273 hPipe = INVALID_HANDLE_VALUE;
313 274
314LExit: 275LExit:
315 ReleaseFileHandle(hLoggingPipe); 276 ReleasePipeHandle(hLoggingPipe);
316 ReleaseFileHandle(hCachePipe); 277 ReleasePipeHandle(hCachePipe);
317 ReleaseFileHandle(hPipe); 278 ReleasePipeHandle(hPipe);
318 ReleaseStr(sczFullPipeName); 279 ReleaseStr(sczPipeName);
319 280
320 if (psd) 281 if (psd)
321 { 282 {
@@ -326,7 +287,7 @@ LExit:
326} 287}
327 288
328/******************************************************************* 289/*******************************************************************
329 PipeWaitForChildConnect - 290 PipeWaitForChildConnect -
330 291
331*******************************************************************/ 292*******************************************************************/
332extern "C" HRESULT PipeWaitForChildConnect( 293extern "C" HRESULT PipeWaitForChildConnect(
@@ -343,58 +304,10 @@ extern "C" HRESULT PipeWaitForChildConnect(
343 for (DWORD i = 0; i < countof(hPipes) && INVALID_HANDLE_VALUE != hPipes[i]; ++i) 304 for (DWORD i = 0; i < countof(hPipes) && INVALID_HANDLE_VALUE != hPipes[i]; ++i)
344 { 305 {
345 HANDLE hPipe = hPipes[i]; 306 HANDLE hPipe = hPipes[i];
346 DWORD dwPipeState = PIPE_READMODE_BYTE | PIPE_NOWAIT;
347 307
348 // Temporarily make the pipe non-blocking so we will not get stuck in ::ConnectNamedPipe() forever 308 hr = PipeServerWaitForClientConnect(hPipe);
349 // if the child decides not to show up.
350 if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL))
351 {
352 ExitWithLastError(hr, "Failed to set pipe to non-blocking.");
353 }
354
355 // Loop for a while waiting for a connection from child process.
356 DWORD cRetry = 0;
357 do
358 {
359 if (!::ConnectNamedPipe(hPipe, NULL))
360 {
361 DWORD er = ::GetLastError();
362 if (ERROR_PIPE_CONNECTED == er)
363 {
364 hr = S_OK;
365 break;
366 }
367 else if (ERROR_PIPE_LISTENING == er)
368 {
369 if (cRetry < PIPE_RETRY_FOR_CONNECTION)
370 {
371 hr = HRESULT_FROM_WIN32(er);
372 }
373 else
374 {
375 hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
376 break;
377 }
378
379 ++cRetry;
380 ::Sleep(PIPE_WAIT_FOR_CONNECTION);
381 }
382 else
383 {
384 hr = HRESULT_FROM_WIN32(er);
385 break;
386 }
387 }
388 } while (HRESULT_FROM_WIN32(ERROR_PIPE_LISTENING) == hr);
389 ExitOnRootFailure(hr, "Failed to wait for child to connect to pipe."); 309 ExitOnRootFailure(hr, "Failed to wait for child to connect to pipe.");
390 310
391 // Put the pipe back in blocking mode.
392 dwPipeState = PIPE_READMODE_BYTE | PIPE_WAIT;
393 if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL))
394 {
395 ExitWithLastError(hr, "Failed to reset pipe to blocking.");
396 }
397
398 // Prove we are the one that created the elevated process by passing the secret. 311 // Prove we are the one that created the elevated process by passing the secret.
399 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(&cbSecret), sizeof(cbSecret)); 312 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(&cbSecret), sizeof(cbSecret));
400 ExitOnFailure(hr, "Failed to write secret length to pipe."); 313 ExitOnFailure(hr, "Failed to write secret length to pipe.");
@@ -422,7 +335,7 @@ LExit:
422} 335}
423 336
424/******************************************************************* 337/*******************************************************************
425 PipeTerminateLoggingPipe - 338 PipeTerminateLoggingPipe -
426 339
427*******************************************************************/ 340*******************************************************************/
428extern "C" HRESULT PipeTerminateLoggingPipe( 341extern "C" HRESULT PipeTerminateLoggingPipe(
@@ -438,7 +351,7 @@ extern "C" HRESULT PipeTerminateLoggingPipe(
438 hr = BuffWriteNumber(&pbData, &cbData, dwParentExitCode); 351 hr = BuffWriteNumber(&pbData, &cbData, dwParentExitCode);
439 ExitOnFailure(hr, "Failed to write exit code to message buffer."); 352 ExitOnFailure(hr, "Failed to write exit code to message buffer.");
440 353
441 hr = WritePipeMessage(hLoggingPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_COMPLETE), pbData, cbData); 354 hr = PipeWriteMessage(hLoggingPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_COMPLETE), pbData, cbData);
442 ExitOnFailure(hr, "Failed to post complete message to logging pipe."); 355 ExitOnFailure(hr, "Failed to post complete message to logging pipe.");
443 356
444LExit: 357LExit:
@@ -448,7 +361,7 @@ LExit:
448} 361}
449 362
450/******************************************************************* 363/*******************************************************************
451 PipeTerminateChildProcess - 364 PipeTerminateChildProcess -
452 365
453*******************************************************************/ 366*******************************************************************/
454extern "C" HRESULT PipeTerminateChildProcess( 367extern "C" HRESULT PipeTerminateChildProcess(
@@ -472,11 +385,11 @@ extern "C" HRESULT PipeTerminateChildProcess(
472 // Send the messages. 385 // Send the messages.
473 if (INVALID_HANDLE_VALUE != pConnection->hCachePipe) 386 if (INVALID_HANDLE_VALUE != pConnection->hCachePipe)
474 { 387 {
475 hr = WritePipeMessage(pConnection->hCachePipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_TERMINATE), pbData, cbData); 388 hr = PipeWriteMessage(pConnection->hCachePipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_TERMINATE), pbData, cbData);
476 ExitOnFailure(hr, "Failed to post terminate message to child process cache thread."); 389 ExitOnFailure(hr, "Failed to post terminate message to child process cache thread.");
477 } 390 }
478 391
479 hr = WritePipeMessage(pConnection->hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_TERMINATE), pbData, cbData); 392 hr = PipeWriteMessage(pConnection->hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_TERMINATE), pbData, cbData);
480 ExitOnFailure(hr, "Failed to post terminate message to child process."); 393 ExitOnFailure(hr, "Failed to post terminate message to child process.");
481 394
482 // If we were able to get a handle to the other process, wait for it to exit. 395 // If we were able to get a handle to the other process, wait for it to exit.
@@ -532,28 +445,7 @@ extern "C" HRESULT PipeChildConnect(
532 LPWSTR sczPipeName = NULL; 445 LPWSTR sczPipeName = NULL;
533 446
534 // Try to connect to the parent. 447 // Try to connect to the parent.
535 hr = StrAllocFormatted(&sczPipeName, PIPE_NAME_FORMAT_STRING, pConnection->sczName); 448 hr = PipeClientConnect(pConnection->sczName, &pConnection->hPipe);
536 ExitOnFailure(hr, "Failed to allocate name of parent pipe.");
537
538 hr = E_UNEXPECTED;
539 for (DWORD cRetry = 0; FAILED(hr) && cRetry < PIPE_RETRY_FOR_CONNECTION; ++cRetry)
540 {
541 pConnection->hPipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
542 if (INVALID_HANDLE_VALUE == pConnection->hPipe)
543 {
544 hr = HRESULT_FROM_WIN32(::GetLastError());
545 if (E_FILENOTFOUND == hr) // if the pipe isn't created, call it a timeout waiting on the parent.
546 {
547 hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
548 }
549
550 ::Sleep(PIPE_WAIT_FOR_CONNECTION);
551 }
552 else // we have a connection, go with it.
553 {
554 hr = S_OK;
555 }
556 }
557 ExitOnRootFailure(hr, "Failed to open parent pipe: %ls", sczPipeName) 449 ExitOnRootFailure(hr, "Failed to open parent pipe: %ls", sczPipeName)
558 450
559 // Verify the parent and notify it that the child connected. 451 // Verify the parent and notify it that the child connected.
@@ -566,11 +458,8 @@ extern "C" HRESULT PipeChildConnect(
566 hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName); 458 hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
567 ExitOnFailure(hr, "Failed to allocate name of parent cache pipe."); 459 ExitOnFailure(hr, "Failed to allocate name of parent cache pipe.");
568 460
569 pConnection->hCachePipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 461 hr = PipeClientConnect(sczPipeName, &pConnection->hCachePipe);
570 if (INVALID_HANDLE_VALUE == pConnection->hCachePipe) 462 ExitOnFailure(hr, "Failed to open parent cache pipe: %ls", sczPipeName)
571 {
572 ExitWithLastError(hr, "Failed to open parent cache pipe: %ls", sczPipeName)
573 }
574 463
575 // Verify the parent and notify it that the child connected. 464 // Verify the parent and notify it that the child connected.
576 hr = ChildPipeConnected(pConnection->hCachePipe, pConnection->sczSecret, &pConnection->dwProcessId); 465 hr = ChildPipeConnected(pConnection->hCachePipe, pConnection->sczSecret, &pConnection->dwProcessId);
@@ -580,11 +469,8 @@ extern "C" HRESULT PipeChildConnect(
580 hr = StrAllocFormatted(&sczPipeName, LOGGING_PIPE_NAME_FORMAT_STRING, pConnection->sczName); 469 hr = StrAllocFormatted(&sczPipeName, LOGGING_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
581 ExitOnFailure(hr, "Failed to allocate name of parent logging pipe."); 470 ExitOnFailure(hr, "Failed to allocate name of parent logging pipe.");
582 471
583 pConnection->hLoggingPipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 472 hr = PipeClientConnect(sczPipeName, &pConnection->hLoggingPipe);
584 if (INVALID_HANDLE_VALUE == pConnection->hLoggingPipe) 473 ExitOnFailure(hr, "Failed to open parent cache pipe: %ls", sczPipeName)
585 {
586 ExitWithLastError(hr, "Failed to open parent logging pipe: %ls", sczPipeName)
587 }
588 474
589 // Verify the parent and notify it that the child connected. 475 // Verify the parent and notify it that the child connected.
590 hr = ChildPipeConnected(pConnection->hLoggingPipe, pConnection->sczSecret, &pConnection->dwProcessId); 476 hr = ChildPipeConnected(pConnection->hLoggingPipe, pConnection->sczSecret, &pConnection->dwProcessId);
@@ -600,127 +486,6 @@ LExit:
600 return hr; 486 return hr;
601} 487}
602 488
603
604static HRESULT AllocatePipeMessage(
605 __in DWORD dwMessage,
606 __in_bcount_opt(cbData) LPVOID pvData,
607 __in SIZE_T cbData,
608 __out_bcount(cb) LPVOID* ppvMessage,
609 __out SIZE_T* pcbMessage
610 )
611{
612 HRESULT hr = S_OK;
613 LPVOID pv = NULL;
614 size_t cb = 0;
615 DWORD dwcbData = 0;
616
617 // If no data was provided, ensure the count of bytes is zero.
618 if (!pvData)
619 {
620 cbData = 0;
621 }
622 else if (MAXDWORD < cbData)
623 {
624 ExitWithRootFailure(hr, E_INVALIDDATA, "Pipe message is too large.");
625 }
626
627 hr = ::SizeTAdd(sizeof(dwMessage) + sizeof(dwcbData), cbData, &cb);
628 ExitOnRootFailure(hr, "Failed to calculate total pipe message size");
629
630 dwcbData = (DWORD)cbData;
631
632 // Allocate the message.
633 pv = MemAlloc(cb, FALSE);
634 ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for message.");
635
636 memcpy_s(pv, cb, &dwMessage, sizeof(dwMessage));
637 memcpy_s(static_cast<BYTE*>(pv) + sizeof(dwMessage), cb - sizeof(dwMessage), &dwcbData, sizeof(dwcbData));
638 if (dwcbData)
639 {
640 memcpy_s(static_cast<BYTE*>(pv) + sizeof(dwMessage) + sizeof(dwcbData), cb - sizeof(dwMessage) - sizeof(dwcbData), pvData, dwcbData);
641 }
642
643 *pcbMessage = cb;
644 *ppvMessage = pv;
645 pv = NULL;
646
647LExit:
648 ReleaseMem(pv);
649 return hr;
650}
651
652static void FreePipeMessage(
653 __in BURN_PIPE_MESSAGE *pMsg
654 )
655{
656 if (pMsg->fAllocatedData)
657 {
658 ReleaseNullMem(pMsg->pvData);
659 pMsg->fAllocatedData = FALSE;
660 }
661}
662
663static HRESULT WritePipeMessage(
664 __in HANDLE hPipe,
665 __in DWORD dwMessage,
666 __in_bcount_opt(cbData) LPVOID pvData,
667 __in SIZE_T cbData
668 )
669{
670 HRESULT hr = S_OK;
671 LPVOID pv = NULL;
672 SIZE_T cb = 0;
673
674 hr = AllocatePipeMessage(dwMessage, pvData, cbData, &pv, &cb);
675 ExitOnFailure(hr, "Failed to allocate message to write.");
676
677 // Write the message.
678 hr = FileWriteHandle(hPipe, reinterpret_cast<LPCBYTE>(pv), cb);
679 ExitOnFailure(hr, "Failed to write message type to pipe.");
680
681LExit:
682 ReleaseMem(pv);
683 return hr;
684}
685
686static HRESULT GetPipeMessage(
687 __in HANDLE hPipe,
688 __in BURN_PIPE_MESSAGE* pMsg
689 )
690{
691 HRESULT hr = S_OK;
692 BYTE pbMessageAndByteCount[sizeof(DWORD) + sizeof(DWORD)] = { };
693
694 hr = FileReadHandle(hPipe, pbMessageAndByteCount, sizeof(pbMessageAndByteCount));
695 if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE) == hr)
696 {
697 memset(pbMessageAndByteCount, 0, sizeof(pbMessageAndByteCount));
698 hr = S_FALSE;
699 }
700 ExitOnFailure(hr, "Failed to read message from pipe.");
701
702 pMsg->dwMessage = *(DWORD*)(pbMessageAndByteCount);
703 pMsg->cbData = *(DWORD*)(pbMessageAndByteCount + sizeof(DWORD));
704 if (pMsg->cbData)
705 {
706 pMsg->pvData = MemAlloc(pMsg->cbData, FALSE);
707 ExitOnNull(pMsg->pvData, hr, E_OUTOFMEMORY, "Failed to allocate data for message.");
708
709 hr = FileReadHandle(hPipe, reinterpret_cast<LPBYTE>(pMsg->pvData), pMsg->cbData);
710 ExitOnFailure(hr, "Failed to read data for message.");
711
712 pMsg->fAllocatedData = TRUE;
713 }
714
715LExit:
716 if (!pMsg->fAllocatedData && pMsg->pvData)
717 {
718 MemFree(pMsg->pvData);
719 }
720
721 return hr;
722}
723
724static HRESULT ChildPipeConnected( 489static HRESULT ChildPipeConnected(
725 __in HANDLE hPipe, 490 __in HANDLE hPipe,
726 __in_z LPCWSTR wzSecret, 491 __in_z LPCWSTR wzSecret,