From b7faab06259d3afdc3205024a0004ace72157cbe Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 29 Apr 2020 19:31:01 +1000 Subject: Treat failing to load SCD like mbahost treats .NET 4.5.2 on Win7 RTM. --- src/dnchost/dnchost.cpp | 87 ++++++++++++++++++++-- src/dnchost/dnchost.h | 8 ++ src/mbahost/mbahost.cpp | 2 + src/wixlib/Dnc.wxs | 10 +++ src/wixstdba/Resources/dncpreq.thm | 47 ++++++++++++ src/wixstdba/Resources/dncpreq.wxl | 29 ++++++++ .../WixStandardBootstrapperApplication.cpp | 26 ++++++- src/wixstdba/wixstdba.cpp | 26 +++++++ src/wixstdba/wixstdba.def | 2 + 9 files changed, 228 insertions(+), 9 deletions(-) create mode 100644 src/wixstdba/Resources/dncpreq.thm create mode 100644 src/wixstdba/Resources/dncpreq.wxl (limited to 'src') diff --git a/src/dnchost/dnchost.cpp b/src/dnchost/dnchost.cpp index c4b0d222..0fad58c1 100644 --- a/src/dnchost/dnchost.cpp +++ b/src/dnchost/dnchost.cpp @@ -20,6 +20,13 @@ static HRESULT LoadRuntime( static HRESULT LoadManagedBootstrapperApplicationFactory( __in DNCSTATE* pState ); +static HRESULT CreatePrerequisiteBA( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in LPCWSTR wzAppBase, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ); // function definitions @@ -51,6 +58,7 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( ) { HRESULT hr = S_OK; + HRESULT hrHostInitialization = S_OK; IBootstrapperEngine* pEngine = NULL; // coreclr.dll doesn't support unloading, so the rest of the .NET Core hosting stack doesn't support it either. @@ -77,18 +85,32 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( if (!vstate.fInitializedRuntime) { hr = LoadRuntime(&vstate); - BalExitOnFailure(hr, "Failed to load .NET Core runtime."); - - vstate.fInitializedRuntime = TRUE; - hr = LoadManagedBootstrapperApplicationFactory(&vstate); - BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory."); + vstate.fInitializedRuntime = SUCCEEDED(hr); } - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core SCD bootstrapper application."); + if (vstate.fInitializedRuntime) + { + if (!vstate.pAppFactory) + { + hr = LoadManagedBootstrapperApplicationFactory(&vstate); + BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory."); + } + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core SCD bootstrapper application."); + + hr = vstate.pAppFactory->Create(pArgs, pResults); + BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application."); + } + else // fallback to the prerequisite BA. + { + hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE; + BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error."); + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr); - hr = vstate.pAppFactory->Create(pArgs, pResults); - BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application."); + hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults); + BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); + } LExit: ReleaseNullObject(pEngine); @@ -98,6 +120,18 @@ LExit: extern "C" void WINAPI BootstrapperApplicationDestroy() { + if (vstate.hMbapreqModule) + { + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy")); + if (pfnDestroy) + { + (*pfnDestroy)(); + } + + ::FreeLibrary(vstate.hMbapreqModule); + vstate.hMbapreqModule = NULL; + } + BalUninitialize(); } @@ -227,3 +261,40 @@ static HRESULT LoadManagedBootstrapperApplicationFactory( return hr; } + +static HRESULT CreatePrerequisiteBA( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in LPCWSTR wzAppBase, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ) +{ + HRESULT hr = S_OK; + LPWSTR sczDncpreqPath = NULL; + HMODULE hModule = NULL; + + hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath); + BalExitOnFailure(hr, "Failed to get path to pre-requisite BA."); + + hModule = ::LoadLibraryW(sczDncpreqPath); + BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); + + PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast(::GetProcAddress(hModule, "DncPrereqBootstrapperApplicationCreate")); + BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get DncPrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath); + + hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); + BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); + + vstate.hMbapreqModule = hModule; + hModule = NULL; + +LExit: + if (hModule) + { + ::FreeLibrary(hModule); + } + ReleaseStr(sczDncpreqPath); + + return hr; +} diff --git a/src/dnchost/dnchost.h b/src/dnchost/dnchost.h index e498edaf..40c506fc 100644 --- a/src/dnchost/dnchost.h +++ b/src/dnchost/dnchost.h @@ -2,6 +2,13 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. +extern "C" typedef HRESULT(WINAPI* PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ); + struct DNCSTATE { BOOL fInitialized; @@ -16,4 +23,5 @@ struct DNCSTATE LPWSTR sczBaFactoryRuntimeConfigPath; HOSTFXR_STATE hostfxrState; IBootstrapperApplicationFactory* pAppFactory; + HMODULE hMbapreqModule; }; diff --git a/src/mbahost/mbahost.cpp b/src/mbahost/mbahost.cpp index 7916ec9a..735f9f21 100644 --- a/src/mbahost/mbahost.cpp +++ b/src/mbahost/mbahost.cpp @@ -129,6 +129,8 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( } LExit: + ReleaseNullObject(pEngine); + return hr; } diff --git a/src/wixlib/Dnc.wxs b/src/wixlib/Dnc.wxs index 65a59e61..a2779c19 100644 --- a/src/wixlib/Dnc.wxs +++ b/src/wixlib/Dnc.wxs @@ -9,6 +9,7 @@ + @@ -16,6 +17,15 @@ + + + + + + + + + diff --git a/src/wixstdba/Resources/dncpreq.thm b/src/wixstdba/Resources/dncpreq.thm new file mode 100644 index 00000000..4ae61819 --- /dev/null +++ b/src/wixstdba/Resources/dncpreq.thm @@ -0,0 +1,47 @@ + + + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + + + + + + + + + + #(loc.InstallLicenseTerms) + + + + + + + + + + + + + #(loc.FailureLogLinkText) + + + + + + + diff --git a/src/wixstdba/Resources/dncpreq.wxl b/src/wixstdba/Resources/dncpreq.wxl new file mode 100644 index 00000000..d6b73b5f --- /dev/null +++ b/src/wixstdba/Resources/dncpreq.wxl @@ -0,0 +1,29 @@ + + + + + + [WixBundleName] Setup + Microsoft .NET Core required for [WixBundleName] setup + Are you sure you want to cancel? + Setup Help + /passive | /quiet - displays minimal UI with no prompts or displays no UI and + no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + Click the "Accept and Install" button to accept the Microsoft .NET Core <a href="#">license terms</a>. + &Accept and Install + &Decline + Setup Progress + Processing: + &Cancel + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + [WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment. + No action was taken as a system reboot is required. + diff --git a/src/wixstdba/WixStandardBootstrapperApplication.cpp b/src/wixstdba/WixStandardBootstrapperApplication.cpp index 88a26534..826c4386 100644 --- a/src/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/wixstdba/WixStandardBootstrapperApplication.cpp @@ -2892,6 +2892,23 @@ private: // privates } } } + else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal) + { + HRESULT hr = StrAllocString(&sczUnformattedText, L"#(loc.SCDRUNTIMEFAILUREErrorMessage)", 0); + if (FAILED(hr)) + { + BalLogError(hr, "Failed to initialize SCDRUNTIMEFAILUREErrorMessage loc identifier."); + } + else + { + hr = LocLocalizeString(m_pWixLoc, &sczUnformattedText); + if (FAILED(hr)) + { + BalLogError(hr, "Failed to localize SCDRUNTIMEFAILUREErrorMessage: %ls", sczUnformattedText); + ReleaseNullStr(sczUnformattedText); + } + } + } else // try to get the error message from the error code. { StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL); @@ -2915,6 +2932,13 @@ private: // privates BalFormatString(sczUnformattedText, &sczText); } } + else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal) + { + if (sczUnformattedText) + { + BalFormatString(sczUnformattedText, &sczText); + } + } else { StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText); @@ -3754,7 +3778,7 @@ HRESULT CreateBootstrapperApplication( if (BOOTSTRAPPER_DISPLAY_UNKNOWN == pArgs->pCommand->display) { - ExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type."); + BalExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type."); } pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine, pArgs); diff --git a/src/wixstdba/wixstdba.cpp b/src/wixstdba/wixstdba.cpp index 2767c74e..727c8cb0 100644 --- a/src/wixstdba/wixstdba.cpp +++ b/src/wixstdba/wixstdba.cpp @@ -55,6 +55,32 @@ extern "C" void WINAPI BootstrapperApplicationDestroy() } +extern "C" HRESULT WINAPI DncPrereqBootstrapperApplicationCreate( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ) +{ + HRESULT hr = S_OK; + + BalInitialize(pEngine); + + hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication); + BalExitOnFailure(hr, "Failed to create .NET Core prerequisite bootstrapper application interface."); + +LExit: + return hr; +} + + +extern "C" void WINAPI DncPrereqBootstrapperApplicationDestroy() +{ + ReleaseNullObject(vpApplication); + BalUninitialize(); +} + + extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate( __in HRESULT hrHostInitialization, __in IBootstrapperEngine* pEngine, diff --git a/src/wixstdba/wixstdba.def b/src/wixstdba/wixstdba.def index 815d2977..ba9980d3 100644 --- a/src/wixstdba/wixstdba.def +++ b/src/wixstdba/wixstdba.def @@ -4,5 +4,7 @@ EXPORTS BootstrapperApplicationCreate BootstrapperApplicationDestroy + DncPrereqBootstrapperApplicationCreate + DncPrereqBootstrapperApplicationDestroy MbaPrereqBootstrapperApplicationCreate MbaPrereqBootstrapperApplicationDestroy -- cgit v1.2.3-55-g6feb