aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-02-02 16:56:57 -0600
committerSean Hall <r.sean.hall@gmail.com>2021-02-04 22:16:10 -0600
commitbb7d4bdc09d0b52a65b8cf3b5ae629f385fc8011 (patch)
tree6d144200ff008c8e8f1f74a51475c54b95f04912
parentcc5fe7c79aad14819df1b4cb134884b80a945141 (diff)
downloadwix-bb7d4bdc09d0b52a65b8cf3b5ae629f385fc8011.tar.gz
wix-bb7d4bdc09d0b52a65b8cf3b5ae629f385fc8011.tar.bz2
wix-bb7d4bdc09d0b52a65b8cf3b5ae629f385fc8011.zip
Clean up synchronization between the engine and the BA.
-rw-r--r--src/engine/apply.cpp5
-rw-r--r--src/engine/core.cpp47
-rw-r--r--src/engine/core.h5
-rw-r--r--src/engine/detect.cpp4
-rw-r--r--src/engine/engine.cpp7
-rw-r--r--src/engine/engine.mc2
-rw-r--r--src/engine/externalengine.cpp21
-rw-r--r--src/engine/userexperience.cpp83
-rw-r--r--src/engine/userexperience.h12
-rw-r--r--src/test/BurnUnitTest/PlanTest.cpp3
10 files changed, 80 insertions, 109 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index dd4932aa..76831461 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -366,7 +366,7 @@ extern "C" HRESULT ApplyRegister(
366 hr = CoreSaveEngineState(pEngineState); 366 hr = CoreSaveEngineState(pEngineState);
367 if (FAILED(hr)) 367 if (FAILED(hr))
368 { 368 {
369 LogErrorId(hr, MSG_STATE_NOT_SAVED, NULL, NULL, NULL); 369 LogErrorId(hr, MSG_STATE_NOT_SAVED);
370 hr = S_OK; 370 hr = S_OK;
371 } 371 }
372 372
@@ -1348,8 +1348,6 @@ static HRESULT PromptForSource(
1348 HRESULT hr = S_OK; 1348 HRESULT hr = S_OK;
1349 BOOTSTRAPPER_RESOLVESOURCE_ACTION action = BOOTSTRAPPER_RESOLVESOURCE_ACTION_NONE; 1349 BOOTSTRAPPER_RESOLVESOURCE_ACTION action = BOOTSTRAPPER_RESOLVESOURCE_ACTION_NONE;
1350 1350
1351 UserExperienceDeactivateEngine(pUX);
1352
1353 hr = UserExperienceOnResolveSource(pUX, wzPackageOrContainerId, wzPayloadId, wzLocalSource, wzDownloadSource, &action); 1351 hr = UserExperienceOnResolveSource(pUX, wzPackageOrContainerId, wzPayloadId, wzLocalSource, wzDownloadSource, &action);
1354 if (FAILED(hr)) 1352 if (FAILED(hr))
1355 { 1353 {
@@ -1376,7 +1374,6 @@ static HRESULT PromptForSource(
1376 } 1374 }
1377 1375
1378LExit: 1376LExit:
1379 UserExperienceActivateEngine(pUX, NULL);
1380 return hr; 1377 return hr;
1381} 1378}
1382 1379
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index ae09ea65..a644d377 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -236,16 +236,12 @@ extern "C" HRESULT CoreDetect(
236 ) 236 )
237{ 237{
238 HRESULT hr = S_OK; 238 HRESULT hr = S_OK;
239 BOOL fActivated = FALSE;
240 BOOL fDetectBegan = FALSE; 239 BOOL fDetectBegan = FALSE;
241 BURN_PACKAGE* pPackage = NULL; 240 BURN_PACKAGE* pPackage = NULL;
242 HRESULT hrFirstPackageFailure = S_OK; 241 HRESULT hrFirstPackageFailure = S_OK;
243 242
244 LogId(REPORT_STANDARD, MSG_DETECT_BEGIN, pEngineState->packages.cPackages); 243 LogId(REPORT_STANDARD, MSG_DETECT_BEGIN, pEngineState->packages.cPackages);
245 244
246 hr = UserExperienceActivateEngine(&pEngineState->userExperience, &fActivated);
247 ExitOnFailure(hr, "Engine cannot start detect because it is busy with another action.");
248
249 // Detect if bundle installed state has changed since start up. This 245 // Detect if bundle installed state has changed since start up. This
250 // only happens if Apply() changed the state of bundle (installed or 246 // only happens if Apply() changed the state of bundle (installed or
251 // uninstalled). In that case, Detect() can be used here to reset 247 // uninstalled). In that case, Detect() can be used here to reset
@@ -369,11 +365,6 @@ LExit:
369 hr = hrFirstPackageFailure; 365 hr = hrFirstPackageFailure;
370 } 366 }
371 367
372 if (fActivated)
373 {
374 UserExperienceDeactivateEngine(&pEngineState->userExperience);
375 }
376
377 if (fDetectBegan) 368 if (fDetectBegan)
378 { 369 {
379 UserExperienceOnDetectComplete(&pEngineState->userExperience, hr); 370 UserExperienceOnDetectComplete(&pEngineState->userExperience, hr);
@@ -392,7 +383,6 @@ extern "C" HRESULT CorePlan(
392 ) 383 )
393{ 384{
394 HRESULT hr = S_OK; 385 HRESULT hr = S_OK;
395 BOOL fActivated = FALSE;
396 BOOL fPlanBegan = FALSE; 386 BOOL fPlanBegan = FALSE;
397 LPWSTR sczLayoutDirectory = NULL; 387 LPWSTR sczLayoutDirectory = NULL;
398 HANDLE hSyncpointEvent = NULL; 388 HANDLE hSyncpointEvent = NULL;
@@ -401,9 +391,6 @@ extern "C" HRESULT CorePlan(
401 391
402 LogId(REPORT_STANDARD, MSG_PLAN_BEGIN, pEngineState->packages.cPackages, LoggingBurnActionToString(action)); 392 LogId(REPORT_STANDARD, MSG_PLAN_BEGIN, pEngineState->packages.cPackages, LoggingBurnActionToString(action));
403 393
404 hr = UserExperienceActivateEngine(&pEngineState->userExperience, &fActivated);
405 ExitOnFailure(hr, "Engine cannot start plan because it is busy with another action.");
406
407 fPlanBegan = TRUE; 394 fPlanBegan = TRUE;
408 hr = UserExperienceOnPlanBegin(&pEngineState->userExperience, pEngineState->packages.cPackages); 395 hr = UserExperienceOnPlanBegin(&pEngineState->userExperience, pEngineState->packages.cPackages);
409 ExitOnRootFailure(hr, "BA aborted plan begin."); 396 ExitOnRootFailure(hr, "BA aborted plan begin.");
@@ -496,11 +483,6 @@ extern "C" HRESULT CorePlan(
496 PlanDump(&pEngineState->plan); 483 PlanDump(&pEngineState->plan);
497 484
498LExit: 485LExit:
499 if (fActivated)
500 {
501 UserExperienceDeactivateEngine(&pEngineState->userExperience);
502 }
503
504 if (fPlanBegan) 486 if (fPlanBegan)
505 { 487 {
506 UserExperienceOnPlanComplete(&pEngineState->userExperience, hr); 488 UserExperienceOnPlanComplete(&pEngineState->userExperience, hr);
@@ -551,10 +533,10 @@ extern "C" HRESULT CoreApply(
551 ) 533 )
552{ 534{
553 HRESULT hr = S_OK; 535 HRESULT hr = S_OK;
554 BOOL fActivated = FALSE;
555 HANDLE hLock = NULL; 536 HANDLE hLock = NULL;
556 DWORD cOverallProgressTicks = 0; 537 DWORD cOverallProgressTicks = 0;
557 HANDLE hCacheThread = NULL; 538 HANDLE hCacheThread = NULL;
539 BOOL fApplyInitialize = FALSE;
558 BOOL fElevated = FALSE; 540 BOOL fElevated = FALSE;
559 BOOL fRegistered = FALSE; 541 BOOL fRegistered = FALSE;
560 BOOL fKeepRegistration = pEngineState->plan.fKeepRegistrationDefault; 542 BOOL fKeepRegistration = pEngineState->plan.fKeepRegistrationDefault;
@@ -567,9 +549,6 @@ extern "C" HRESULT CoreApply(
567 549
568 LogId(REPORT_STANDARD, MSG_APPLY_BEGIN); 550 LogId(REPORT_STANDARD, MSG_APPLY_BEGIN);
569 551
570 hr = UserExperienceActivateEngine(&pEngineState->userExperience, &fActivated);
571 ExitOnFailure(hr, "Engine cannot start apply because it is busy with another action.");
572
573 // Ensure any previous attempts to execute are reset. 552 // Ensure any previous attempts to execute are reset.
574 ApplyReset(&pEngineState->userExperience, &pEngineState->packages); 553 ApplyReset(&pEngineState->userExperience, &pEngineState->packages);
575 554
@@ -599,6 +578,7 @@ extern "C" HRESULT CoreApply(
599 ExitOnFailure(hr, "Another per-user setup is already executing."); 578 ExitOnFailure(hr, "Another per-user setup is already executing.");
600 579
601 // Initialize only after getting a lock. 580 // Initialize only after getting a lock.
581 fApplyInitialize = TRUE;
602 ApplyInitialize(); 582 ApplyInitialize();
603 583
604 pEngineState->userExperience.hwndApply = hwndParent; 584 pEngineState->userExperience.hwndApply = hwndParent;
@@ -627,7 +607,7 @@ extern "C" HRESULT CoreApply(
627 ExitOnFailure(hr, "Failed to elevate."); 607 ExitOnFailure(hr, "Failed to elevate.");
628 608
629 hr = ElevationApplyInitialize(pEngineState->companionConnection.hPipe, &pEngineState->userExperience, &pEngineState->variables, pEngineState->plan.action, pEngineState->automaticUpdates, !pEngineState->fDisableSystemRestore); 609 hr = ElevationApplyInitialize(pEngineState->companionConnection.hPipe, &pEngineState->userExperience, &pEngineState->variables, pEngineState->plan.action, pEngineState->automaticUpdates, !pEngineState->fDisableSystemRestore);
630 ExitOnFailure(hr, "Another per-machine setup is already executing."); 610 ExitOnFailure(hr, "Failed to initialize apply in elevated process.");
631 611
632 fElevated = TRUE; 612 fElevated = TRUE;
633 } 613 }
@@ -704,7 +684,10 @@ LExit:
704 684
705 pEngineState->userExperience.hwndApply = NULL; 685 pEngineState->userExperience.hwndApply = NULL;
706 686
707 ApplyUninitialize(); 687 if (fApplyInitialize)
688 {
689 ApplyUninitialize();
690 }
708 691
709 if (hLock) 692 if (hLock)
710 { 693 {
@@ -712,11 +695,6 @@ LExit:
712 ::CloseHandle(hLock); 695 ::CloseHandle(hLock);
713 } 696 }
714 697
715 if (fActivated)
716 {
717 UserExperienceDeactivateEngine(&pEngineState->userExperience);
718 }
719
720 ReleaseHandle(hCacheThread); 698 ReleaseHandle(hCacheThread);
721 699
722 UserExperienceOnApplyComplete(&pEngineState->userExperience, hr, restart, &applyCompleteAction); 700 UserExperienceOnApplyComplete(&pEngineState->userExperience, hr, restart, &applyCompleteAction);
@@ -736,14 +714,10 @@ extern "C" HRESULT CoreLaunchApprovedExe(
736 ) 714 )
737{ 715{
738 HRESULT hr = S_OK; 716 HRESULT hr = S_OK;
739 BOOL fActivated = FALSE;
740 DWORD dwProcessId = 0; 717 DWORD dwProcessId = 0;
741 718
742 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_BEGIN, pLaunchApprovedExe->sczId); 719 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_BEGIN, pLaunchApprovedExe->sczId);
743 720
744 hr = UserExperienceActivateEngine(&pEngineState->userExperience, &fActivated);
745 ExitOnFailure(hr, "Engine cannot start LaunchApprovedExe because it is busy with another action.");
746
747 hr = UserExperienceOnLaunchApprovedExeBegin(&pEngineState->userExperience); 721 hr = UserExperienceOnLaunchApprovedExeBegin(&pEngineState->userExperience);
748 ExitOnRootFailure(hr, "BA aborted LaunchApprovedExe begin."); 722 ExitOnRootFailure(hr, "BA aborted LaunchApprovedExe begin.");
749 723
@@ -755,11 +729,6 @@ extern "C" HRESULT CoreLaunchApprovedExe(
755 hr = ElevationLaunchApprovedExe(pEngineState->companionConnection.hPipe, pLaunchApprovedExe, &dwProcessId); 729 hr = ElevationLaunchApprovedExe(pEngineState->companionConnection.hPipe, pLaunchApprovedExe, &dwProcessId);
756 730
757LExit: 731LExit:
758 if (fActivated)
759 {
760 UserExperienceDeactivateEngine(&pEngineState->userExperience);
761 }
762
763 UserExperienceOnLaunchApprovedExeComplete(&pEngineState->userExperience, hr, dwProcessId); 732 UserExperienceOnLaunchApprovedExeComplete(&pEngineState->userExperience, hr, dwProcessId);
764 733
765 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_COMPLETE, hr, dwProcessId); 734 LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_COMPLETE, hr, dwProcessId);
@@ -782,7 +751,7 @@ extern "C" HRESULT CoreQuit(
782 hr = CoreSaveEngineState(pEngineState); 751 hr = CoreSaveEngineState(pEngineState);
783 if (FAILED(hr)) 752 if (FAILED(hr))
784 { 753 {
785 LogErrorId(hr, MSG_STATE_NOT_SAVED, NULL, NULL, NULL); 754 LogErrorId(hr, MSG_STATE_NOT_SAVED);
786 hr = S_OK; 755 hr = S_OK;
787 } 756 }
788 } 757 }
diff --git a/src/engine/core.h b/src/engine/core.h
index 0161eaa0..fae4bfe5 100644
--- a/src/engine/core.h
+++ b/src/engine/core.h
@@ -77,11 +77,6 @@ enum BURN_AU_PAUSE_ACTION
77 77
78typedef struct _BURN_ENGINE_STATE 78typedef struct _BURN_ENGINE_STATE
79{ 79{
80 // synchronization
81 CRITICAL_SECTION csActive; // Any call from the UX that reads or alters the engine state
82 // needs to be syncronized through this critical section.
83 // Note: The engine must never do a UX callback while in this critical section.
84
85 // UX flow control 80 // UX flow control
86 //BOOL fSuspend; // Is TRUE when UX made Suspend() call on core. 81 //BOOL fSuspend; // Is TRUE when UX made Suspend() call on core.
87 //BOOL fForcedReboot; // Is TRUE when UX made Reboot() call on core. 82 //BOOL fForcedReboot; // Is TRUE when UX made Reboot() call on core.
diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp
index 3b8d63e2..ff6ba4d7 100644
--- a/src/engine/detect.cpp
+++ b/src/engine/detect.cpp
@@ -9,7 +9,7 @@ typedef struct _DETECT_AUTHENTICATION_REQUIRED_DATA
9} DETECT_AUTHENTICATION_REQUIRED_DATA; 9} DETECT_AUTHENTICATION_REQUIRED_DATA;
10 10
11// internal function definitions 11// internal function definitions
12static HRESULT AuthenticationRequired( 12static HRESULT WINAPI AuthenticationRequired(
13 __in LPVOID pData, 13 __in LPVOID pData,
14 __in HINTERNET hUrl, 14 __in HINTERNET hUrl,
15 __in long lHttpCode, 15 __in long lHttpCode,
@@ -288,7 +288,7 @@ LExit:
288 return hr; 288 return hr;
289} 289}
290 290
291static HRESULT AuthenticationRequired( 291static HRESULT WINAPI AuthenticationRequired(
292 __in LPVOID pData, 292 __in LPVOID pData,
293 __in HINTERNET hUrl, 293 __in HINTERNET hUrl,
294 __in long lHttpCode, 294 __in long lHttpCode,
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
index 9eee7fde..2c6bad03 100644
--- a/src/engine/engine.cpp
+++ b/src/engine/engine.cpp
@@ -330,7 +330,6 @@ static HRESULT InitializeEngineState(
330 330
331 pEngineState->automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED; 331 pEngineState->automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED;
332 pEngineState->dwElevatedLoggingTlsId = TLS_OUT_OF_INDEXES; 332 pEngineState->dwElevatedLoggingTlsId = TLS_OUT_OF_INDEXES;
333 ::InitializeCriticalSection(&pEngineState->csActive);
334 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); 333 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
335 PipeConnectionInitialize(&pEngineState->companionConnection); 334 PipeConnectionInitialize(&pEngineState->companionConnection);
336 PipeConnectionInitialize(&pEngineState->embeddedConnection); 335 PipeConnectionInitialize(&pEngineState->embeddedConnection);
@@ -418,8 +417,6 @@ static void UninitializeEngineState(
418 ::TlsFree(pEngineState->dwElevatedLoggingTlsId); 417 ::TlsFree(pEngineState->dwElevatedLoggingTlsId);
419 } 418 }
420 419
421 ::DeleteCriticalSection(&pEngineState->csActive);
422
423 // clear struct 420 // clear struct
424 memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE)); 421 memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE));
425} 422}
@@ -805,6 +802,8 @@ static HRESULT ProcessMessage(
805{ 802{
806 HRESULT hr = S_OK; 803 HRESULT hr = S_OK;
807 804
805 UserExperienceActivateEngine(&pEngineState->userExperience);
806
808 switch (pmsg->message) 807 switch (pmsg->message)
809 { 808 {
810 case WM_BURN_DETECT: 809 case WM_BURN_DETECT:
@@ -832,6 +831,8 @@ static HRESULT ProcessMessage(
832 break; 831 break;
833 } 832 }
834 833
834 UserExperienceDeactivateEngine(&pEngineState->userExperience);
835
835 return hr; 836 return hr;
836} 837}
837 838
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index d6e9751a..b120c5bb 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -938,7 +938,7 @@ MessageId=501
938Severity=Warning 938Severity=Warning
939SymbolicName=MSG_STATE_NOT_SAVED 939SymbolicName=MSG_STATE_NOT_SAVED
940Language=English 940Language=English
941The state file could not be saved, error: 0x%1!x!. Continuing... 941The state file could not be saved. Continuing...
942. 942.
943 943
944MessageId=600 944MessageId=600
diff --git a/src/engine/externalengine.cpp b/src/engine/externalengine.cpp
index 39878c8b..f9a06437 100644
--- a/src/engine/externalengine.cpp
+++ b/src/engine/externalengine.cpp
@@ -276,7 +276,9 @@ HRESULT ExternalEngineSetUpdate(
276 WCHAR wzGuid[39]; 276 WCHAR wzGuid[39];
277 RPC_STATUS rs = RPC_S_OK; 277 RPC_STATUS rs = RPC_S_OK;
278 278
279 ::EnterCriticalSection(&pEngineState->csActive); 279 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
280 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
281 ExitOnFailure(hr, "Engine is active, cannot change engine state.");
280 282
281 if ((!wzLocalSource || !*wzLocalSource) && (!wzDownloadSource || !*wzDownloadSource)) 283 if ((!wzLocalSource || !*wzLocalSource) && (!wzDownloadSource || !*wzDownloadSource))
282 { 284 {
@@ -332,7 +334,7 @@ HRESULT ExternalEngineSetUpdate(
332 } 334 }
333 335
334LExit: 336LExit:
335 ::LeaveCriticalSection(&pEngineState->csActive); 337 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
336 338
337 ReleaseStr(sczCommandline); 339 ReleaseStr(sczCommandline);
338 ReleaseStr(sczLocalSource); 340 ReleaseStr(sczLocalSource);
@@ -351,7 +353,7 @@ HRESULT ExternalEngineSetLocalSource(
351 BURN_CONTAINER* pContainer = NULL; 353 BURN_CONTAINER* pContainer = NULL;
352 BURN_PAYLOAD* pPayload = NULL; 354 BURN_PAYLOAD* pPayload = NULL;
353 355
354 ::EnterCriticalSection(&pEngineState->csActive); 356 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
355 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience); 357 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
356 ExitOnFailure(hr, "Engine is active, cannot change engine state."); 358 ExitOnFailure(hr, "Engine is active, cannot change engine state.");
357 359
@@ -387,7 +389,7 @@ HRESULT ExternalEngineSetLocalSource(
387 } 389 }
388 390
389LExit: 391LExit:
390 ::LeaveCriticalSection(&pEngineState->csActive); 392 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
391 393
392 return hr; 394 return hr;
393} 395}
@@ -406,7 +408,7 @@ HRESULT ExternalEngineSetDownloadSource(
406 BURN_PAYLOAD* pPayload = NULL; 408 BURN_PAYLOAD* pPayload = NULL;
407 DOWNLOAD_SOURCE* pDownloadSource = NULL; 409 DOWNLOAD_SOURCE* pDownloadSource = NULL;
408 410
409 ::EnterCriticalSection(&pEngineState->csActive); 411 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
410 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience); 412 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
411 ExitOnFailure(hr, "Engine is active, cannot change engine state."); 413 ExitOnFailure(hr, "Engine is active, cannot change engine state.");
412 414
@@ -470,7 +472,7 @@ HRESULT ExternalEngineSetDownloadSource(
470 } 472 }
471 473
472LExit: 474LExit:
473 ::LeaveCriticalSection(&pEngineState->csActive); 475 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
474 476
475 return hr; 477 return hr;
476} 478}
@@ -686,7 +688,7 @@ HRESULT ExternalEngineLaunchApprovedExe(
686 pLaunchApprovedExe = (BURN_LAUNCH_APPROVED_EXE*)MemAlloc(sizeof(BURN_LAUNCH_APPROVED_EXE), TRUE); 688 pLaunchApprovedExe = (BURN_LAUNCH_APPROVED_EXE*)MemAlloc(sizeof(BURN_LAUNCH_APPROVED_EXE), TRUE);
687 ExitOnNull(pLaunchApprovedExe, hr, E_OUTOFMEMORY, "Failed to alloc BURN_LAUNCH_APPROVED_EXE"); 689 ExitOnNull(pLaunchApprovedExe, hr, E_OUTOFMEMORY, "Failed to alloc BURN_LAUNCH_APPROVED_EXE");
688 690
689 ::EnterCriticalSection(&pEngineState->csActive); 691 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
690 fLeaveCriticalSection = TRUE; 692 fLeaveCriticalSection = TRUE;
691 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience); 693 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
692 ExitOnFailure(hr, "Engine is active, cannot change engine state."); 694 ExitOnFailure(hr, "Engine is active, cannot change engine state.");
@@ -699,9 +701,6 @@ HRESULT ExternalEngineLaunchApprovedExe(
699 hr = ApprovedExesFindById(&pEngineState->approvedExes, wzApprovedExeForElevationId, &pApprovedExe); 701 hr = ApprovedExesFindById(&pEngineState->approvedExes, wzApprovedExeForElevationId, &pApprovedExe);
700 ExitOnFailure(hr, "BA requested unknown approved exe with id: %ls", wzApprovedExeForElevationId); 702 ExitOnFailure(hr, "BA requested unknown approved exe with id: %ls", wzApprovedExeForElevationId);
701 703
702 ::LeaveCriticalSection(&pEngineState->csActive);
703 fLeaveCriticalSection = FALSE;
704
705 hr = StrAllocString(&pLaunchApprovedExe->sczId, wzApprovedExeForElevationId, NULL); 704 hr = StrAllocString(&pLaunchApprovedExe->sczId, wzApprovedExeForElevationId, NULL);
706 ExitOnFailure(hr, "Failed to copy the id."); 705 ExitOnFailure(hr, "Failed to copy the id.");
707 706
@@ -723,7 +722,7 @@ HRESULT ExternalEngineLaunchApprovedExe(
723LExit: 722LExit:
724 if (fLeaveCriticalSection) 723 if (fLeaveCriticalSection)
725 { 724 {
726 ::LeaveCriticalSection(&pEngineState->csActive); 725 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
727 } 726 }
728 727
729 if (FAILED(hr)) 728 if (FAILED(hr))
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp
index ea8b8a19..3a36cab6 100644
--- a/src/engine/userexperience.cpp
+++ b/src/engine/userexperience.cpp
@@ -24,6 +24,13 @@ static HRESULT SendBAMessage(
24 __inout LPVOID pvResults 24 __inout LPVOID pvResults
25 ); 25 );
26 26
27static HRESULT SendBAMessageFromInactiveEngine(
28 __in BURN_USER_EXPERIENCE* pUserExperience,
29 __in BOOTSTRAPPER_APPLICATION_MESSAGE message,
30 __in const LPVOID pvArgs,
31 __inout LPVOID pvResults
32 );
33
27 34
28// function definitions 35// function definitions
29 36
@@ -230,51 +237,31 @@ extern "C" int UserExperienceSendError(
230 return nResult; 237 return nResult;
231} 238}
232 239
233extern "C" HRESULT UserExperienceActivateEngine( 240extern "C" void UserExperienceActivateEngine(
234 __in BURN_USER_EXPERIENCE* pUserExperience, 241 __in BURN_USER_EXPERIENCE* pUserExperience
235 __out_opt BOOL* pfActivated
236 ) 242 )
237{ 243{
238 HRESULT hr = S_OK;
239 BOOL fActivated;
240
241 ::EnterCriticalSection(&pUserExperience->csEngineActive); 244 ::EnterCriticalSection(&pUserExperience->csEngineActive);
242 if (InterlockedCompareExchange(reinterpret_cast<LONG*>(&pUserExperience->fEngineActive), TRUE, FALSE)) 245 AssertSz(!pUserExperience->fEngineActive, "Engine should have been deactivated before activating it.");
243 { 246 pUserExperience->fEngineActive = TRUE;
244 AssertSz(FALSE, "Engine should have been deactivated before activating it.");
245
246 fActivated = FALSE;
247 hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
248 }
249 else
250 {
251 fActivated = TRUE;
252 }
253 ::LeaveCriticalSection(&pUserExperience->csEngineActive); 247 ::LeaveCriticalSection(&pUserExperience->csEngineActive);
254
255 if (pfActivated)
256 {
257 *pfActivated = fActivated;
258 }
259 ExitOnRootFailure(hr, "Engine active cannot be changed because it was already in that state.");
260
261LExit:
262 return hr;
263} 248}
264 249
265extern "C" void UserExperienceDeactivateEngine( 250extern "C" void UserExperienceDeactivateEngine(
266 __in BURN_USER_EXPERIENCE* pUserExperience 251 __in BURN_USER_EXPERIENCE* pUserExperience
267 ) 252 )
268{ 253{
269 BOOL fActive = InterlockedExchange(reinterpret_cast<LONG*>(&pUserExperience->fEngineActive), FALSE); 254 ::EnterCriticalSection(&pUserExperience->csEngineActive);
270 fActive = fActive; // prevents warning in "ship" build. 255 AssertSz(pUserExperience->fEngineActive, "Engine should have been active before deactivating it.");
271 AssertSz(fActive, "Engine should have be active before deactivating it."); 256 pUserExperience->fEngineActive = FALSE;
257 ::LeaveCriticalSection(&pUserExperience->csEngineActive);
272} 258}
273 259
274extern "C" HRESULT UserExperienceEnsureEngineInactive( 260extern "C" HRESULT UserExperienceEnsureEngineInactive(
275 __in BURN_USER_EXPERIENCE* pUserExperience 261 __in BURN_USER_EXPERIENCE* pUserExperience
276 ) 262 )
277{ 263{
264 // Make a slight optimization here by ignoring the critical section, because all callers should have needed to enter it for their operation anyway.
278 HRESULT hr = pUserExperience->fEngineActive ? HRESULT_FROM_WIN32(ERROR_BUSY) : S_OK; 265 HRESULT hr = pUserExperience->fEngineActive ? HRESULT_FROM_WIN32(ERROR_BUSY) : S_OK;
279 ExitOnRootFailure(hr, "Engine is active, cannot proceed."); 266 ExitOnRootFailure(hr, "Engine is active, cannot proceed.");
280 267
@@ -346,7 +333,7 @@ EXTERN_C BAAPI UserExperienceOnApplyComplete(
346 results.cbSize = sizeof(results); 333 results.cbSize = sizeof(results);
347 results.action = *pAction; 334 results.action = *pAction;
348 335
349 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYCOMPLETE, &args, &results); 336 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYCOMPLETE, &args, &results);
350 ExitOnFailure(hr, "BA OnApplyComplete failed."); 337 ExitOnFailure(hr, "BA OnApplyComplete failed.");
351 338
352 *pAction = results.action; 339 *pAction = results.action;
@@ -761,7 +748,7 @@ EXTERN_C BAAPI UserExperienceOnDetectComplete(
761 748
762 results.cbSize = sizeof(results); 749 results.cbSize = sizeof(results);
763 750
764 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTCOMPLETE, &args, &results); 751 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTCOMPLETE, &args, &results);
765 ExitOnFailure(hr, "BA OnDetectComplete failed."); 752 ExitOnFailure(hr, "BA OnDetectComplete failed.");
766 753
767LExit: 754LExit:
@@ -990,7 +977,7 @@ LExit:
990 977
991EXTERN_C BAAPI UserExperienceOnDetectUpdate( 978EXTERN_C BAAPI UserExperienceOnDetectUpdate(
992 __in BURN_USER_EXPERIENCE* pUserExperience, 979 __in BURN_USER_EXPERIENCE* pUserExperience,
993 __in_z LPCWSTR wzUpdateLocation, 980 __in_z_opt LPCWSTR wzUpdateLocation,
994 __in DWORD64 dw64Size, 981 __in DWORD64 dw64Size,
995 __in VERUTIL_VERSION* pVersion, 982 __in VERUTIL_VERSION* pVersion,
996 __in_z_opt LPCWSTR wzTitle, 983 __in_z_opt LPCWSTR wzTitle,
@@ -1016,7 +1003,7 @@ EXTERN_C BAAPI UserExperienceOnDetectUpdate(
1016 results.cbSize = sizeof(results); 1003 results.cbSize = sizeof(results);
1017 results.fStopProcessingUpdates = *pfStopProcessingUpdates; 1004 results.fStopProcessingUpdates = *pfStopProcessingUpdates;
1018 1005
1019 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATE, &args, &results); 1006 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATE, &args, &results);
1020 ExitOnFailure(hr, "BA OnDetectUpdate failed."); 1007 ExitOnFailure(hr, "BA OnDetectUpdate failed.");
1021 1008
1022 if (results.fCancel) 1009 if (results.fCancel)
@@ -1045,7 +1032,7 @@ EXTERN_C BAAPI UserExperienceOnDetectUpdateBegin(
1045 results.cbSize = sizeof(results); 1032 results.cbSize = sizeof(results);
1046 results.fSkip = *pfSkip; 1033 results.fSkip = *pfSkip;
1047 1034
1048 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATEBEGIN, &args, &results); 1035 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATEBEGIN, &args, &results);
1049 ExitOnFailure(hr, "BA OnDetectUpdateBegin failed."); 1036 ExitOnFailure(hr, "BA OnDetectUpdateBegin failed.");
1050 1037
1051 if (results.fCancel) 1038 if (results.fCancel)
@@ -1074,7 +1061,7 @@ EXTERN_C BAAPI UserExperienceOnDetectUpdateComplete(
1074 results.cbSize = sizeof(results); 1061 results.cbSize = sizeof(results);
1075 results.fIgnoreError = *pfIgnoreError; 1062 results.fIgnoreError = *pfIgnoreError;
1076 1063
1077 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATECOMPLETE, &args, &results); 1064 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATECOMPLETE, &args, &results);
1078 ExitOnFailure(hr, "BA OnDetectUpdateComplete failed."); 1065 ExitOnFailure(hr, "BA OnDetectUpdateComplete failed.");
1079 1066
1080 if (FAILED(hrStatus)) 1067 if (FAILED(hrStatus))
@@ -1124,7 +1111,7 @@ EXTERN_C BAAPI UserExperienceOnElevateComplete(
1124 1111
1125 results.cbSize = sizeof(results); 1112 results.cbSize = sizeof(results);
1126 1113
1127 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONELEVATECOMPLETE, &args, &results); 1114 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONELEVATECOMPLETE, &args, &results);
1128 ExitOnFailure(hr, "BA OnElevateComplete failed."); 1115 ExitOnFailure(hr, "BA OnElevateComplete failed.");
1129 1116
1130LExit: 1117LExit:
@@ -1452,7 +1439,7 @@ EXTERN_C BAAPI UserExperienceOnLaunchApprovedExeComplete(
1452 1439
1453 results.cbSize = sizeof(results); 1440 results.cbSize = sizeof(results);
1454 1441
1455 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE, &args, &results); 1442 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE, &args, &results);
1456 ExitOnFailure(hr, "BA OnLaunchApprovedExeComplete failed."); 1443 ExitOnFailure(hr, "BA OnLaunchApprovedExeComplete failed.");
1457 1444
1458LExit: 1445LExit:
@@ -1571,7 +1558,7 @@ EXTERN_C BAAPI UserExperienceOnPlanComplete(
1571 1558
1572 results.cbSize = sizeof(results); 1559 results.cbSize = sizeof(results);
1573 1560
1574 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPLETE, &args, &results); 1561 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPLETE, &args, &results);
1575 ExitOnFailure(hr, "BA OnPlanComplete failed."); 1562 ExitOnFailure(hr, "BA OnPlanComplete failed.");
1576 1563
1577LExit: 1564LExit:
@@ -1831,7 +1818,7 @@ EXTERN_C BAAPI UserExperienceOnResolveSource(
1831 results.cbSize = sizeof(results); 1818 results.cbSize = sizeof(results);
1832 results.action = *pAction; 1819 results.action = *pAction;
1833 1820
1834 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONRESOLVESOURCE, &args, &results); 1821 hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONRESOLVESOURCE, &args, &results);
1835 ExitOnFailure(hr, "BA OnResolveSource failed."); 1822 ExitOnFailure(hr, "BA OnResolveSource failed.");
1836 1823
1837 if (results.fCancel) 1824 if (results.fCancel)
@@ -2317,3 +2304,21 @@ static HRESULT SendBAMessage(
2317 2304
2318 return hr; 2305 return hr;
2319} 2306}
2307
2308static HRESULT SendBAMessageFromInactiveEngine(
2309 __in BURN_USER_EXPERIENCE* pUserExperience,
2310 __in BOOTSTRAPPER_APPLICATION_MESSAGE message,
2311 __in const LPVOID pvArgs,
2312 __inout LPVOID pvResults
2313 )
2314{
2315 HRESULT hr = S_OK;
2316
2317 UserExperienceDeactivateEngine(pUserExperience);
2318
2319 hr = SendBAMessage(pUserExperience, message, pvArgs, pvResults);
2320
2321 UserExperienceActivateEngine(pUserExperience);
2322
2323 return hr;
2324}
diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h
index 3176e762..f51c09ff 100644
--- a/src/engine/userexperience.h
+++ b/src/engine/userexperience.h
@@ -82,13 +82,17 @@ int UserExperienceSendError(
82 __in DWORD uiFlags, 82 __in DWORD uiFlags,
83 __in int nRecommendation 83 __in int nRecommendation
84 ); 84 );
85HRESULT UserExperienceActivateEngine( 85void UserExperienceActivateEngine(
86 __in BURN_USER_EXPERIENCE* pUserExperience, 86 __in BURN_USER_EXPERIENCE* pUserExperience
87 __out_opt BOOL* pfActivated
88 ); 87 );
89void UserExperienceDeactivateEngine( 88void UserExperienceDeactivateEngine(
90 __in BURN_USER_EXPERIENCE* pUserExperience 89 __in BURN_USER_EXPERIENCE* pUserExperience
91 ); 90 );
91/********************************************************************
92 UserExperienceEnsureEngineInactive - Verifies the engine is inactive.
93 The caller MUST enter the csActive critical section before calling.
94
95*********************************************************************/
92HRESULT UserExperienceEnsureEngineInactive( 96HRESULT UserExperienceEnsureEngineInactive(
93 __in BURN_USER_EXPERIENCE* pUserExperience 97 __in BURN_USER_EXPERIENCE* pUserExperience
94 ); 98 );
@@ -240,7 +244,7 @@ BAAPI UserExperienceOnDetectTargetMsiPackage(
240 ); 244 );
241BAAPI UserExperienceOnDetectUpdate( 245BAAPI UserExperienceOnDetectUpdate(
242 __in BURN_USER_EXPERIENCE* pUserExperience, 246 __in BURN_USER_EXPERIENCE* pUserExperience,
243 __in_z LPCWSTR wzUpdateLocation, 247 __in_z_opt LPCWSTR wzUpdateLocation,
244 __in DWORD64 dw64Size, 248 __in DWORD64 dw64Size,
245 __in VERUTIL_VERSION* pVersion, 249 __in VERUTIL_VERSION* pVersion,
246 __in_z_opt LPCWSTR wzTitle, 250 __in_z_opt LPCWSTR wzTitle,
diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp
index fb4ca246..10b12e7b 100644
--- a/src/test/BurnUnitTest/PlanTest.cpp
+++ b/src/test/BurnUnitTest/PlanTest.cpp
@@ -529,7 +529,6 @@ namespace Bootstrapper
529 HRESULT hr = S_OK; 529 HRESULT hr = S_OK;
530 LPWSTR sczFilePath = NULL; 530 LPWSTR sczFilePath = NULL;
531 531
532 ::InitializeCriticalSection(&pEngineState->csActive);
533 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); 532 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
534 533
535 hr = VariableInitialize(&pEngineState->variables); 534 hr = VariableInitialize(&pEngineState->variables);
@@ -567,6 +566,8 @@ namespace Bootstrapper
567 566
568 hr = DepDependencyArrayAlloc(&pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, pRegistration->sczProviderKey, NULL); 567 hr = DepDependencyArrayAlloc(&pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, pRegistration->sczProviderKey, NULL);
569 NativeAssert::Succeeded(hr, "Failed to add the bundle provider key to the list of dependencies to ignore."); 568 NativeAssert::Succeeded(hr, "Failed to add the bundle provider key to the list of dependencies to ignore.");
569
570 pEngineState->userExperience.fEngineActive = TRUE;
570 } 571 }
571 572
572 void DetectAttachedContainerAsAttached(BURN_ENGINE_STATE* pEngineState) 573 void DetectAttachedContainerAsAttached(BURN_ENGINE_STATE* pEngineState)