diff options
Diffstat (limited to '')
| -rw-r--r-- | src/burn/engine/engine.cpp | 243 |
1 files changed, 74 insertions, 169 deletions
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index f5ea5332..9daa18a1 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp | |||
| @@ -16,9 +16,11 @@ static HRESULT InitializeEngineState( | |||
| 16 | static void UninitializeEngineState( | 16 | static void UninitializeEngineState( |
| 17 | __in BURN_ENGINE_STATE* pEngineState | 17 | __in BURN_ENGINE_STATE* pEngineState |
| 18 | ); | 18 | ); |
| 19 | #if 0 | ||
| 19 | static HRESULT RunUntrusted( | 20 | static HRESULT RunUntrusted( |
| 20 | __in BURN_ENGINE_STATE* pEngineState | 21 | __in BURN_ENGINE_STATE* pEngineState |
| 21 | ); | 22 | ); |
| 23 | #endif | ||
| 22 | static HRESULT RunNormal( | 24 | static HRESULT RunNormal( |
| 23 | __in HINSTANCE hInstance, | 25 | __in HINSTANCE hInstance, |
| 24 | __in BURN_ENGINE_STATE* pEngineState | 26 | __in BURN_ENGINE_STATE* pEngineState |
| @@ -38,12 +40,13 @@ static HRESULT RunRunOnce( | |||
| 38 | ); | 40 | ); |
| 39 | static HRESULT RunApplication( | 41 | static HRESULT RunApplication( |
| 40 | __in BURN_ENGINE_STATE* pEngineState, | 42 | __in BURN_ENGINE_STATE* pEngineState, |
| 43 | __in BOOL fSecondaryBootstrapperApplication, | ||
| 41 | __out BOOL* pfReloadApp, | 44 | __out BOOL* pfReloadApp, |
| 42 | __out BOOL* pfSkipCleanup | 45 | __out BOOL* pfSkipCleanup |
| 43 | ); | 46 | ); |
| 44 | static HRESULT ProcessMessage( | 47 | static HRESULT ProcessMessage( |
| 45 | __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext, | 48 | __in BAENGINE_CONTEXT* pEngineContext, |
| 46 | __in BOOTSTRAPPER_ENGINE_ACTION* pAction | 49 | __in BAENGINE_ACTION* pAction |
| 47 | ); | 50 | ); |
| 48 | static HRESULT DAPI RedirectLoggingOverPipe( | 51 | static HRESULT DAPI RedirectLoggingOverPipe( |
| 49 | __in_z LPCSTR szString, | 52 | __in_z LPCSTR szString, |
| @@ -72,28 +75,6 @@ static void CALLBACK BurnTraceError( | |||
| 72 | 75 | ||
| 73 | // function definitions | 76 | // function definitions |
| 74 | 77 | ||
| 75 | extern "C" BOOL EngineInCleanRoom( | ||
| 76 | __in_z_opt LPCWSTR wzCommandLine | ||
| 77 | ) | ||
| 78 | { | ||
| 79 | // Be very careful with the functions you call from here. | ||
| 80 | // This function will be called before ::SetDefaultDllDirectories() | ||
| 81 | // has been called so dependencies outside of kernel32.dll are | ||
| 82 | // very likely to introduce DLL hijacking opportunities. | ||
| 83 | |||
| 84 | static DWORD cchCleanRoomSwitch = lstrlenW(BURN_COMMANDLINE_SWITCH_CLEAN_ROOM); | ||
| 85 | |||
| 86 | // This check is wholly dependent on the clean room command line switch being | ||
| 87 | // present at the beginning of the command line. Since Burn is the only thing | ||
| 88 | // that should be setting this command line option, that is in our control. | ||
| 89 | BOOL fInCleanRoom = (wzCommandLine && | ||
| 90 | (wzCommandLine[0] == L'-' || wzCommandLine[0] == L'/') && | ||
| 91 | CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzCommandLine + 1, cchCleanRoomSwitch, BURN_COMMANDLINE_SWITCH_CLEAN_ROOM, cchCleanRoomSwitch) | ||
| 92 | ); | ||
| 93 | |||
| 94 | return fInCleanRoom; | ||
| 95 | } | ||
| 96 | |||
| 97 | extern "C" HRESULT EngineRun( | 78 | extern "C" HRESULT EngineRun( |
| 98 | __in HINSTANCE hInstance, | 79 | __in HINSTANCE hInstance, |
| 99 | __in HANDLE hEngineFile, | 80 | __in HANDLE hEngineFile, |
| @@ -113,7 +94,6 @@ extern "C" HRESULT EngineRun( | |||
| 113 | SYSTEM_INFO si = { }; | 94 | SYSTEM_INFO si = { }; |
| 114 | RTL_OSVERSIONINFOEXW ovix = { }; | 95 | RTL_OSVERSIONINFOEXW ovix = { }; |
| 115 | LPWSTR sczExePath = NULL; | 96 | LPWSTR sczExePath = NULL; |
| 116 | BOOL fRunUntrusted = FALSE; | ||
| 117 | BOOL fRunNormal = FALSE; | 97 | BOOL fRunNormal = FALSE; |
| 118 | BOOL fRunElevated = FALSE; | 98 | BOOL fRunElevated = FALSE; |
| 119 | BOOL fRunRunOnce = FALSE; | 99 | BOOL fRunRunOnce = FALSE; |
| @@ -214,25 +194,18 @@ extern "C" HRESULT EngineRun( | |||
| 214 | // Select run mode. | 194 | // Select run mode. |
| 215 | switch (engineState.internalCommand.mode) | 195 | switch (engineState.internalCommand.mode) |
| 216 | { | 196 | { |
| 217 | case BURN_MODE_UNTRUSTED: | ||
| 218 | fRunUntrusted = TRUE; | ||
| 219 | |||
| 220 | hr = RunUntrusted(&engineState); | ||
| 221 | ExitOnFailure(hr, "Failed to run untrusted mode."); | ||
| 222 | break; | ||
| 223 | |||
| 224 | case BURN_MODE_NORMAL: | 197 | case BURN_MODE_NORMAL: |
| 225 | fRunNormal = TRUE; | 198 | fRunNormal = TRUE; |
| 226 | 199 | ||
| 227 | hr = RunNormal(hInstance, &engineState); | 200 | hr = RunNormal(hInstance, &engineState); |
| 228 | ExitOnFailure(hr, "Failed to run per-user mode."); | 201 | ExitOnFailure(hr, "Failed to run normal mode."); |
| 229 | break; | 202 | break; |
| 230 | 203 | ||
| 231 | case BURN_MODE_ELEVATED: | 204 | case BURN_MODE_ELEVATED: |
| 232 | fRunElevated = TRUE; | 205 | fRunElevated = TRUE; |
| 233 | 206 | ||
| 234 | hr = RunElevated(hInstance, wzCommandLine, &engineState); | 207 | hr = RunElevated(hInstance, wzCommandLine, &engineState); |
| 235 | ExitOnFailure(hr, "Failed to run per-machine mode."); | 208 | ExitOnFailure(hr, "Failed to run elevated mode."); |
| 236 | break; | 209 | break; |
| 237 | 210 | ||
| 238 | case BURN_MODE_EMBEDDED: | 211 | case BURN_MODE_EMBEDDED: |
| @@ -266,7 +239,7 @@ LExit: | |||
| 266 | LoggingOpenFailed(); | 239 | LoggingOpenFailed(); |
| 267 | } | 240 | } |
| 268 | 241 | ||
| 269 | UserExperienceRemove(&engineState.userExperience); | 242 | BootstrapperApplicationRemove(&engineState.userExperience); |
| 270 | 243 | ||
| 271 | CacheRemoveBaseWorkingFolder(&engineState.cache); | 244 | CacheRemoveBaseWorkingFolder(&engineState.cache); |
| 272 | CacheUninitialize(&engineState.cache); | 245 | CacheUninitialize(&engineState.cache); |
| @@ -284,10 +257,6 @@ LExit: | |||
| 284 | { | 257 | { |
| 285 | LogId(REPORT_STANDARD, MSG_EXITING, FAILED(hr) ? (int)hr : *pdwExitCode, LoggingBoolToString(engineState.fRestart)); | 258 | LogId(REPORT_STANDARD, MSG_EXITING, FAILED(hr) ? (int)hr : *pdwExitCode, LoggingBoolToString(engineState.fRestart)); |
| 286 | } | 259 | } |
| 287 | else if (fRunUntrusted) | ||
| 288 | { | ||
| 289 | LogId(REPORT_STANDARD, MSG_EXITING_CLEAN_ROOM, FAILED(hr) ? (int)hr : *pdwExitCode); | ||
| 290 | } | ||
| 291 | else if (fRunRunOnce) | 260 | else if (fRunRunOnce) |
| 292 | { | 261 | { |
| 293 | LogId(REPORT_STANDARD, MSG_EXITING_RUN_ONCE, FAILED(hr) ? (int)hr : *pdwExitCode); | 262 | LogId(REPORT_STANDARD, MSG_EXITING_RUN_ONCE, FAILED(hr) ? (int)hr : *pdwExitCode); |
| @@ -452,7 +421,7 @@ static void UninitializeEngineState( | |||
| 452 | BurnExtensionUninitialize(&pEngineState->extensions); | 421 | BurnExtensionUninitialize(&pEngineState->extensions); |
| 453 | 422 | ||
| 454 | ::DeleteCriticalSection(&pEngineState->userExperience.csEngineActive); | 423 | ::DeleteCriticalSection(&pEngineState->userExperience.csEngineActive); |
| 455 | UserExperienceUninitialize(&pEngineState->userExperience); | 424 | BootstrapperApplicationUninitialize(&pEngineState->userExperience); |
| 456 | 425 | ||
| 457 | ApprovedExesUninitialize(&pEngineState->approvedExes); | 426 | ApprovedExesUninitialize(&pEngineState->approvedExes); |
| 458 | DependencyUninitialize(&pEngineState->dependencies); | 427 | DependencyUninitialize(&pEngineState->dependencies); |
| @@ -475,7 +444,6 @@ static void UninitializeEngineState( | |||
| 475 | ReleaseStr(pEngineState->internalCommand.sczIgnoreDependencies); | 444 | ReleaseStr(pEngineState->internalCommand.sczIgnoreDependencies); |
| 476 | ReleaseStr(pEngineState->internalCommand.sczLogFile); | 445 | ReleaseStr(pEngineState->internalCommand.sczLogFile); |
| 477 | ReleaseStr(pEngineState->internalCommand.sczOriginalSource); | 446 | ReleaseStr(pEngineState->internalCommand.sczOriginalSource); |
| 478 | ReleaseStr(pEngineState->internalCommand.sczSourceProcessPath); | ||
| 479 | ReleaseStr(pEngineState->internalCommand.sczEngineWorkingDirectory); | 447 | ReleaseStr(pEngineState->internalCommand.sczEngineWorkingDirectory); |
| 480 | 448 | ||
| 481 | ReleaseStr(pEngineState->log.sczExtension); | 449 | ReleaseStr(pEngineState->log.sczExtension); |
| @@ -489,82 +457,6 @@ static void UninitializeEngineState( | |||
| 489 | memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE)); | 457 | memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE)); |
| 490 | } | 458 | } |
| 491 | 459 | ||
| 492 | static HRESULT RunUntrusted( | ||
| 493 | __in BURN_ENGINE_STATE* pEngineState | ||
| 494 | ) | ||
| 495 | { | ||
| 496 | HRESULT hr = S_OK; | ||
| 497 | LPWSTR sczCurrentProcessPath = NULL; | ||
| 498 | LPWSTR wzCleanRoomBundlePath = NULL; | ||
| 499 | LPWSTR sczCachedCleanRoomBundlePath = NULL; | ||
| 500 | LPWSTR sczParameters = NULL; | ||
| 501 | LPWSTR sczFullCommandLine = NULL; | ||
| 502 | PROCESS_INFORMATION pi = { }; | ||
| 503 | HANDLE hFileAttached = NULL; | ||
| 504 | HANDLE hFileSelf = NULL; | ||
| 505 | HANDLE hProcess = NULL; | ||
| 506 | |||
| 507 | // Initialize logging. | ||
| 508 | hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName); | ||
| 509 | ExitOnFailure(hr, "Failed to open clean room log."); | ||
| 510 | |||
| 511 | hr = PathForCurrentProcess(&sczCurrentProcessPath, NULL); | ||
| 512 | ExitOnFailure(hr, "Failed to get path for current process."); | ||
| 513 | |||
| 514 | // If we're running from the package cache, we're in a secure | ||
| 515 | // folder (DLLs cannot be inserted here for hijacking purposes) | ||
| 516 | // so just launch the current process's path as the clean room | ||
| 517 | // process. Technically speaking, we'd be able to skip creating | ||
| 518 | // a clean room process at all (since we're already running from | ||
| 519 | // a secure folder) but it makes the code that only wants to run | ||
| 520 | // in clean room more complicated if we don't launch an explicit | ||
| 521 | // clean room process. | ||
| 522 | if (CacheBundleRunningFromCache(&pEngineState->cache)) | ||
| 523 | { | ||
| 524 | wzCleanRoomBundlePath = sczCurrentProcessPath; | ||
| 525 | } | ||
| 526 | else | ||
| 527 | { | ||
| 528 | hr = CacheBundleToCleanRoom(&pEngineState->cache, &pEngineState->section, &sczCachedCleanRoomBundlePath); | ||
| 529 | ExitOnFailure(hr, "Failed to cache to clean room."); | ||
| 530 | |||
| 531 | wzCleanRoomBundlePath = sczCachedCleanRoomBundlePath; | ||
| 532 | } | ||
| 533 | |||
| 534 | hr = CoreCreateCleanRoomCommandLine(&sczParameters, pEngineState, wzCleanRoomBundlePath, sczCurrentProcessPath, &hFileAttached, &hFileSelf); | ||
| 535 | ExitOnFailure(hr, "Failed to create clean room command-line."); | ||
| 536 | |||
| 537 | hr = StrAllocFormattedSecure(&sczFullCommandLine, L"\"%ls\" %ls", wzCleanRoomBundlePath, sczParameters); | ||
| 538 | ExitOnFailure(hr, "Failed to allocate full command-line."); | ||
| 539 | |||
| 540 | hr = CoreCreateProcess(wzCleanRoomBundlePath, sczFullCommandLine, TRUE, 0, NULL, static_cast<WORD>(pEngineState->command.nCmdShow), &pi); | ||
| 541 | ExitOnFailure(hr, "Failed to launch clean room process: %ls", sczFullCommandLine); | ||
| 542 | |||
| 543 | hProcess = pi.hProcess; | ||
| 544 | pi.hProcess = NULL; | ||
| 545 | |||
| 546 | hr = ProcWaitForCompletion(hProcess, INFINITE, &pEngineState->userExperience.dwExitCode); | ||
| 547 | ExitOnFailure(hr, "Failed to wait for clean room process: %ls", wzCleanRoomBundlePath); | ||
| 548 | |||
| 549 | LExit: | ||
| 550 | // If the splash screen is still around, close it. | ||
| 551 | if (::IsWindow(pEngineState->command.hwndSplashScreen)) | ||
| 552 | { | ||
| 553 | ::PostMessageW(pEngineState->command.hwndSplashScreen, WM_CLOSE, 0, 0); | ||
| 554 | } | ||
| 555 | |||
| 556 | ReleaseHandle(pi.hThread); | ||
| 557 | ReleaseFileHandle(hFileSelf); | ||
| 558 | ReleaseFileHandle(hFileAttached); | ||
| 559 | ReleaseHandle(hProcess); | ||
| 560 | StrSecureZeroFreeString(sczFullCommandLine); | ||
| 561 | StrSecureZeroFreeString(sczParameters); | ||
| 562 | ReleaseStr(sczCachedCleanRoomBundlePath); | ||
| 563 | ReleaseStr(sczCurrentProcessPath); | ||
| 564 | |||
| 565 | return hr; | ||
| 566 | } | ||
| 567 | |||
| 568 | static HRESULT RunNormal( | 460 | static HRESULT RunNormal( |
| 569 | __in HINSTANCE hInstance, | 461 | __in HINSTANCE hInstance, |
| 570 | __in BURN_ENGINE_STATE* pEngineState | 462 | __in BURN_ENGINE_STATE* pEngineState |
| @@ -574,9 +466,10 @@ static HRESULT RunNormal( | |||
| 574 | LPWSTR sczOriginalSource = NULL; | 466 | LPWSTR sczOriginalSource = NULL; |
| 575 | LPWSTR sczCopiedOriginalSource = NULL; | 467 | LPWSTR sczCopiedOriginalSource = NULL; |
| 576 | BOOL fContinueExecution = TRUE; | 468 | BOOL fContinueExecution = TRUE; |
| 577 | BOOL fReloadApp = FALSE; | 469 | BOOL fReloadApp = TRUE; |
| 578 | BOOL fSkipCleanup = FALSE; | 470 | BOOL fSkipCleanup = FALSE; |
| 579 | BURN_EXTENSION_ENGINE_CONTEXT extensionEngineContext = { }; | 471 | BURN_EXTENSION_ENGINE_CONTEXT extensionEngineContext = { }; |
| 472 | BOOL fRunSecondaryBootstrapperApplication = FALSE; | ||
| 580 | 473 | ||
| 581 | // Initialize logging. | 474 | // Initialize logging. |
| 582 | hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName); | 475 | hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName); |
| @@ -644,14 +537,27 @@ static HRESULT RunNormal( | |||
| 644 | hr = BurnExtensionLoad(&pEngineState->extensions, &extensionEngineContext); | 537 | hr = BurnExtensionLoad(&pEngineState->extensions, &extensionEngineContext); |
| 645 | ExitOnFailure(hr, "Failed to load BundleExtensions."); | 538 | ExitOnFailure(hr, "Failed to load BundleExtensions."); |
| 646 | 539 | ||
| 647 | do | 540 | // The secondary bootstrapper application only gets one chance to execute. That means |
| 541 | // first time through we run the primary bootstrapper application and on reload we run | ||
| 542 | // the secondary bootstrapper application, and if the secondary bootstrapper application | ||
| 543 | // requests a reload, we load the primary bootstrapper application one last time. | ||
| 544 | for (DWORD i = 0; i < 3 && fReloadApp; i++) | ||
| 648 | { | 545 | { |
| 649 | fReloadApp = FALSE; | 546 | fReloadApp = FALSE; |
| 650 | pEngineState->fQuit = FALSE; | 547 | pEngineState->fQuit = FALSE; |
| 651 | 548 | ||
| 652 | hr = RunApplication(pEngineState, &fReloadApp, &fSkipCleanup); | 549 | hr = RunApplication(pEngineState, fRunSecondaryBootstrapperApplication, &fReloadApp, &fSkipCleanup); |
| 653 | ExitOnFailure(hr, "Failed while running "); | 550 | |
| 654 | } while (fReloadApp); | 551 | // If reloading, switch to the other bootstrapper application. |
| 552 | if (fReloadApp) | ||
| 553 | { | ||
| 554 | fRunSecondaryBootstrapperApplication = !fRunSecondaryBootstrapperApplication; | ||
| 555 | } | ||
| 556 | else if (FAILED(hr)) | ||
| 557 | { | ||
| 558 | break; | ||
| 559 | } | ||
| 560 | } | ||
| 655 | 561 | ||
| 656 | LExit: | 562 | LExit: |
| 657 | if (!fSkipCleanup) | 563 | if (!fSkipCleanup) |
| @@ -790,73 +696,64 @@ LExit: | |||
| 790 | return hr; | 696 | return hr; |
| 791 | } | 697 | } |
| 792 | 698 | ||
| 793 | static void CALLBACK FreeQueueItem( | ||
| 794 | __in void* pvValue, | ||
| 795 | __in void* /*pvContext*/ | ||
| 796 | ) | ||
| 797 | { | ||
| 798 | BOOTSTRAPPER_ENGINE_ACTION* pAction = reinterpret_cast<BOOTSTRAPPER_ENGINE_ACTION*>(pvValue); | ||
| 799 | |||
| 800 | LogId(REPORT_WARNING, MSG_IGNORE_OPERATION_AFTER_QUIT, LoggingBurnMessageToString(pAction->dwMessage)); | ||
| 801 | |||
| 802 | CoreBootstrapperEngineActionUninitialize(pAction); | ||
| 803 | MemFree(pAction); | ||
| 804 | } | ||
| 805 | |||
| 806 | static HRESULT RunApplication( | 699 | static HRESULT RunApplication( |
| 807 | __in BURN_ENGINE_STATE* pEngineState, | 700 | __in BURN_ENGINE_STATE* pEngineState, |
| 701 | __in BOOL fSecondaryBootstrapperApplication, | ||
| 808 | __out BOOL* pfReloadApp, | 702 | __out BOOL* pfReloadApp, |
| 809 | __out BOOL* pfSkipCleanup | 703 | __out BOOL* pfSkipCleanup |
| 810 | ) | 704 | ) |
| 811 | { | 705 | { |
| 812 | HRESULT hr = S_OK; | 706 | HRESULT hr = S_OK; |
| 813 | BOOTSTRAPPER_ENGINE_CONTEXT engineContext = { }; | ||
| 814 | BOOL fStartupCalled = FALSE; | 707 | BOOL fStartupCalled = FALSE; |
| 708 | BAENGINE_CONTEXT* pEngineContext = NULL; | ||
| 709 | HANDLE rghWait[2] = { }; | ||
| 710 | DWORD dwSignaled = 0; | ||
| 711 | BAENGINE_ACTION* pAction = NULL; | ||
| 815 | BOOTSTRAPPER_SHUTDOWN_ACTION shutdownAction = BOOTSTRAPPER_SHUTDOWN_ACTION_NONE; | 712 | BOOTSTRAPPER_SHUTDOWN_ACTION shutdownAction = BOOTSTRAPPER_SHUTDOWN_ACTION_NONE; |
| 816 | BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL; | ||
| 817 | |||
| 818 | // Setup the bootstrapper engine. | ||
| 819 | engineContext.pEngineState = pEngineState; | ||
| 820 | 713 | ||
| 821 | ::InitializeCriticalSection(&engineContext.csQueue); | 714 | // Start the bootstrapper application. |
| 822 | 715 | hr = BootstrapperApplicationStart(pEngineState, fSecondaryBootstrapperApplication); | |
| 823 | engineContext.hQueueSemaphore = ::CreateSemaphoreW(NULL, 0, LONG_MAX, NULL); | 716 | ExitOnFailure(hr, "Failed to start bootstrapper application."); |
| 824 | ExitOnNullWithLastError(engineContext.hQueueSemaphore, hr, "Failed to create semaphore for queue."); | ||
| 825 | |||
| 826 | hr = QueCreate(&engineContext.hQueue); | ||
| 827 | ExitOnFailure(hr, "Failed to create queue for bootstrapper engine."); | ||
| 828 | 717 | ||
| 829 | // Load the bootstrapper application. | 718 | pEngineContext = pEngineState->userExperience.pEngineContext; |
| 830 | hr = UserExperienceLoad(&pEngineState->userExperience, &engineContext, &pEngineState->command); | ||
| 831 | ExitOnFailure(hr, "Failed to load BA."); | ||
| 832 | 719 | ||
| 833 | fStartupCalled = TRUE; | 720 | fStartupCalled = TRUE; |
| 834 | hr = UserExperienceOnStartup(&pEngineState->userExperience); | 721 | hr = BACallbackOnStartup(&pEngineState->userExperience); |
| 835 | ExitOnFailure(hr, "Failed to start bootstrapper application."); | 722 | ExitOnFailure(hr, "Failed to start bootstrapper application."); |
| 836 | 723 | ||
| 724 | rghWait[0] = pEngineState->userExperience.hBAProcess; | ||
| 725 | rghWait[1] = pEngineContext->hQueueSemaphore; | ||
| 726 | |||
| 837 | while (!pEngineState->fQuit) | 727 | while (!pEngineState->fQuit) |
| 838 | { | 728 | { |
| 839 | hr = AppWaitForSingleObject(engineContext.hQueueSemaphore, INFINITE); | 729 | hr = AppWaitForMultipleObjects(countof(rghWait), rghWait, FALSE, INFINITE, &dwSignaled); |
| 840 | ExitOnFailure(hr, "Failed to wait on queue event."); | 730 | ExitOnFailure(hr, "Failed to wait on queue event."); |
| 841 | 731 | ||
| 842 | ::EnterCriticalSection(&engineContext.csQueue); | 732 | // If the bootstrapper application process exited, bail. |
| 733 | if (0 == dwSignaled) | ||
| 734 | { | ||
| 735 | pEngineState->fQuit = TRUE; | ||
| 736 | break; | ||
| 737 | } | ||
| 738 | |||
| 739 | ::EnterCriticalSection(&pEngineContext->csQueue); | ||
| 843 | 740 | ||
| 844 | hr = QueDequeue(engineContext.hQueue, reinterpret_cast<void**>(&pAction)); | 741 | hr = QueDequeue(pEngineContext->hQueue, reinterpret_cast<void**>(&pAction)); |
| 845 | 742 | ||
| 846 | ::LeaveCriticalSection(&engineContext.csQueue); | 743 | ::LeaveCriticalSection(&pEngineContext->csQueue); |
| 847 | 744 | ||
| 848 | ExitOnFailure(hr, "Failed to dequeue action."); | 745 | ExitOnFailure(hr, "Failed to dequeue action."); |
| 849 | 746 | ||
| 850 | ProcessMessage(&engineContext, pAction); | 747 | ProcessMessage(pEngineContext, pAction); |
| 851 | 748 | ||
| 852 | CoreBootstrapperEngineActionUninitialize(pAction); | 749 | BAEngineFreeAction(pAction); |
| 853 | MemFree(pAction); | 750 | pAction = NULL; |
| 854 | } | 751 | } |
| 855 | 752 | ||
| 856 | LExit: | 753 | LExit: |
| 857 | if (fStartupCalled) | 754 | if (fStartupCalled) |
| 858 | { | 755 | { |
| 859 | UserExperienceOnShutdown(&pEngineState->userExperience, &shutdownAction); | 756 | BACallbackOnShutdown(&pEngineState->userExperience, &shutdownAction); |
| 860 | if (BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART == shutdownAction) | 757 | if (BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART == shutdownAction) |
| 861 | { | 758 | { |
| 862 | LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RESTART, LoggingBoolToString(pEngineState->fRestart)); | 759 | LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RESTART, LoggingBoolToString(pEngineState->fRestart)); |
| @@ -873,26 +770,34 @@ LExit: | |||
| 873 | *pfSkipCleanup = TRUE; | 770 | *pfSkipCleanup = TRUE; |
| 874 | } | 771 | } |
| 875 | } | 772 | } |
| 773 | else // if the bootstrapper application did not start, there won't be anything to clean up. | ||
| 774 | { | ||
| 775 | *pfSkipCleanup = TRUE; | ||
| 776 | } | ||
| 876 | 777 | ||
| 877 | // Unload BA. | 778 | // Stop the BA. |
| 878 | UserExperienceUnload(&pEngineState->userExperience, *pfReloadApp); | 779 | BootstrapperApplicationStop(&pEngineState->userExperience, pfReloadApp); |
| 879 | 780 | ||
| 880 | ::DeleteCriticalSection(&engineContext.csQueue); | 781 | if (*pfReloadApp && !pEngineState->userExperience.pSecondaryExePayload) |
| 881 | ReleaseHandle(engineContext.hQueueSemaphore); | 782 | { |
| 882 | ReleaseQueue(engineContext.hQueue, FreeQueueItem, &engineContext); | 783 | // If the BA requested a reload but we do not have a secondary EXE, |
| 784 | // then log a message and do not reload. | ||
| 785 | LogId(REPORT_STANDARD, MSG_BA_NO_SECONDARY_BOOSTRAPPER_SO_RELOAD_NOT_SUPPORTED); | ||
| 786 | *pfReloadApp = FALSE; | ||
| 787 | } | ||
| 883 | 788 | ||
| 884 | return hr; | 789 | return hr; |
| 885 | } | 790 | } |
| 886 | 791 | ||
| 887 | static HRESULT ProcessMessage( | 792 | static HRESULT ProcessMessage( |
| 888 | __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext, | 793 | __in BAENGINE_CONTEXT* pEngineContext, |
| 889 | __in BOOTSTRAPPER_ENGINE_ACTION* pAction | 794 | __in BAENGINE_ACTION* pAction |
| 890 | ) | 795 | ) |
| 891 | { | 796 | { |
| 892 | HRESULT hr = S_OK; | 797 | HRESULT hr = S_OK; |
| 893 | BURN_ENGINE_STATE* pEngineState = pEngineContext->pEngineState; | 798 | BURN_ENGINE_STATE* pEngineState = pEngineContext->pEngineState; |
| 894 | 799 | ||
| 895 | UserExperienceActivateEngine(&pEngineState->userExperience); | 800 | BootstrapperApplicationActivateEngine(&pEngineState->userExperience); |
| 896 | 801 | ||
| 897 | switch (pAction->dwMessage) | 802 | switch (pAction->dwMessage) |
| 898 | { | 803 | { |
| @@ -921,7 +826,7 @@ static HRESULT ProcessMessage( | |||
| 921 | break; | 826 | break; |
| 922 | } | 827 | } |
| 923 | 828 | ||
| 924 | UserExperienceDeactivateEngine(&pEngineState->userExperience); | 829 | BootstrapperApplicationDeactivateEngine(&pEngineState->userExperience); |
| 925 | 830 | ||
| 926 | return hr; | 831 | return hr; |
| 927 | } | 832 | } |
| @@ -971,7 +876,7 @@ static HRESULT LogStringOverPipe( | |||
| 971 | hr = (HRESULT)dwResult; | 876 | hr = (HRESULT)dwResult; |
| 972 | 877 | ||
| 973 | LExit: | 878 | LExit: |
| 974 | ReleaseBuffer(pbData); | 879 | ReleaseMem(pbData); |
| 975 | 880 | ||
| 976 | return hr; | 881 | return hr; |
| 977 | } | 882 | } |
