aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-10-19 15:44:40 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-10-25 15:13:06 -0500
commit98080672cdbbde00ea40a96c1ce38e8a52f24fee (patch)
tree9c0b859f147d55d5c4caadccfd764ca84ed7e648 /src/burn
parent28e9c7c14d2a156b55476f6b8e39e13f17aa87b6 (diff)
downloadwix-98080672cdbbde00ea40a96c1ce38e8a52f24fee.tar.gz
wix-98080672cdbbde00ea40a96c1ce38e8a52f24fee.tar.bz2
wix-98080672cdbbde00ea40a96c1ce38e8a52f24fee.zip
Add queutil so Burn can manage its own queue of BA requested actions.
Fixes 6349
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/EngineForApplication.cpp12
-rw-r--r--src/burn/engine/EngineForApplication.h33
-rw-r--r--src/burn/engine/approvedexe.cpp1
-rw-r--r--src/burn/engine/core.cpp31
-rw-r--r--src/burn/engine/core.h9
-rw-r--r--src/burn/engine/elevation.cpp5
-rw-r--r--src/burn/engine/engine.cpp95
-rw-r--r--src/burn/engine/externalengine.cpp166
-rw-r--r--src/burn/engine/externalengine.h14
-rw-r--r--src/burn/engine/platform.h1
-rw-r--r--src/burn/engine/precomp.h1
11 files changed, 244 insertions, 124 deletions
diff --git a/src/burn/engine/EngineForApplication.cpp b/src/burn/engine/EngineForApplication.cpp
index 27f815c6..45bfaf83 100644
--- a/src/burn/engine/EngineForApplication.cpp
+++ b/src/burn/engine/EngineForApplication.cpp
@@ -325,7 +325,7 @@ static HRESULT BAEngineDetect(
325 ValidateMessageArgs(hr, pvArgs, BAENGINE_DETECT_ARGS, pArgs); 325 ValidateMessageArgs(hr, pvArgs, BAENGINE_DETECT_ARGS, pArgs);
326 ValidateMessageResults(hr, pvResults, BAENGINE_DETECT_RESULTS, pResults); 326 ValidateMessageResults(hr, pvResults, BAENGINE_DETECT_RESULTS, pResults);
327 327
328 hr = ExternalEngineDetect(pContext->dwThreadId, pArgs->hwndParent); 328 hr = ExternalEngineDetect(pContext, pArgs->hwndParent);
329 329
330LExit: 330LExit:
331 return hr; 331 return hr;
@@ -341,7 +341,7 @@ static HRESULT BAEnginePlan(
341 ValidateMessageArgs(hr, pvArgs, BAENGINE_PLAN_ARGS, pArgs); 341 ValidateMessageArgs(hr, pvArgs, BAENGINE_PLAN_ARGS, pArgs);
342 ValidateMessageResults(hr, pvResults, BAENGINE_PLAN_RESULTS, pResults); 342 ValidateMessageResults(hr, pvResults, BAENGINE_PLAN_RESULTS, pResults);
343 343
344 hr = ExternalEnginePlan(pContext->dwThreadId, pArgs->action); 344 hr = ExternalEnginePlan(pContext, pArgs->action);
345 345
346LExit: 346LExit:
347 return hr; 347 return hr;
@@ -357,7 +357,7 @@ static HRESULT BAEngineElevate(
357 ValidateMessageArgs(hr, pvArgs, BAENGINE_ELEVATE_ARGS, pArgs); 357 ValidateMessageArgs(hr, pvArgs, BAENGINE_ELEVATE_ARGS, pArgs);
358 ValidateMessageResults(hr, pvResults, BAENGINE_ELEVATE_RESULTS, pResults); 358 ValidateMessageResults(hr, pvResults, BAENGINE_ELEVATE_RESULTS, pResults);
359 359
360 hr = ExternalEngineElevate(pContext->pEngineState, pContext->dwThreadId, pArgs->hwndParent); 360 hr = ExternalEngineElevate(pContext, pArgs->hwndParent);
361 361
362LExit: 362LExit:
363 return hr; 363 return hr;
@@ -373,7 +373,7 @@ static HRESULT BAEngineApply(
373 ValidateMessageArgs(hr, pvArgs, BAENGINE_APPLY_ARGS, pArgs); 373 ValidateMessageArgs(hr, pvArgs, BAENGINE_APPLY_ARGS, pArgs);
374 ValidateMessageResults(hr, pvResults, BAENGINE_APPLY_RESULTS, pResults); 374 ValidateMessageResults(hr, pvResults, BAENGINE_APPLY_RESULTS, pResults);
375 375
376 hr = ExternalEngineApply(pContext->dwThreadId, pArgs->hwndParent); 376 hr = ExternalEngineApply(pContext, pArgs->hwndParent);
377 377
378LExit: 378LExit:
379 return hr; 379 return hr;
@@ -389,7 +389,7 @@ static HRESULT BAEngineQuit(
389 ValidateMessageArgs(hr, pvArgs, BAENGINE_QUIT_ARGS, pArgs); 389 ValidateMessageArgs(hr, pvArgs, BAENGINE_QUIT_ARGS, pArgs);
390 ValidateMessageResults(hr, pvResults, BAENGINE_QUIT_RESULTS, pResults); 390 ValidateMessageResults(hr, pvResults, BAENGINE_QUIT_RESULTS, pResults);
391 391
392 hr = ExternalEngineQuit(pContext->dwThreadId, pArgs->dwExitCode); 392 hr = ExternalEngineQuit(pContext, pArgs->dwExitCode);
393 393
394LExit: 394LExit:
395 return hr; 395 return hr;
@@ -405,7 +405,7 @@ static HRESULT BAEngineLaunchApprovedExe(
405 ValidateMessageArgs(hr, pvArgs, BAENGINE_LAUNCHAPPROVEDEXE_ARGS, pArgs); 405 ValidateMessageArgs(hr, pvArgs, BAENGINE_LAUNCHAPPROVEDEXE_ARGS, pArgs);
406 ValidateMessageResults(hr, pvResults, BAENGINE_LAUNCHAPPROVEDEXE_RESULTS, pResults); 406 ValidateMessageResults(hr, pvResults, BAENGINE_LAUNCHAPPROVEDEXE_RESULTS, pResults);
407 407
408 hr = ExternalEngineLaunchApprovedExe(pContext->pEngineState, pContext->dwThreadId, pArgs->hwndParent, pArgs->wzApprovedExeForElevationId, pArgs->wzArguments, pArgs->dwWaitForInputIdleTimeout); 408 hr = ExternalEngineLaunchApprovedExe(pContext, pArgs->hwndParent, pArgs->wzApprovedExeForElevationId, pArgs->wzArguments, pArgs->dwWaitForInputIdleTimeout);
409 409
410LExit: 410LExit:
411 return hr; 411 return hr;
diff --git a/src/burn/engine/EngineForApplication.h b/src/burn/engine/EngineForApplication.h
index d25a7e51..bf86b7ee 100644
--- a/src/burn/engine/EngineForApplication.h
+++ b/src/burn/engine/EngineForApplication.h
@@ -11,9 +11,40 @@ extern "C" {
11typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT 11typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT
12{ 12{
13 BURN_ENGINE_STATE* pEngineState; 13 BURN_ENGINE_STATE* pEngineState;
14 DWORD dwThreadId; 14 QUEUTIL_QUEUE_HANDLE hQueue;
15 HANDLE hQueueSemaphore;
16 CRITICAL_SECTION csQueue;
15} BOOTSTRAPPER_ENGINE_CONTEXT; 17} BOOTSTRAPPER_ENGINE_CONTEXT;
16 18
19typedef struct _BOOTSTRAPPER_ENGINE_ACTION
20{
21 WM_BURN dwMessage;
22 union
23 {
24 struct
25 {
26 HWND hwndParent;
27 } detect;
28 struct
29 {
30 BOOTSTRAPPER_ACTION action;
31 } plan;
32 struct
33 {
34 HWND hwndParent;
35 } elevate;
36 struct
37 {
38 HWND hwndParent;
39 } apply;
40 BURN_LAUNCH_APPROVED_EXE launchApprovedExe;
41 struct
42 {
43 DWORD dwExitCode;
44 } quit;
45 };
46} BOOTSTRAPPER_ENGINE_ACTION;
47
17// function declarations 48// function declarations
18 49
19HRESULT WINAPI EngineForApplicationProc( 50HRESULT WINAPI EngineForApplicationProc(
diff --git a/src/burn/engine/approvedexe.cpp b/src/burn/engine/approvedexe.cpp
index d8bd956b..28b26d6d 100644
--- a/src/burn/engine/approvedexe.cpp
+++ b/src/burn/engine/approvedexe.cpp
@@ -106,7 +106,6 @@ extern "C" void ApprovedExesUninitializeLaunch(
106 ReleaseStr(pLaunchApprovedExe->sczArguments); 106 ReleaseStr(pLaunchApprovedExe->sczArguments);
107 ReleaseStr(pLaunchApprovedExe->sczExecutablePath); 107 ReleaseStr(pLaunchApprovedExe->sczExecutablePath);
108 ReleaseStr(pLaunchApprovedExe->sczId); 108 ReleaseStr(pLaunchApprovedExe->sczId);
109 MemFree(pLaunchApprovedExe);
110 } 109 }
111} 110}
112 111
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index c443e0c8..8903b5b2 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -884,17 +884,16 @@ LExit:
884 884
885 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_COMPLETE, hr, dwProcessId); 885 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_COMPLETE, hr, dwProcessId);
886 886
887 ApprovedExesUninitializeLaunch(pLaunchApprovedExe);
888
889 return hr; 887 return hr;
890} 888}
891 889
892extern "C" HRESULT CoreQuit( 890extern "C" void CoreQuit(
893 __in BURN_ENGINE_STATE* pEngineState, 891 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
894 __in int nExitCode 892 __in DWORD dwExitCode
895 ) 893 )
896{ 894{
897 HRESULT hr = S_OK; 895 HRESULT hr = S_OK;
896 BURN_ENGINE_STATE* pEngineState = pEngineContext->pEngineState;
898 897
899 // Save engine state if resume mode is unequal to "none". 898 // Save engine state if resume mode is unequal to "none".
900 if (BURN_RESUME_MODE_NONE != pEngineState->resumeMode) 899 if (BURN_RESUME_MODE_NONE != pEngineState->resumeMode)
@@ -907,13 +906,15 @@ extern "C" HRESULT CoreQuit(
907 } 906 }
908 } 907 }
909 908
910 LogId(REPORT_STANDARD, MSG_QUIT, nExitCode); 909 LogId(REPORT_STANDARD, MSG_QUIT, dwExitCode);
911 910
912 pEngineState->fQuit = TRUE; 911 pEngineState->userExperience.dwExitCode = dwExitCode;
913 912
914 ::PostQuitMessage(nExitCode); // go bye-bye. 913 ::EnterCriticalSection(&pEngineContext->csQueue);
915 914
916 return hr; 915 pEngineState->fQuit = TRUE;
916
917 ::LeaveCriticalSection(&pEngineContext->csQueue);
917} 918}
918 919
919extern "C" HRESULT CoreSaveEngineState( 920extern "C" HRESULT CoreSaveEngineState(
@@ -2071,6 +2072,18 @@ LExit:
2071 return hr; 2072 return hr;
2072} 2073}
2073 2074
2075extern "C" void DAPI CoreBootstrapperEngineActionUninitialize(
2076 __in BOOTSTRAPPER_ENGINE_ACTION* pAction
2077 )
2078{
2079 switch (pAction->dwMessage)
2080 {
2081 case WM_BURN_LAUNCH_APPROVED_EXE:
2082 ApprovedExesUninitializeLaunch(&pAction->launchApprovedExe);
2083 break;
2084 }
2085}
2086
2074// internal helper functions 2087// internal helper functions
2075 2088
2076static HRESULT AppendEscapedArgumentToCommandLine( 2089static HRESULT AppendEscapedArgumentToCommandLine(
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 3e636640..186b49ca 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -262,9 +262,9 @@ HRESULT CoreLaunchApprovedExe(
262 __in BURN_ENGINE_STATE* pEngineState, 262 __in BURN_ENGINE_STATE* pEngineState,
263 __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe 263 __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe
264 ); 264 );
265HRESULT CoreQuit( 265void CoreQuit(
266 __in BURN_ENGINE_STATE* pEngineState, 266 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
267 __in int nExitCode 267 __in DWORD dwExitCode
268 ); 268 );
269HRESULT CoreSaveEngineState( 269HRESULT CoreSaveEngineState(
270 __in BURN_ENGINE_STATE* pEngineState 270 __in BURN_ENGINE_STATE* pEngineState
@@ -354,6 +354,9 @@ HRESULT DAPI CoreCloseElevatedLoggingThread(
354HRESULT DAPI CoreWaitForUnelevatedLoggingThread( 354HRESULT DAPI CoreWaitForUnelevatedLoggingThread(
355 __in HANDLE hUnelevatedLoggingThread 355 __in HANDLE hUnelevatedLoggingThread
356 ); 356 );
357void DAPI CoreBootstrapperEngineActionUninitialize(
358 __in BOOTSTRAPPER_ENGINE_ACTION* pAction
359 );
357 360
358#if defined(__cplusplus) 361#if defined(__cplusplus)
359} 362}
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 7fd372b0..154c407d 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -3824,7 +3824,8 @@ static HRESULT OnLaunchApprovedExe(
3824{ 3824{
3825 HRESULT hr = S_OK; 3825 HRESULT hr = S_OK;
3826 SIZE_T iData = 0; 3826 SIZE_T iData = 0;
3827 BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = NULL; 3827 BURN_LAUNCH_APPROVED_EXE launchApprovedExe = { };
3828 BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = &launchApprovedExe;
3828 BURN_APPROVED_EXE* pApprovedExe = NULL; 3829 BURN_APPROVED_EXE* pApprovedExe = NULL;
3829 HKEY hKey = NULL; 3830 HKEY hKey = NULL;
3830 DWORD dwProcessId = 0; 3831 DWORD dwProcessId = 0;
@@ -3832,8 +3833,6 @@ static HRESULT OnLaunchApprovedExe(
3832 SIZE_T cbSendData = 0; 3833 SIZE_T cbSendData = 0;
3833 DWORD dwResult = 0; 3834 DWORD dwResult = 0;
3834 3835
3835 pLaunchApprovedExe = (BURN_LAUNCH_APPROVED_EXE*)MemAlloc(sizeof(BURN_LAUNCH_APPROVED_EXE), TRUE);
3836
3837 // Deserialize message data. 3836 // Deserialize message data.
3838 hr = BuffReadString(pbData, cbData, &iData, &pLaunchApprovedExe->sczId); 3837 hr = BuffReadString(pbData, cbData, &iData, &pLaunchApprovedExe->sczId);
3839 ExitOnFailure(hr, "Failed to read approved exe id."); 3838 ExitOnFailure(hr, "Failed to read approved exe id.");
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;
diff --git a/src/burn/engine/externalengine.cpp b/src/burn/engine/externalengine.cpp
index 5e540c2a..262bb1a9 100644
--- a/src/burn/engine/externalengine.cpp
+++ b/src/burn/engine/externalengine.cpp
@@ -13,6 +13,10 @@ static HRESULT ProcessUnknownEmbeddedMessages(
13 __in_opt LPVOID /*pvContext*/, 13 __in_opt LPVOID /*pvContext*/,
14 __out DWORD* pdwResult 14 __out DWORD* pdwResult
15 ); 15 );
16static HRESULT EnqueueAction(
17 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
18 __inout BOOTSTRAPPER_ENGINE_ACTION** ppAction
19 );
16 20
17// function definitions 21// function definitions
18 22
@@ -582,69 +586,91 @@ HRESULT ExternalEngineCompareVersions(
582} 586}
583 587
584HRESULT ExternalEngineDetect( 588HRESULT ExternalEngineDetect(
585 __in const DWORD dwThreadId, 589 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
586 __in_opt const HWND hwndParent 590 __in_opt const HWND hwndParent
587 ) 591 )
588{ 592{
589 HRESULT hr = S_OK; 593 HRESULT hr = S_OK;
594 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
590 595
591 if (!::PostThreadMessageW(dwThreadId, WM_BURN_DETECT, 0, reinterpret_cast<LPARAM>(hwndParent))) 596 pAction = (BOOTSTRAPPER_ENGINE_ACTION*)MemAlloc(sizeof(BOOTSTRAPPER_ENGINE_ACTION), TRUE);
592 { 597 ExitOnNull(pAction, hr, E_OUTOFMEMORY, "Failed to alloc BOOTSTRAPPER_ENGINE_ACTION");
593 ExitWithLastError(hr, "Failed to post detect message."); 598
594 } 599 pAction->dwMessage = WM_BURN_DETECT;
600 pAction->detect.hwndParent = hwndParent;
601
602 hr = EnqueueAction(pEngineContext, &pAction);
603 ExitOnFailure(hr, "Failed to enqueue detect action.");
595 604
596LExit: 605LExit:
606 ReleaseMem(pAction);
607
597 return hr; 608 return hr;
598} 609}
599 610
600HRESULT ExternalEnginePlan( 611HRESULT ExternalEnginePlan(
601 __in const DWORD dwThreadId, 612 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
602 __in const BOOTSTRAPPER_ACTION action 613 __in const BOOTSTRAPPER_ACTION action
603 ) 614 )
604{ 615{
605 HRESULT hr = S_OK; 616 HRESULT hr = S_OK;
617 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
606 618
607 if (BOOTSTRAPPER_ACTION_LAYOUT > action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED < action) 619 if (BOOTSTRAPPER_ACTION_LAYOUT > action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED < action)
608 { 620 {
609 ExitOnRootFailure(hr = E_INVALIDARG, "BA passed invalid action to Plan: %u.", action); 621 ExitOnRootFailure(hr = E_INVALIDARG, "BA passed invalid action to Plan: %u.", action);
610 } 622 }
611 623
612 if (!::PostThreadMessageW(dwThreadId, WM_BURN_PLAN, 0, action)) 624 pAction = (BOOTSTRAPPER_ENGINE_ACTION*)MemAlloc(sizeof(BOOTSTRAPPER_ENGINE_ACTION), TRUE);
613 { 625 ExitOnNull(pAction, hr, E_OUTOFMEMORY, "Failed to alloc BOOTSTRAPPER_ENGINE_ACTION");
614 ExitWithLastError(hr, "Failed to post plan message."); 626
615 } 627 pAction->dwMessage = WM_BURN_PLAN;
628 pAction->plan.action = action;
629
630 hr = EnqueueAction(pEngineContext, &pAction);
631 ExitOnFailure(hr, "Failed to enqueue plan action.");
616 632
617LExit: 633LExit:
634 ReleaseMem(pAction);
635
618 return hr; 636 return hr;
619} 637}
620 638
621HRESULT ExternalEngineElevate( 639HRESULT ExternalEngineElevate(
622 __in BURN_ENGINE_STATE* pEngineState, 640 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
623 __in const DWORD dwThreadId,
624 __in_opt const HWND hwndParent 641 __in_opt const HWND hwndParent
625 ) 642 )
626{ 643{
627 HRESULT hr = S_OK; 644 HRESULT hr = S_OK;
645 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
628 646
629 if (INVALID_HANDLE_VALUE != pEngineState->companionConnection.hPipe) 647 if (INVALID_HANDLE_VALUE != pEngineContext->pEngineState->companionConnection.hPipe)
630 {
631 hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
632 }
633 else if (!::PostThreadMessageW(dwThreadId, WM_BURN_ELEVATE, 0, reinterpret_cast<LPARAM>(hwndParent)))
634 { 648 {
635 ExitWithLastError(hr, "Failed to post elevate message."); 649 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED));
636 } 650 }
637 651
652 pAction = (BOOTSTRAPPER_ENGINE_ACTION*)MemAlloc(sizeof(BOOTSTRAPPER_ENGINE_ACTION), TRUE);
653 ExitOnNull(pAction, hr, E_OUTOFMEMORY, "Failed to alloc BOOTSTRAPPER_ENGINE_ACTION");
654
655 pAction->dwMessage = WM_BURN_ELEVATE;
656 pAction->elevate.hwndParent = hwndParent;
657
658 hr = EnqueueAction(pEngineContext, &pAction);
659 ExitOnFailure(hr, "Failed to enqueue elevate action.");
660
638LExit: 661LExit:
662 ReleaseMem(pAction);
663
639 return hr; 664 return hr;
640} 665}
641 666
642HRESULT ExternalEngineApply( 667HRESULT ExternalEngineApply(
643 __in const DWORD dwThreadId, 668 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
644 __in_opt const HWND hwndParent 669 __in_opt const HWND hwndParent
645 ) 670 )
646{ 671{
647 HRESULT hr = S_OK; 672 HRESULT hr = S_OK;
673 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
648 674
649 ExitOnNull(hwndParent, hr, E_INVALIDARG, "BA passed NULL hwndParent to Apply."); 675 ExitOnNull(hwndParent, hr, E_INVALIDARG, "BA passed NULL hwndParent to Apply.");
650 if (!::IsWindow(hwndParent)) 676 if (!::IsWindow(hwndParent))
@@ -652,34 +678,46 @@ HRESULT ExternalEngineApply(
652 ExitOnRootFailure(hr = E_INVALIDARG, "BA passed invalid hwndParent to Apply."); 678 ExitOnRootFailure(hr = E_INVALIDARG, "BA passed invalid hwndParent to Apply.");
653 } 679 }
654 680
655 if (!::PostThreadMessageW(dwThreadId, WM_BURN_APPLY, 0, reinterpret_cast<LPARAM>(hwndParent))) 681 pAction = (BOOTSTRAPPER_ENGINE_ACTION*)MemAlloc(sizeof(BOOTSTRAPPER_ENGINE_ACTION), TRUE);
656 { 682 ExitOnNull(pAction, hr, E_OUTOFMEMORY, "Failed to alloc BOOTSTRAPPER_ENGINE_ACTION");
657 ExitWithLastError(hr, "Failed to post apply message."); 683
658 } 684 pAction->dwMessage = WM_BURN_APPLY;
685 pAction->apply.hwndParent = hwndParent;
686
687 hr = EnqueueAction(pEngineContext, &pAction);
688 ExitOnFailure(hr, "Failed to enqueue apply action.");
659 689
660LExit: 690LExit:
691 ReleaseMem(pAction);
692
661 return hr; 693 return hr;
662} 694}
663 695
664HRESULT ExternalEngineQuit( 696HRESULT ExternalEngineQuit(
665 __in const DWORD dwThreadId, 697 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
666 __in const DWORD dwExitCode 698 __in const DWORD dwExitCode
667 ) 699 )
668{ 700{
669 HRESULT hr = S_OK; 701 HRESULT hr = S_OK;
702 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
670 703
671 if (!::PostThreadMessageW(dwThreadId, WM_BURN_QUIT, static_cast<WPARAM>(dwExitCode), 0)) 704 pAction = (BOOTSTRAPPER_ENGINE_ACTION*)MemAlloc(sizeof(BOOTSTRAPPER_ENGINE_ACTION), TRUE);
672 { 705 ExitOnNull(pAction, hr, E_OUTOFMEMORY, "Failed to alloc BOOTSTRAPPER_ENGINE_ACTION");
673 ExitWithLastError(hr, "Failed to post shutdown message."); 706
674 } 707 pAction->dwMessage = WM_BURN_QUIT;
708 pAction->quit.dwExitCode = dwExitCode;
709
710 hr = EnqueueAction(pEngineContext, &pAction);
711 ExitOnFailure(hr, "Failed to enqueue shutdown action.");
675 712
676LExit: 713LExit:
714 ReleaseMem(pAction);
715
677 return hr; 716 return hr;
678} 717}
679 718
680HRESULT ExternalEngineLaunchApprovedExe( 719HRESULT ExternalEngineLaunchApprovedExe(
681 __in BURN_ENGINE_STATE* pEngineState, 720 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
682 __in const DWORD dwThreadId,
683 __in_opt const HWND hwndParent, 721 __in_opt const HWND hwndParent,
684 __in_z LPCWSTR wzApprovedExeForElevationId, 722 __in_z LPCWSTR wzApprovedExeForElevationId,
685 __in_z_opt LPCWSTR wzArguments, 723 __in_z_opt LPCWSTR wzArguments,
@@ -688,25 +726,23 @@ HRESULT ExternalEngineLaunchApprovedExe(
688{ 726{
689 HRESULT hr = S_OK; 727 HRESULT hr = S_OK;
690 BURN_APPROVED_EXE* pApprovedExe = NULL; 728 BURN_APPROVED_EXE* pApprovedExe = NULL;
691 BOOL fLeaveCriticalSection = FALSE;
692 BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = NULL; 729 BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = NULL;
693 730 BOOTSTRAPPER_ENGINE_ACTION* pAction = NULL;
694 pLaunchApprovedExe = (BURN_LAUNCH_APPROVED_EXE*)MemAlloc(sizeof(BURN_LAUNCH_APPROVED_EXE), TRUE);
695 ExitOnNull(pLaunchApprovedExe, hr, E_OUTOFMEMORY, "Failed to alloc BURN_LAUNCH_APPROVED_EXE");
696
697 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
698 fLeaveCriticalSection = TRUE;
699 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
700 ExitOnFailure(hr, "Engine is active, cannot change engine state.");
701 731
702 if (!wzApprovedExeForElevationId || !*wzApprovedExeForElevationId) 732 if (!wzApprovedExeForElevationId || !*wzApprovedExeForElevationId)
703 { 733 {
704 ExitFunction1(hr = E_INVALIDARG); 734 ExitFunction1(hr = E_INVALIDARG);
705 } 735 }
706 736
707 hr = ApprovedExesFindById(&pEngineState->approvedExes, wzApprovedExeForElevationId, &pApprovedExe); 737 hr = ApprovedExesFindById(&pEngineContext->pEngineState->approvedExes, wzApprovedExeForElevationId, &pApprovedExe);
708 ExitOnFailure(hr, "BA requested unknown approved exe with id: %ls", wzApprovedExeForElevationId); 738 ExitOnFailure(hr, "BA requested unknown approved exe with id: %ls", wzApprovedExeForElevationId);
709 739
740 pAction = (BOOTSTRAPPER_ENGINE_ACTION*)MemAlloc(sizeof(BOOTSTRAPPER_ENGINE_ACTION), TRUE);
741 ExitOnNull(pAction, hr, E_OUTOFMEMORY, "Failed to alloc BOOTSTRAPPER_ENGINE_ACTION");
742
743 pAction->dwMessage = WM_BURN_LAUNCH_APPROVED_EXE;
744 pLaunchApprovedExe = &pAction->launchApprovedExe;
745
710 hr = StrAllocString(&pLaunchApprovedExe->sczId, wzApprovedExeForElevationId, NULL); 746 hr = StrAllocString(&pLaunchApprovedExe->sczId, wzApprovedExeForElevationId, NULL);
711 ExitOnFailure(hr, "Failed to copy the id."); 747 ExitOnFailure(hr, "Failed to copy the id.");
712 748
@@ -720,20 +756,14 @@ HRESULT ExternalEngineLaunchApprovedExe(
720 756
721 pLaunchApprovedExe->hwndParent = hwndParent; 757 pLaunchApprovedExe->hwndParent = hwndParent;
722 758
723 if (!::PostThreadMessageW(dwThreadId, WM_BURN_LAUNCH_APPROVED_EXE, 0, reinterpret_cast<LPARAM>(pLaunchApprovedExe))) 759 hr = EnqueueAction(pEngineContext, &pAction);
724 { 760 ExitOnFailure(hr, "Failed to enqueue launch approved exe action.");
725 ExitWithLastError(hr, "Failed to post launch approved exe message.");
726 }
727 761
728LExit: 762LExit:
729 if (fLeaveCriticalSection) 763 if (pAction)
730 { 764 {
731 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive); 765 CoreBootstrapperEngineActionUninitialize(pAction);
732 } 766 MemFree(pAction);
733
734 if (FAILED(hr))
735 {
736 ApprovedExesUninitializeLaunch(pLaunchApprovedExe);
737 } 767 }
738 768
739 return hr; 769 return hr;
@@ -836,3 +866,37 @@ static HRESULT ProcessUnknownEmbeddedMessages(
836 866
837 return S_OK; 867 return S_OK;
838} 868}
869
870static HRESULT EnqueueAction(
871 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
872 __inout BOOTSTRAPPER_ENGINE_ACTION** ppAction
873 )
874{
875 HRESULT hr = S_OK;
876
877 ::EnterCriticalSection(&pEngineContext->csQueue);
878
879 if (pEngineContext->pEngineState->fQuit)
880 {
881 LogId(REPORT_WARNING, MSG_IGNORE_OPERATION_AFTER_QUIT, LoggingBurnMessageToString((*ppAction)->dwMessage));
882 hr = E_INVALIDSTATE;
883 }
884 else
885 {
886 hr = QueEnqueue(pEngineContext->hQueue, *ppAction);
887 }
888
889 ::LeaveCriticalSection(&pEngineContext->csQueue);
890
891 ExitOnFailure(hr, "Failed to enqueue action.");
892
893 *ppAction = NULL;
894
895 if (!::ReleaseSemaphore(pEngineContext->hQueueSemaphore, 1, NULL))
896 {
897 ExitWithLastError(hr, "Failed to signal queue semaphore.");
898 }
899
900LExit:
901 return hr;
902}
diff --git a/src/burn/engine/externalengine.h b/src/burn/engine/externalengine.h
index f28971cd..9322234a 100644
--- a/src/burn/engine/externalengine.h
+++ b/src/burn/engine/externalengine.h
@@ -130,34 +130,32 @@ HRESULT ExternalEngineCompareVersions(
130 ); 130 );
131 131
132HRESULT ExternalEngineDetect( 132HRESULT ExternalEngineDetect(
133 __in const DWORD dwThreadId, 133 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
134 __in_opt const HWND hwndParent 134 __in_opt const HWND hwndParent
135 ); 135 );
136 136
137HRESULT ExternalEnginePlan( 137HRESULT ExternalEnginePlan(
138 __in const DWORD dwThreadId, 138 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
139 __in const BOOTSTRAPPER_ACTION action 139 __in const BOOTSTRAPPER_ACTION action
140 ); 140 );
141 141
142HRESULT ExternalEngineElevate( 142HRESULT ExternalEngineElevate(
143 __in BURN_ENGINE_STATE* pEngineState, 143 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
144 __in const DWORD dwThreadId,
145 __in_opt const HWND hwndParent 144 __in_opt const HWND hwndParent
146 ); 145 );
147 146
148HRESULT ExternalEngineApply( 147HRESULT ExternalEngineApply(
149 __in const DWORD dwThreadId, 148 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
150 __in_opt const HWND hwndParent 149 __in_opt const HWND hwndParent
151 ); 150 );
152 151
153HRESULT ExternalEngineQuit( 152HRESULT ExternalEngineQuit(
154 __in const DWORD dwThreadId, 153 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
155 __in const DWORD dwExitCode 154 __in const DWORD dwExitCode
156 ); 155 );
157 156
158HRESULT ExternalEngineLaunchApprovedExe( 157HRESULT ExternalEngineLaunchApprovedExe(
159 __in BURN_ENGINE_STATE* pEngineState, 158 __in BOOTSTRAPPER_ENGINE_CONTEXT* pEngineContext,
160 __in const DWORD dwThreadId,
161 __in_opt const HWND hwndParent, 159 __in_opt const HWND hwndParent,
162 __in_z LPCWSTR wzApprovedExeForElevationId, 160 __in_z LPCWSTR wzApprovedExeForElevationId,
163 __in_z_opt LPCWSTR wzArguments, 161 __in_z_opt LPCWSTR wzArguments,
diff --git a/src/burn/engine/platform.h b/src/burn/engine/platform.h
index 60184c23..5896a5ca 100644
--- a/src/burn/engine/platform.h
+++ b/src/burn/engine/platform.h
@@ -28,6 +28,7 @@ enum WM_BURN
28 28
29enum BURN_MODE; 29enum BURN_MODE;
30typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; 30typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT;
31typedef struct _BOOTSTRAPPER_ENGINE_ACTION BOOTSTRAPPER_ENGINE_ACTION;
31typedef struct _BURN_CACHE BURN_CACHE; 32typedef struct _BURN_CACHE BURN_CACHE;
32typedef struct _BURN_DEPENDENCIES BURN_DEPENDENCIES; 33typedef struct _BURN_DEPENDENCIES BURN_DEPENDENCIES;
33typedef struct _BURN_ENGINE_COMMAND BURN_ENGINE_COMMAND; 34typedef struct _BURN_ENGINE_COMMAND BURN_ENGINE_COMMAND;
diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h
index e2d1b5cd..a64ce474 100644
--- a/src/burn/engine/precomp.h
+++ b/src/burn/engine/precomp.h
@@ -40,6 +40,7 @@
40#include <pathutil.h> 40#include <pathutil.h>
41#include <polcutil.h> 41#include <polcutil.h>
42#include <procutil.h> 42#include <procutil.h>
43#include <queutil.h>
43#include <regutil.h> 44#include <regutil.h>
44#include <resrutil.h> 45#include <resrutil.h>
45#include <shelutil.h> 46#include <shelutil.h>