aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-06-29 10:28:53 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-06-29 15:08:37 -0500
commit7cca75c8e95f129a21c33f1f4568e90e9e397f9d (patch)
treecb9890caa1ac8bc891d444b6376a5e9f997ca1e3 /src/burn
parent3ff6428a068bafd74d8ec072a5fc261c33cc2019 (diff)
downloadwix-7cca75c8e95f129a21c33f1f4568e90e9e397f9d.tar.gz
wix-7cca75c8e95f129a21c33f1f4568e90e9e397f9d.tar.bz2
wix-7cca75c8e95f129a21c33f1f4568e90e9e397f9d.zip
Add AppWaitForSingleObject/MultipleObjects, ThreadWaitForCompletion.
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/apply.cpp26
-rw-r--r--src/burn/engine/cabextract.cpp42
-rw-r--r--src/burn/engine/core.cpp54
-rw-r--r--src/burn/engine/core.h14
-rw-r--r--src/burn/engine/elevation.cpp11
-rw-r--r--src/burn/engine/netfxchainer.cpp31
-rw-r--r--src/burn/engine/pipe.cpp34
-rw-r--r--src/burn/engine/precomp.h1
-rw-r--r--src/burn/test/BurnUnitTest/ElevationTest.cpp3
-rw-r--r--src/burn/test/BurnUnitTest/precomp.h1
10 files changed, 111 insertions, 106 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index e5b978f1..dd99a5cd 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -2333,6 +2333,8 @@ static HRESULT DoExecuteAction(
2333 2333
2334 HRESULT hr = S_OK; 2334 HRESULT hr = S_OK;
2335 HANDLE rghWait[2] = { }; 2335 HANDLE rghWait[2] = { };
2336 DWORD dwSignaledIndex = 0;
2337 DWORD dwExitCode = 0;
2336 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2338 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2337 BOOL fRetry = FALSE; 2339 BOOL fRetry = FALSE;
2338 BOOL fStopWusaService = FALSE; 2340 BOOL fStopWusaService = FALSE;
@@ -2356,27 +2358,23 @@ static HRESULT DoExecuteAction(
2356 // wait for cache sync-point 2358 // wait for cache sync-point
2357 rghWait[0] = pExecuteAction->waitCachePackage.pPackage->hCacheEvent; 2359 rghWait[0] = pExecuteAction->waitCachePackage.pPackage->hCacheEvent;
2358 rghWait[1] = pContext->pApplyContext->hCacheThread; 2360 rghWait[1] = pContext->pApplyContext->hCacheThread;
2359 switch (::WaitForMultipleObjects(rghWait[1] ? 2 : 1, rghWait, FALSE, INFINITE)) 2361
2362 hr = AppWaitForMultipleObjects(rghWait[1] ? 2 : 1, rghWait, FALSE, INFINITE, &dwSignaledIndex);
2363 ExitOnFailure(hr, "Failed to wait for cache check-point.");
2364
2365 switch (dwSignaledIndex)
2360 { 2366 {
2361 case WAIT_OBJECT_0: 2367 case 0:
2362 break; 2368 break;
2363 2369 case 1:
2364 case WAIT_OBJECT_0 + 1: 2370 if (!::GetExitCodeThread(pContext->pApplyContext->hCacheThread, &dwExitCode))
2365 if (!::GetExitCodeThread(pContext->pApplyContext->hCacheThread, (DWORD*)&hr))
2366 { 2371 {
2367 ExitWithLastError(hr, "Failed to get cache thread exit code."); 2372 ExitWithLastError(hr, "Failed to get cache thread exit code.");
2368 } 2373 }
2369 2374
2370 if (SUCCEEDED(hr)) 2375 ExitWithRootFailure(hr, E_UNEXPECTED, "Cache thread exited unexpectedly with exit code: %u.", dwExitCode);
2371 {
2372 hr = E_UNEXPECTED;
2373 }
2374 ExitOnFailure(hr, "Cache thread exited unexpectedly.");
2375
2376 case WAIT_FAILED: __fallthrough;
2377 default:
2378 ExitWithLastError(hr, "Failed to wait for cache check-point.");
2379 } 2376 }
2377
2380 break; 2378 break;
2381 2379
2382 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: 2380 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
diff --git a/src/burn/engine/cabextract.cpp b/src/burn/engine/cabextract.cpp
index 5a02ff8a..56146a39 100644
--- a/src/burn/engine/cabextract.cpp
+++ b/src/burn/engine/cabextract.cpp
@@ -262,10 +262,8 @@ extern "C" HRESULT CabExtractClose(
262 } 262 }
263 263
264 // wait for thread to terminate 264 // wait for thread to terminate
265 if (WAIT_OBJECT_0 != ::WaitForSingleObject(pContext->Cabinet.hThread, INFINITE)) 265 hr = AppWaitForSingleObject(pContext->Cabinet.hThread, INFINITE);
266 { 266 ExitOnFailure(hr, "Failed to wait for thread to terminate.");
267 ExitWithLastError(hr, "Failed to wait for thread to terminate.");
268 }
269 } 267 }
270 268
271LExit: 269LExit:
@@ -306,29 +304,31 @@ static HRESULT WaitForOperation(
306{ 304{
307 HRESULT hr = S_OK; 305 HRESULT hr = S_OK;
308 HANDLE rghWait[2] = { }; 306 HANDLE rghWait[2] = { };
307 DWORD dwSignaledIndex = 0;
309 308
310 // wait for operation complete event 309 // wait for operation complete event
311 rghWait[0] = pContext->Cabinet.hOperationCompleteEvent; 310 rghWait[0] = pContext->Cabinet.hOperationCompleteEvent;
312 rghWait[1] = pContext->Cabinet.hThread; 311 rghWait[1] = pContext->Cabinet.hThread;
313 switch (::WaitForMultipleObjects(countof(rghWait), rghWait, FALSE, INFINITE)) 312
313 hr = AppWaitForMultipleObjects(countof(rghWait), rghWait, FALSE, INFINITE, &dwSignaledIndex);
314 ExitOnFailure(hr, "Failed to wait for operation complete event.");
315
316 switch (dwSignaledIndex)
314 { 317 {
315 case WAIT_OBJECT_0: 318 case 0:
316 if (!::ResetEvent(pContext->Cabinet.hOperationCompleteEvent)) 319 if (!::ResetEvent(pContext->Cabinet.hOperationCompleteEvent))
317 { 320 {
318 ExitWithLastError(hr, "Failed to reset operation complete event."); 321 ExitWithLastError(hr, "Failed to reset operation complete event.");
319 } 322 }
320 break;
321 323
322 case WAIT_OBJECT_0 + 1: 324 break;
325 case 1:
323 if (!::GetExitCodeThread(pContext->Cabinet.hThread, (DWORD*)&hr)) 326 if (!::GetExitCodeThread(pContext->Cabinet.hThread, (DWORD*)&hr))
324 { 327 {
325 ExitWithLastError(hr, "Failed to get extraction thread exit code."); 328 ExitWithLastError(hr, "Failed to get extraction thread exit code.");
326 } 329 }
327 ExitFunction();
328 330
329 case WAIT_FAILED: __fallthrough; 331 ExitFunction();
330 default:
331 ExitWithLastError(hr, "Failed to wait for operation complete event.");
332 } 332 }
333 333
334 // clear operation 334 // clear operation
@@ -430,10 +430,8 @@ static DWORD WINAPI ExtractThreadProc(
430 } 430 }
431 431
432 // wait for begin operation event 432 // wait for begin operation event
433 if (WAIT_FAILED == ::WaitForSingleObject(pContext->Cabinet.hBeginOperationEvent, INFINITE)) 433 hr = AppWaitForSingleObject(pContext->Cabinet.hBeginOperationEvent, INFINITE);
434 { 434 ExitOnFailure(hr, "Failed to wait for begin operation event.");
435 ExitWithLastError(hr, "Failed to wait for begin operation event.");
436 }
437 435
438 if (!::ResetEvent(pContext->Cabinet.hBeginOperationEvent)) 436 if (!::ResetEvent(pContext->Cabinet.hBeginOperationEvent))
439 { 437 {
@@ -517,10 +515,8 @@ static INT_PTR CopyFileCallback(
517 } 515 }
518 516
519 // wait for begin operation event 517 // wait for begin operation event
520 if (WAIT_FAILED == ::WaitForSingleObject(pContext->Cabinet.hBeginOperationEvent, INFINITE)) 518 hr = AppWaitForSingleObject(pContext->Cabinet.hBeginOperationEvent, INFINITE);
521 { 519 ExitOnFailure(hr, "Failed to wait for begin operation event.");
522 ExitWithLastError(hr, "Failed to wait for begin operation event.");
523 }
524 520
525 if (!::ResetEvent(pContext->Cabinet.hBeginOperationEvent)) 521 if (!::ResetEvent(pContext->Cabinet.hBeginOperationEvent))
526 { 522 {
@@ -552,10 +548,8 @@ static INT_PTR CopyFileCallback(
552 } 548 }
553 549
554 // wait for begin operation event 550 // wait for begin operation event
555 if (WAIT_FAILED == ::WaitForSingleObject(pContext->Cabinet.hBeginOperationEvent, INFINITE)) 551 hr = AppWaitForSingleObject(pContext->Cabinet.hBeginOperationEvent, INFINITE);
556 { 552 ExitOnFailure(hr, "Failed to wait for begin operation event.");
557 ExitWithLastError(hr, "Failed to wait for begin operation event.");
558 }
559 553
560 if (!::ResetEvent(pContext->Cabinet.hBeginOperationEvent)) 554 if (!::ResetEvent(pContext->Cabinet.hBeginOperationEvent))
561 { 555 {
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index c1e3a12c..716e5af1 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -12,6 +12,9 @@ struct BURN_CACHE_THREAD_CONTEXT
12}; 12};
13 13
14 14
15static PFN_PROCWAITFORCOMPLETION vpfnProcWaitForCompletion = ProcWaitForCompletion;
16
17
15// internal function declarations 18// internal function declarations
16 19
17static HRESULT CoreRecreateCommandLine( 20static HRESULT CoreRecreateCommandLine(
@@ -65,9 +68,6 @@ static HRESULT DetectPackagePayloadsCached(
65static DWORD WINAPI CacheThreadProc( 68static DWORD WINAPI CacheThreadProc(
66 __in LPVOID lpThreadParameter 69 __in LPVOID lpThreadParameter
67 ); 70 );
68static HRESULT WaitForCacheThread(
69 __in HANDLE hCacheThread
70 );
71static void LogPackages( 71static void LogPackages(
72 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage, 72 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage,
73 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage, 73 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage,
@@ -636,6 +636,7 @@ extern "C" HRESULT CoreApply(
636 BURN_APPLY_CONTEXT applyContext = { }; 636 BURN_APPLY_CONTEXT applyContext = { };
637 BOOL fDeleteApplyCs = FALSE; 637 BOOL fDeleteApplyCs = FALSE;
638 BURN_CACHE_THREAD_CONTEXT cacheThreadContext = { }; 638 BURN_CACHE_THREAD_CONTEXT cacheThreadContext = { };
639 DWORD dwCacheExitCode = 0;
639 BOOL fRollbackCache = FALSE; 640 BOOL fRollbackCache = FALSE;
640 DWORD dwPhaseCount = 0; 641 DWORD dwPhaseCount = 0;
641 BOOTSTRAPPER_APPLYCOMPLETE_ACTION applyCompleteAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE; 642 BOOTSTRAPPER_APPLYCOMPLETE_ACTION applyCompleteAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE;
@@ -744,7 +745,10 @@ extern "C" HRESULT CoreApply(
744 // If we're not caching in parallel, wait for the cache thread to terminate. 745 // If we're not caching in parallel, wait for the cache thread to terminate.
745 if (!pEngineState->fParallelCacheAndExecute) 746 if (!pEngineState->fParallelCacheAndExecute)
746 { 747 {
747 hr = WaitForCacheThread(applyContext.hCacheThread); 748 hr = ThrdWaitForCompletion(applyContext.hCacheThread, INFINITE, &dwCacheExitCode);
749 ExitOnFailure(hr, "Failed to wait for cache thread before execute.");
750
751 hr = (HRESULT)dwCacheExitCode;
748 ExitOnFailure(hr, "Failed while caching, aborting execution."); 752 ExitOnFailure(hr, "Failed while caching, aborting execution.");
749 753
750 ReleaseHandle(applyContext.hCacheThread); 754 ReleaseHandle(applyContext.hCacheThread);
@@ -761,10 +765,12 @@ extern "C" HRESULT CoreApply(
761 // Wait for cache thread to terminate, this should return immediately unless we're waiting for layout to complete. 765 // Wait for cache thread to terminate, this should return immediately unless we're waiting for layout to complete.
762 if (applyContext.hCacheThread) 766 if (applyContext.hCacheThread)
763 { 767 {
764 HRESULT hrCached = WaitForCacheThread(applyContext.hCacheThread); 768 HRESULT hrCached = ThrdWaitForCompletion(applyContext.hCacheThread, INFINITE, &dwCacheExitCode);
769 ExitOnFailure(hrCached, "Failed to wait for cache thread after execute.");
770
765 if (SUCCEEDED(hr)) 771 if (SUCCEEDED(hr))
766 { 772 {
767 hr = hrCached; 773 hr = (HRESULT)dwCacheExitCode;
768 } 774 }
769 } 775 }
770 776
@@ -1940,6 +1946,22 @@ LExit:
1940 return hr; 1946 return hr;
1941} 1947}
1942 1948
1949extern "C" void CoreFunctionOverride(
1950 __in_opt PFN_PROCWAITFORCOMPLETION pfnProcWaitForCompletion
1951 )
1952{
1953 vpfnProcWaitForCompletion = pfnProcWaitForCompletion;
1954}
1955
1956extern "C" HRESULT DAPI CoreWaitForProcCompletion(
1957 __in HANDLE hProcess,
1958 __in DWORD dwTimeout,
1959 __out DWORD* pdwReturnCode
1960 )
1961{
1962 return vpfnProcWaitForCompletion(hProcess, dwTimeout, pdwReturnCode);
1963}
1964
1943// internal helper functions 1965// internal helper functions
1944 1966
1945static HRESULT AppendEscapedArgumentToCommandLine( 1967static HRESULT AppendEscapedArgumentToCommandLine(
@@ -2268,26 +2290,6 @@ LExit:
2268 return (DWORD)hr; 2290 return (DWORD)hr;
2269} 2291}
2270 2292
2271static HRESULT WaitForCacheThread(
2272 __in HANDLE hCacheThread
2273 )
2274{
2275 HRESULT hr = S_OK;
2276
2277 if (WAIT_OBJECT_0 != ::WaitForSingleObject(hCacheThread, INFINITE))
2278 {
2279 ExitWithLastError(hr, "Failed to wait for cache thread to terminate.");
2280 }
2281
2282 if (!::GetExitCodeThread(hCacheThread, (DWORD*)&hr))
2283 {
2284 ExitWithLastError(hr, "Failed to get cache thread exit code.");
2285 }
2286
2287LExit:
2288 return hr;
2289}
2290
2291static void LogPackages( 2293static void LogPackages(
2292 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage, 2294 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage,
2293 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage, 2295 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage,
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 28d7ea78..14dbabcc 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -174,6 +174,12 @@ typedef struct _BURN_APPLY_CONTEXT
174 DWORD dwCacheCheckpoint; 174 DWORD dwCacheCheckpoint;
175} BURN_APPLY_CONTEXT; 175} BURN_APPLY_CONTEXT;
176 176
177typedef HRESULT (DAPI *PFN_PROCWAITFORCOMPLETION)(
178 __in HANDLE hProcess,
179 __in DWORD dwTimeout,
180 __out DWORD* pReturnCode
181 );
182
177 183
178// function declarations 184// function declarations
179 185
@@ -280,6 +286,14 @@ HRESULT CoreParseCommandLine(
280 __inout HANDLE* phSectionFile, 286 __inout HANDLE* phSectionFile,
281 __inout HANDLE* phSourceEngineFile 287 __inout HANDLE* phSourceEngineFile
282 ); 288 );
289void CoreFunctionOverride(
290 __in_opt PFN_PROCWAITFORCOMPLETION pfnProcWaitForCompletion
291 );
292HRESULT DAPI CoreWaitForProcCompletion(
293 __in HANDLE hProcess,
294 __in DWORD dwTimeout,
295 __out_opt DWORD* pdwReturnCode
296 );
283 297
284#if defined(__cplusplus) 298#if defined(__cplusplus)
285} 299}
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 4a5be8ec..e165a257 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -1687,15 +1687,8 @@ static HRESULT WaitForElevatedChildCacheThread(
1687 HRESULT hr = S_OK; 1687 HRESULT hr = S_OK;
1688 DWORD dwExitCode = ERROR_SUCCESS; 1688 DWORD dwExitCode = ERROR_SUCCESS;
1689 1689
1690 if (WAIT_OBJECT_0 != ::WaitForSingleObject(hCacheThread, BURN_TIMEOUT)) 1690 hr = ThrdWaitForCompletion(hCacheThread, BURN_TIMEOUT, &dwExitCode);
1691 { 1691 ExitOnFailure(hr, "Failed to wait for cache thread to complete.");
1692 ExitWithLastError(hr, "Failed to wait for cache thread to terminate.");
1693 }
1694
1695 if (!::GetExitCodeThread(hCacheThread, &dwExitCode))
1696 {
1697 ExitWithLastError(hr, "Failed to get cache thread exit code.");
1698 }
1699 1692
1700 AssertSz(dwExitCode == dwExpectedExitCode, "Cache thread should have exited with the expected exit code."); 1693 AssertSz(dwExitCode == dwExpectedExitCode, "Cache thread should have exited with the expected exit code.");
1701 1694
diff --git a/src/burn/engine/netfxchainer.cpp b/src/burn/engine/netfxchainer.cpp
index 6f223eed..68ddb093 100644
--- a/src/burn/engine/netfxchainer.cpp
+++ b/src/burn/engine/netfxchainer.cpp
@@ -338,7 +338,8 @@ extern "C" HRESULT NetFxRunChainer(
338 ) 338 )
339{ 339{
340 HRESULT hr = S_OK; 340 HRESULT hr = S_OK;
341 DWORD er = 0; 341 DWORD dwSignaledIndex = 0;
342 BOOL fTimedOut = 0;
342 WCHAR wzGuid[GUID_STRING_LENGTH]; 343 WCHAR wzGuid[GUID_STRING_LENGTH];
343 LPWSTR sczEventName = NULL; 344 LPWSTR sczEventName = NULL;
344 LPWSTR sczSectionName = NULL; 345 LPWSTR sczSectionName = NULL;
@@ -381,9 +382,17 @@ extern "C" HRESULT NetFxRunChainer(
381 382
382 for (;;) 383 for (;;)
383 { 384 {
384 er = ::WaitForMultipleObjects(2, handles, FALSE, 100); 385 hr = AppWaitForMultipleObjects(2, handles, FALSE, 100, &dwSignaledIndex);
385 if (WAIT_OBJECT_0 == er) 386 ExitOnWaitObjectFailure(hr, fTimedOut, "Failed to wait for netfx chainer process to complete");
387
388 if (fTimedOut)
389 {
390 continue;
391 }
392
393 switch (dwSignaledIndex)
386 { 394 {
395 case 0:
387 // Process has exited 396 // Process has exited
388 *pdwExitCode = NetFxGetResult(pNetfxChainer, &hrInternalError); 397 *pdwExitCode = NetFxGetResult(pNetfxChainer, &hrInternalError);
389 if (E_PENDING == *pdwExitCode) 398 if (E_PENDING == *pdwExitCode)
@@ -396,21 +405,17 @@ extern "C" HRESULT NetFxRunChainer(
396 else if (FAILED(hrInternalError)) 405 else if (FAILED(hrInternalError))
397 { 406 {
398 // push internal error message 407 // push internal error message
399 OnNetFxError(pNetfxChainer, hrInternalError, pfnGenericMessageHandler, pvContext); 408 hr = OnNetFxError(pNetfxChainer, hrInternalError, pfnGenericMessageHandler, pvContext);
400 ExitOnFailure(hr, "Failed to send internal error message from netfx chainer."); 409 ExitOnFailure(hr, "Failed to send internal error message from netfx chainer.");
401 } 410 }
402 411
403 break; 412 ExitFunction();
404 } 413 case 1:
405 else if (WAIT_OBJECT_0 + 1 == er)
406 {
407 // Chainee has notified us of a change. 414 // Chainee has notified us of a change.
408 hr = ProcessNetFxMessage(pNetfxChainer, pfnGenericMessageHandler, pvContext); 415 hr = ProcessNetFxMessage(pNetfxChainer, pfnGenericMessageHandler, pvContext);
409 ExitOnFailure(hr, "Failed to process netfx chainer message."); 416 ExitOnFailure(hr, "Failed to process netfx chainer message.");
410 } 417
411 else if (WAIT_FAILED == er) 418 break;
412 {
413 ExitWithLastError(hr, "Failed to wait for netfx chainer process to complete");
414 } 419 }
415 } 420 }
416 421
diff --git a/src/burn/engine/pipe.cpp b/src/burn/engine/pipe.cpp
index e6c9905b..9529ef40 100644
--- a/src/burn/engine/pipe.cpp
+++ b/src/burn/engine/pipe.cpp
@@ -422,6 +422,7 @@ extern "C" HRESULT PipeTerminateChildProcess(
422 HRESULT hr = S_OK; 422 HRESULT hr = S_OK;
423 BYTE* pbData = NULL; 423 BYTE* pbData = NULL;
424 SIZE_T cbData = 0; 424 SIZE_T cbData = 0;
425 BOOL fTimedOut = FALSE;
425 426
426 // Prepare the exit message. 427 // Prepare the exit message.
427 hr = BuffWriteNumber(&pbData, &cbData, dwParentExitCode); 428 hr = BuffWriteNumber(&pbData, &cbData, dwParentExitCode);
@@ -443,31 +444,28 @@ extern "C" HRESULT PipeTerminateChildProcess(
443 // If we were able to get a handle to the other process, wait for it to exit. 444 // If we were able to get a handle to the other process, wait for it to exit.
444 if (pConnection->hProcess) 445 if (pConnection->hProcess)
445 { 446 {
446 if (WAIT_FAILED == ::WaitForSingleObject(pConnection->hProcess, PIPE_WAIT_FOR_CONNECTION * PIPE_RETRY_FOR_CONNECTION)) 447 hr = AppWaitForSingleObject(pConnection->hProcess, PIPE_WAIT_FOR_CONNECTION * PIPE_RETRY_FOR_CONNECTION);
447 { 448 ExitOnWaitObjectFailure(hr, fTimedOut, "Failed to wait for child process exit.");
448 ExitWithLastError(hr, "Failed to wait for child process exit."); 449
449 } 450 AssertSz(!fTimedOut, "Timed out while waiting for child process to exit.");
451 }
450 452
451#ifdef DEBUG 453#ifdef DEBUG
454 if (pConnection->hProcess && !fTimedOut)
455 {
452 DWORD dwChildExitCode = 0; 456 DWORD dwChildExitCode = 0;
453 DWORD dwErrorCode = ERROR_SUCCESS; 457 HRESULT hrDebug = S_OK;
454 BOOL fReturnedExitCode = ::GetExitCodeProcess(pConnection->hProcess, &dwChildExitCode);
455 if (!fReturnedExitCode)
456 {
457 dwErrorCode = ::GetLastError(); // if the other process is elevated and we are not, then we'll get ERROR_ACCESS_DENIED.
458 458
459 // The unit test use a thread instead of a process so try to get the exit code from 459 hrDebug = CoreWaitForProcCompletion(pConnection->hProcess, 0, &dwChildExitCode);
460 // the thread because we failed to get it from the process. 460 if (E_ACCESSDENIED != hrDebug) // if the other process is elevated and we are not, then we'll get ERROR_ACCESS_DENIED.
461 if (ERROR_INVALID_HANDLE == dwErrorCode) 461 {
462 { 462 TraceError(hrDebug, "Failed to wait for child process completion.");
463 fReturnedExitCode = ::GetExitCodeThread(pConnection->hProcess, &dwChildExitCode);
464 }
465 } 463 }
466 AssertSz((fReturnedExitCode && dwChildExitCode == dwParentExitCode) || 464
467 (!fReturnedExitCode && ERROR_ACCESS_DENIED == dwErrorCode), 465 AssertSz(E_ACCESSDENIED == hrDebug || dwChildExitCode == dwParentExitCode,
468 "Child elevated process did not return matching exit code to parent process."); 466 "Child elevated process did not return matching exit code to parent process.");
469#endif
470 } 467 }
468#endif
471 469
472LExit: 470LExit:
473 return hr; 471 return hr;
diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h
index bc7046f6..e2d1b5cd 100644
--- a/src/burn/engine/precomp.h
+++ b/src/burn/engine/precomp.h
@@ -46,6 +46,7 @@
46#include <srputil.h> 46#include <srputil.h>
47#include <strutil.h> 47#include <strutil.h>
48#include <svcutil.h> 48#include <svcutil.h>
49#include <thrdutil.h>
49#include <userutil.h> 50#include <userutil.h>
50#include <wiutil.h> 51#include <wiutil.h>
51#include <wuautil.h> 52#include <wuautil.h>
diff --git a/src/burn/test/BurnUnitTest/ElevationTest.cpp b/src/burn/test/BurnUnitTest/ElevationTest.cpp
index 97d76b7d..ce34b4b1 100644
--- a/src/burn/test/BurnUnitTest/ElevationTest.cpp
+++ b/src/burn/test/BurnUnitTest/ElevationTest.cpp
@@ -54,7 +54,6 @@ namespace Bootstrapper
54 HRESULT hr = S_OK; 54 HRESULT hr = S_OK;
55 BURN_ENGINE_STATE engineState = { }; 55 BURN_ENGINE_STATE engineState = { };
56 BURN_PIPE_CONNECTION* pConnection = &engineState.companionConnection; 56 BURN_PIPE_CONNECTION* pConnection = &engineState.companionConnection;
57 HANDLE hEvent = NULL;
58 DWORD dwResult = S_OK; 57 DWORD dwResult = S_OK;
59 58
60 engineState.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe"; 59 engineState.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe";
@@ -62,6 +61,7 @@ namespace Bootstrapper
62 try 61 try
63 { 62 {
64 ShelFunctionOverride(ElevateTest_ShellExecuteExW); 63 ShelFunctionOverride(ElevateTest_ShellExecuteExW);
64 CoreFunctionOverride(ThrdWaitForCompletion);
65 65
66 PipeConnectionInitialize(pConnection); 66 PipeConnectionInitialize(pConnection);
67 67
@@ -87,7 +87,6 @@ namespace Bootstrapper
87 finally 87 finally
88 { 88 {
89 PipeConnectionUninitialize(pConnection); 89 PipeConnectionUninitialize(pConnection);
90 ReleaseHandle(hEvent);
91 } 90 }
92 } 91 }
93 }; 92 };
diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h
index 92c8c4c0..69c62cb2 100644
--- a/src/burn/test/BurnUnitTest/precomp.h
+++ b/src/burn/test/BurnUnitTest/precomp.h
@@ -28,6 +28,7 @@
28#include <resrutil.h> 28#include <resrutil.h>
29#include <shelutil.h> 29#include <shelutil.h>
30#include <strutil.h> 30#include <strutil.h>
31#include <thrdutil.h>
31#include <wiutil.h> 32#include <wiutil.h>
32#include <xmlutil.h> 33#include <xmlutil.h>
33#include <dictutil.h> 34#include <dictutil.h>