summaryrefslogtreecommitdiff
path: root/src/burn/engine/engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/engine.cpp')
-rw-r--r--src/burn/engine/engine.cpp95
1 files changed, 53 insertions, 42 deletions
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index 48196655..c9d2bdcd 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -42,8 +42,8 @@ static HRESULT RunApplication(
42 __out BOOL* pfSkipCleanup 42 __out BOOL* pfSkipCleanup
43 ); 43 );
44static HRESULT ProcessMessage( 44static HRESULT ProcessMessage(
45 __in BURN_ENGINE_STATE* pEngineState, 45 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
46 __in const MSG* pmsg 46 __in BOOTSTRAPPER_ENGINE_ACTION* pAction
47 ); 47 );
48static HRESULT DAPI RedirectLoggingOverPipe( 48static HRESULT DAPI RedirectLoggingOverPipe(
49 __in_z LPCSTR szString, 49 __in_z LPCSTR szString,
@@ -790,6 +790,19 @@ LExit:
790 return hr; 790 return hr;
791} 791}
792 792
793static 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
793static HRESULT RunApplication( 806static HRESULT RunApplication(
794 __in BURN_ENGINE_STATE* pEngineState, 807 __in BURN_ENGINE_STATE* pEngineState,
795 __out BOOL* pfReloadApp, 808 __out BOOL* pfReloadApp,
@@ -799,16 +812,20 @@ static HRESULT RunApplication(
799 HRESULT hr = S_OK; 812 HRESULT hr = S_OK;
800 BOOTSTRAPPER_ENGINE_CONTEXT engineContext = { }; 813 BOOTSTRAPPER_ENGINE_CONTEXT engineContext = { };
801 BOOL fStartupCalled = FALSE; 814 BOOL fStartupCalled = FALSE;
802 BOOL fRet = FALSE;
803 MSG msg = { };
804 BOOTSTRAPPER_SHUTDOWN_ACTION shutdownAction = BOOTSTRAPPER_SHUTDOWN_ACTION_NONE; 815 BOOTSTRAPPER_SHUTDOWN_ACTION shutdownAction = BOOTSTRAPPER_SHUTDOWN_ACTION_NONE;
805 816 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
806 ::PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
807 817
808 // Setup the bootstrapper engine. 818 // Setup the bootstrapper engine.
809 engineContext.dwThreadId = ::GetCurrentThreadId();
810 engineContext.pEngineState = pEngineState; 819 engineContext.pEngineState = pEngineState;
811 820
821 ::InitializeCriticalSection(&engineContext.csQueue);
822
823 engineContext.hQueueSemaphore = ::CreateSemaphoreW(NULL, 0, LONG_MAX, NULL);
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
812 // Load the bootstrapper application. 829 // Load the bootstrapper application.
813 hr = UserExperienceLoad(&pEngineState->userExperience, &engineContext, &pEngineState->command); 830 hr = UserExperienceLoad(&pEngineState->userExperience, &engineContext, &pEngineState->command);
814 ExitOnFailure(hr, "Failed to load BA."); 831 ExitOnFailure(hr, "Failed to load BA.");
@@ -817,28 +834,24 @@ static HRESULT RunApplication(
817 hr = UserExperienceOnStartup(&pEngineState->userExperience); 834 hr = UserExperienceOnStartup(&pEngineState->userExperience);
818 ExitOnFailure(hr, "Failed to start bootstrapper application."); 835 ExitOnFailure(hr, "Failed to start bootstrapper application.");
819 836
820 // Enter the message pump. 837 while (!pEngineState->fQuit)
821 while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
822 { 838 {
823 if (-1 == fRet) 839 hr = AppWaitForSingleObject(engineContext.hQueueSemaphore, INFINITE);
824 { 840 ExitOnFailure(hr, "Failed to wait on queue event.");
825 hr = E_UNEXPECTED;
826 ExitOnRootFailure(hr, "Unexpected return value from message pump.");
827 }
828 else
829 {
830 // When the BA makes a request from its own thread, it's common for the PostThreadMessage in externalengine.cpp
831 // to block until this thread waits on something. It's also common for Detect and Plan to never wait on something.
832 // In the extreme case, the engine could be elevating in Apply before the Detect call returned to the BA.
833 // This helps to avoid that situation, which could be blocking a UI thread.
834 ::Sleep(0);
835 841
836 ProcessMessage(pEngineState, &msg); 842 ::EnterCriticalSection(&engineContext.csQueue);
837 } 843
838 } 844 hr = QueDequeue(engineContext.hQueue, reinterpret_cast<void**>(&pAction));
845
846 ::LeaveCriticalSection(&engineContext.csQueue);
839 847
840 // Get exit code. 848 ExitOnFailure(hr, "Failed to dequeue action.");
841 pEngineState->userExperience.dwExitCode = (DWORD)msg.wParam; 849
850 ProcessMessage(&engineContext, pAction);
851
852 CoreBootstrapperEngineActionUninitialize(pAction);
853 MemFree(pAction);
854 }
842 855
843LExit: 856LExit:
844 if (fStartupCalled) 857 if (fStartupCalled)
@@ -864,52 +877,50 @@ LExit:
864 // Unload BA. 877 // Unload BA.
865 UserExperienceUnload(&pEngineState->userExperience, *pfReloadApp); 878 UserExperienceUnload(&pEngineState->userExperience, *pfReloadApp);
866 879
880 ::DeleteCriticalSection(&engineContext.csQueue);
881 ReleaseHandle(engineContext.hQueueSemaphore);
882 ReleaseQueue(engineContext.hQueue, FreeQueueItem, &engineContext);
883
867 return hr; 884 return hr;
868} 885}
869 886
870static HRESULT ProcessMessage( 887static HRESULT ProcessMessage(
871 __in BURN_ENGINE_STATE* pEngineState, 888 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
872 __in const MSG* pmsg 889 __in BOOTSTRAPPER_ENGINE_ACTION* pAction
873 ) 890 )
874{ 891{
875 HRESULT hr = S_OK; 892 HRESULT hr = S_OK;
893 BURN_ENGINE_STATE* pEngineState = pEngineContext->pEngineState;
876 894
877 UserExperienceActivateEngine(&pEngineState->userExperience); 895 UserExperienceActivateEngine(&pEngineState->userExperience);
878 896
879 if (pEngineState->fQuit) 897 switch (pAction->dwMessage)
880 {
881 LogId(REPORT_WARNING, MSG_IGNORE_OPERATION_AFTER_QUIT, LoggingBurnMessageToString(pmsg->message));
882 ExitFunction1(hr = E_INVALIDSTATE);
883 }
884
885 switch (pmsg->message)
886 { 898 {
887 case WM_BURN_DETECT: 899 case WM_BURN_DETECT:
888 hr = CoreDetect(pEngineState, reinterpret_cast<HWND>(pmsg->lParam)); 900 hr = CoreDetect(pEngineState, pAction->detect.hwndParent);
889 break; 901 break;
890 902
891 case WM_BURN_PLAN: 903 case WM_BURN_PLAN:
892 hr = CorePlan(pEngineState, static_cast<BOOTSTRAPPER_ACTION>(pmsg->lParam)); 904 hr = CorePlan(pEngineState, pAction->plan.action);
893 break; 905 break;
894 906
895 case WM_BURN_ELEVATE: 907 case WM_BURN_ELEVATE:
896 hr = CoreElevate(pEngineState, WM_BURN_ELEVATE, reinterpret_cast<HWND>(pmsg->lParam)); 908 hr = CoreElevate(pEngineState, WM_BURN_ELEVATE, pAction->elevate.hwndParent);
897 break; 909 break;
898 910
899 case WM_BURN_APPLY: 911 case WM_BURN_APPLY:
900 hr = CoreApply(pEngineState, reinterpret_cast<HWND>(pmsg->lParam)); 912 hr = CoreApply(pEngineState, pAction->apply.hwndParent);
901 break; 913 break;
902 914
903 case WM_BURN_LAUNCH_APPROVED_EXE: 915 case WM_BURN_LAUNCH_APPROVED_EXE:
904 hr = CoreLaunchApprovedExe(pEngineState, reinterpret_cast<BURN_LAUNCH_APPROVED_EXE*>(pmsg->lParam)); 916 hr = CoreLaunchApprovedExe(pEngineState, &pAction->launchApprovedExe);
905 break; 917 break;
906 918
907 case WM_BURN_QUIT: 919 case WM_BURN_QUIT:
908 hr = CoreQuit(pEngineState, static_cast<int>(pmsg->wParam)); 920 CoreQuit(pEngineContext, pAction->quit.dwExitCode);
909 break; 921 break;
910 } 922 }
911 923
912LExit:
913 UserExperienceDeactivateEngine(&pEngineState->userExperience); 924 UserExperienceDeactivateEngine(&pEngineState->userExperience);
914 925
915 return hr; 926 return hr;