From d47c73dbcd0a314cf3346b9b1294063ed4a124c4 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Tue, 8 Jun 2021 11:21:53 -0500 Subject: Show Burn splash screen earlier. Make the initial Burn process show the splash screen, and show it before parsing the manifest. Fixes half of #5300 --- src/burn/engine/core.cpp | 45 +++++++++++++++++++++++++++++++++++--- src/burn/engine/core.h | 5 +++++ src/burn/engine/engine.cpp | 15 ++++++++----- src/burn/engine/splashscreen.cpp | 39 +++++++++++++++++++++++++++++++-- src/burn/engine/splashscreen.h | 14 ++++++++++++ src/burn/engine/userexperience.cpp | 7 ------ src/burn/engine/userexperience.h | 1 - 7 files changed, 107 insertions(+), 19 deletions(-) (limited to 'src/burn') diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index dc976eb4..e7e8e48d 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp @@ -1060,7 +1060,7 @@ extern "C" HRESULT CoreAppendFileHandleAttachedToCommandLine( ExitWithLastError(hr, "Failed to duplicate file handle for attached container."); } - hr = StrAllocFormattedSecure(psczCommandLine, L"%ls -%ls=%Iu", *psczCommandLine, BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, reinterpret_cast(hExecutableFile)); + hr = StrAllocConcatFormattedSecure(psczCommandLine, L" -%ls=%Iu", BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, reinterpret_cast(hExecutableFile)); ExitOnFailure(hr, "Failed to append the file handle to the command line."); *phExecutableFile = hExecutableFile; @@ -1088,12 +1088,12 @@ extern "C" HRESULT CoreAppendFileHandleSelfToCommandLine( hExecutableFile = ::CreateFileW(wzExecutablePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, &securityAttributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE != hExecutableFile) { - hr = StrAllocFormattedSecure(psczCommandLine, L"%ls -%ls=%Iu", *psczCommandLine, BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF, reinterpret_cast(hExecutableFile)); + hr = StrAllocConcatFormattedSecure(psczCommandLine, L" -%ls=%Iu", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF, reinterpret_cast(hExecutableFile)); ExitOnFailure(hr, "Failed to append the file handle to the command line."); if (psczObfuscatedCommandLine) { - hr = StrAllocFormatted(psczObfuscatedCommandLine, L"%ls -%ls=%Iu", *psczObfuscatedCommandLine, BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF, reinterpret_cast(hExecutableFile)); + hr = StrAllocConcatFormatted(psczObfuscatedCommandLine, L" -%ls=%Iu", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF, reinterpret_cast(hExecutableFile)); ExitOnFailure(hr, "Failed to append the file handle to the obfuscated command line."); } @@ -1107,6 +1107,23 @@ LExit: return hr; } +extern "C" HRESULT CoreAppendSplashScreenWindowToCommandLine( + __in_opt HWND hwndSplashScreen, + __deref_inout_z LPWSTR* psczCommandLine + ) +{ + HRESULT hr = S_OK; + + if (hwndSplashScreen) + { + hr = StrAllocConcatFormattedSecure(psczCommandLine, L" -%ls=%Iu", BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN, reinterpret_cast(hwndSplashScreen)); + ExitOnFailure(hr, "Failed to append the splash screen window to the command line."); + } + +LExit: + return hr; +} + extern "C" void CoreCleanup( __in BURN_ENGINE_STATE* pEngineState ) @@ -1571,6 +1588,28 @@ extern "C" HRESULT CoreParseCommandLine( } } } + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN), BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN, lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN))) + { + LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN)]; + if (L'=' != wzParam[-1] || L'\0' == wzParam[0]) + { + fInvalidCommandLine = TRUE; + TraceLog(E_INVALIDARG, "Missing required parameter for switch: %ls", BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN); + } + else + { + hr = StrStringToUInt64(wzParam, 0, &qw); + if (FAILED(hr)) + { + TraceLog(hr, "Failed to parse splash screen window: '%ls'", wzParam); + hr = S_OK; + } + else + { + pCommand->hwndSplashScreen = (HWND)qw; + } + } + } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_PREFIX), BURN_COMMANDLINE_SWITCH_PREFIX, lstrlenW(BURN_COMMANDLINE_SWITCH_PREFIX))) { // Skip (but log) any other private burn switches we don't recognize, so that diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h index 7b1be47e..0a92d64f 100644 --- a/src/burn/engine/core.h +++ b/src/burn/engine/core.h @@ -29,6 +29,7 @@ const LPCWSTR BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES = L"burn.ignoredependen const LPCWSTR BURN_COMMANDLINE_SWITCH_ANCESTORS = L"burn.ancestors"; const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED = L"burn.filehandle.attached"; const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF = L"burn.filehandle.self"; +const LPCWSTR BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN = L"burn.splash.screen"; const LPCWSTR BURN_COMMANDLINE_SWITCH_PREFIX = L"burn."; const LPCWSTR BURN_BUNDLE_LAYOUT_DIRECTORY = L"WixBundleLayoutDirectory"; @@ -228,6 +229,10 @@ HRESULT CoreAppendFileHandleSelfToCommandLine( __deref_inout_z LPWSTR* psczCommandLine, __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine ); +HRESULT CoreAppendSplashScreenWindowToCommandLine( + __in_opt HWND hwndSplashScreen, + __deref_inout_z LPWSTR* psczCommandLine + ); void CoreCleanup( __in BURN_ENGINE_STATE* pEngineState ); diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index 1314ddc6..4323b540 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp @@ -122,6 +122,11 @@ extern "C" HRESULT EngineRun( engineState.command.nCmdShow = nCmdShow; + if (BURN_MODE_ELEVATED != engineState.mode && BOOTSTRAPPER_DISPLAY_NONE < engineState.command.display && !engineState.command.hwndSplashScreen) + { + SplashScreenCreate(hInstance, NULL, &engineState.command.hwndSplashScreen); + } + // initialize platform layer PlatformInitialize(); @@ -452,7 +457,10 @@ static HRESULT RunUntrusted( hr = CoreAppendFileHandleSelfToCommandLine(wzCleanRoomBundlePath, &hFileSelf, &sczParameters, NULL); ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); - hr = StrAllocFormattedSecure(&sczParameters, L"%ls %ls", sczParameters, wzCommandLine); + hr = CoreAppendSplashScreenWindowToCommandLine(pEngineState->command.hwndSplashScreen, &sczParameters); + ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN); + + hr = StrAllocConcatFormattedSecure(&sczParameters, L" %ls", wzCommandLine); ExitOnFailure(hr, "Failed to append original command line."); #ifdef ENABLE_UNELEVATE @@ -525,11 +533,6 @@ static HRESULT RunNormal( ExitFunction1(hr = S_OK); } - if (pEngineState->userExperience.fSplashScreen && BOOTSTRAPPER_DISPLAY_NONE < pEngineState->command.display) - { - SplashScreenCreate(hInstance, NULL, &pEngineState->command.hwndSplashScreen); - } - // Create a top-level window to handle system messages. hr = UiCreateMessageWindow(hInstance, pEngineState); ExitOnFailure(hr, "Failed to create the message window."); diff --git a/src/burn/engine/splashscreen.cpp b/src/burn/engine/splashscreen.cpp index 90bd5203..ff61996f 100644 --- a/src/burn/engine/splashscreen.cpp +++ b/src/burn/engine/splashscreen.cpp @@ -3,7 +3,6 @@ #include "precomp.h" #define BURN_SPLASHSCREEN_CLASS_WINDOW L"WixBurnSplashScreen" -#define IDB_SPLASHSCREEN 1 // struct @@ -21,12 +20,17 @@ struct SPLASHSCREEN_CONTEXT HANDLE hInitializedEvent; HINSTANCE hInstance; LPCWSTR wzCaption; + BURN_SPLASH_SCREEN_CONFIGURATION* pSplashScreenConfiguration; HWND* pHwnd; }; // internal function definitions +static HRESULT LoadConfiguration( + __in HINSTANCE hInstance, + __in BURN_SPLASH_SCREEN_CONFIGURATION** ppSplashScreenConfiguration + ); static DWORD WINAPI ThreadProc( __in LPVOID pvContext ); @@ -74,6 +78,19 @@ extern "C" void SplashScreenCreate( HANDLE rgSplashScreenEvents[2] = { }; DWORD dwSplashScreenThreadId = 0; + hr = LoadConfiguration(hInstance, &context.pSplashScreenConfiguration); + ExitOnFailure(hr, "Failed to load splash screen configuration."); + + switch (context.pSplashScreenConfiguration->type) + { + case BURN_SPLASH_SCREEN_TYPE_NONE: + ExitFunction(); + case BURN_SPLASH_SCREEN_TYPE_BITMAP_RESOURCE: + break; + default: + ExitWithRootFailure(hr, E_INVALIDDATA, "Invalid splash screen type: %i", context.pSplashScreenConfiguration->type); + } + rgSplashScreenEvents[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL); ExitOnNullWithLastError(rgSplashScreenEvents[0], hr, "Failed to create modal event."); @@ -125,6 +142,24 @@ LExit: } +static HRESULT LoadConfiguration( + __in HINSTANCE hInstance, + __in BURN_SPLASH_SCREEN_CONFIGURATION** ppSplashScreenConfiguration + ) +{ + HRESULT hr = S_OK; + DWORD cbData = 0; + + hr = ResReadData(hInstance, MAKEINTRESOURCEA(IDD_BURN_SPLASH_SCREEN_CONFIGURATION), reinterpret_cast(ppSplashScreenConfiguration), &cbData); + ExitOnFailure(hr, "Failed to read splash screen configuration resource."); + + AssertSz(sizeof(BURN_SPLASH_SCREEN_CONFIGURATION) == cbData, "Splash screen configuration resource size is wrong"); + +LExit: + return hr; +} + + static DWORD WINAPI ThreadProc( __in LPVOID pvContext ) @@ -242,7 +277,7 @@ static HRESULT LoadSplashScreen( RECT* pMonitorRect = NULL; pSplashScreen->nDpi = USER_DEFAULT_SCREEN_DPI; - pSplashScreen->hBitmap = ::LoadBitmapW(pContext->hInstance, MAKEINTRESOURCEW(IDB_SPLASHSCREEN)); + pSplashScreen->hBitmap = ::LoadBitmapW(pContext->hInstance, MAKEINTRESOURCEW(pContext->pSplashScreenConfiguration->wResourceId)); ExitOnNullWithLastError(pSplashScreen->hBitmap, hr, "Failed to load splash screen bitmap."); ::GetObject(pSplashScreen->hBitmap, sizeof(bmp), static_cast(&bmp)); diff --git a/src/burn/engine/splashscreen.h b/src/burn/engine/splashscreen.h index 8f8817c7..470c5930 100644 --- a/src/burn/engine/splashscreen.h +++ b/src/burn/engine/splashscreen.h @@ -6,12 +6,26 @@ extern "C" { #endif +// IDD_BURN_SPLASH_SCREEN_CONFIGURATION, BURN_SPLASH_SCREEN_TYPE, and BURN_SPLASH_SCREEN_CONFIGURATION must stay in sync with src\wix\WixToolset.Core.Burn\Bundles\CreateBundleExeCommand.cs + +#define IDD_BURN_SPLASH_SCREEN_CONFIGURATION 1 // constants +enum BURN_SPLASH_SCREEN_TYPE +{ + BURN_SPLASH_SCREEN_TYPE_NONE, + BURN_SPLASH_SCREEN_TYPE_BITMAP_RESOURCE, +}; // structs +typedef struct _BURN_SPLASH_SCREEN_CONFIGURATION +{ + BURN_SPLASH_SCREEN_TYPE type; + WORD wResourceId; +} BURN_SPLASH_SCREEN_CONFIGURATION; + // functions diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 07f4b831..88655774 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp @@ -54,13 +54,6 @@ extern "C" HRESULT UserExperienceParseFromXml( } ExitOnFailure(hr, "Failed to select user experience node."); - // parse splash screen - hr = XmlGetYesNoAttribute(pixnUserExperienceNode, L"SplashScreen", &pUserExperience->fSplashScreen); - if (E_NOTFOUND != hr) - { - ExitOnFailure(hr, "Failed to to get UX/@SplashScreen"); - } - // parse payloads hr = PayloadsParseFromXml(&pUserExperience->payloads, NULL, NULL, pixnUserExperienceNode); ExitOnFailure(hr, "Failed to parse user experience payloads."); diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index 56bc3239..6a5ae697 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h @@ -19,7 +19,6 @@ typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; typedef struct _BURN_USER_EXPERIENCE { - BOOL fSplashScreen; BURN_PAYLOADS payloads; HMODULE hUXModule; -- cgit v1.2.3-55-g6feb