From 6a6974a15deb6edf593736cdb8043bfb93064782 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 13 May 2022 13:50:50 -0500 Subject: Move infinite loop detection into the hosts. Tell the BA during Destroy whether it will be reloaded, and let the BA decide then whether it's module should be unloaded. Show error when infinite prereq loop detected. Only clip the exit code if they're Win32 errors. Set related bundle type to none to avoid downgrades during preqba. --- .../inc/BootstrapperApplication.h | 18 +- src/api/burn/balutil/inc/BAFunctions.h | 17 +- src/api/burn/balutil/inc/balutil.h | 1 + src/burn/engine/engine.cpp | 4 +- src/burn/engine/userexperience.cpp | 15 +- src/burn/engine/userexperience.h | 4 +- src/ext/Bal/Samples/bafunctions/bafunctions.cpp | 2 + src/ext/Bal/dnchost/dnchost.cpp | 51 ++-- src/ext/Bal/dnchost/dnchost.h | 8 +- src/ext/Bal/dnchost/dnchost.vcxproj | 2 +- src/ext/Bal/dnchost/precomp.h | 2 + src/ext/Bal/mbahost/mbahost.cpp | 289 ++++++++++--------- src/ext/Bal/mbahost/mbahost.h | 17 ++ src/ext/Bal/mbahost/mbahost.vcxproj | 3 +- src/ext/Bal/mbahost/precomp.h | 17 +- .../Bal/test/examples/TestEngine/ReloadEngine.cpp | 4 +- .../test/examples/TestEngine/ShutdownEngine.cpp | 2 +- .../Bal/test/examples/TestEngine/TestEngine.cpp | 16 +- src/ext/Bal/test/examples/TestEngine/TestEngine.h | 6 +- .../test/examples/TestEngine/WaitForQuitEngine.cpp | 2 +- src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/dncpreq.wxl | 1 + src/ext/Bal/wixstdba/Resources/mbapreq.wxl | 1 + .../WixStandardBootstrapperApplication.cpp | 320 +++++++-------------- src/ext/Bal/wixstdba/inc/preqba.h | 16 ++ src/ext/Bal/wixstdba/precomp.h | 66 +++-- src/ext/Bal/wixstdba/wixstdba.cpp | 54 ++-- src/ext/Bal/wixstdba/wixstdba.def | 6 +- src/ext/Bal/wixstdba/wixstdba.vcxproj | 1 + src/test/burn/TestBA/TestBA.cs | 8 +- .../TestData/Manual/BafThmutilTesting/precomp.cpp | 2 + src/test/burn/WixToolset.WixBA/WixBA.cs | 9 +- .../burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs | 6 +- 55 files changed, 500 insertions(+), 493 deletions(-) create mode 100644 src/ext/Bal/mbahost/mbahost.h create mode 100644 src/ext/Bal/wixstdba/inc/preqba.h diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h index 228cb6ff..ea3be214 100644 --- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h +++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h @@ -1494,7 +1494,22 @@ extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_PROC)( __in_opt LPVOID pvContext ); -extern "C" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)(); +struct BOOTSTRAPPER_DESTROY_ARGS +{ + DWORD cbSize; + BOOL fReload; +}; + +struct BOOTSTRAPPER_DESTROY_RESULTS +{ + DWORD cbSize; + BOOL fDisableUnloading; // indicates the BA dll must not be unloaded after BootstrapperApplicationDestroy. +}; + +extern "C" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)( + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults + ); @@ -1512,7 +1527,6 @@ struct BOOTSTRAPPER_CREATE_RESULTS DWORD cbSize; PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBootstrapperApplicationProc; LPVOID pvBootstrapperApplicationProcContext; - BOOL fDisableUnloading; // indicates the BA dll must not be unloaded after BootstrapperApplicationDestroy. }; extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_CREATE)( diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h index c1057ab6..b23dd02e 100644 --- a/src/api/burn/balutil/inc/BAFunctions.h +++ b/src/api/burn/balutil/inc/BAFunctions.h @@ -126,6 +126,18 @@ struct BA_FUNCTIONS_CREATE_RESULTS LPVOID pvBAFunctionsProcContext; }; +struct BA_FUNCTIONS_DESTROY_ARGS +{ + DWORD cbSize; + BOOL fReload; +}; + +struct BA_FUNCTIONS_DESTROY_RESULTS +{ + DWORD cbSize; + BOOL fDisableUnloading; // indicates the BAFunctions dll must not be unloaded after BAFunctionsDestroy. +}; + struct BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS { DWORD cbSize; @@ -218,7 +230,10 @@ typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_CREATE)( __inout BA_FUNCTIONS_CREATE_RESULTS* pResults ); -typedef void (WINAPI *PFN_BA_FUNCTIONS_DESTROY)(); +typedef void (WINAPI *PFN_BA_FUNCTIONS_DESTROY)( + __in const BA_FUNCTIONS_DESTROY_ARGS* pArgs, + __inout BA_FUNCTIONS_DESTROY_RESULTS* pResults + ); #ifdef __cplusplus } diff --git a/src/api/burn/balutil/inc/balutil.h b/src/api/burn/balutil/inc/balutil.h index 2e370db7..33f1a6de 100644 --- a/src/api/burn/balutil/inc/balutil.h +++ b/src/api/burn/balutil/inc/balutil.h @@ -39,6 +39,7 @@ static const HRESULT E_WIXSTDBA_CONDITION_FAILED = MAKE_HRESULT(SEVERITY_ERROR, static const HRESULT E_MBAHOST_NET452_ON_WIN7RTM = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1000); static const HRESULT E_DNCHOST_SCD_RUNTIME_FAILURE = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1001); +static const HRESULT E_PREREQBA_INFINITE_LOOP = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1002); /******************************************************************* diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index ee848acf..a408ed4a 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp @@ -796,7 +796,7 @@ LExit: else if (BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER == shutdownAction) { LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RELOAD); - *pfReloadApp = TRUE; + *pfReloadApp = SUCCEEDED(hr); } else if (BOOTSTRAPPER_SHUTDOWN_ACTION_SKIP_CLEANUP == shutdownAction) { @@ -806,7 +806,7 @@ LExit: } // Unload BA. - UserExperienceUnload(&pEngineState->userExperience); + UserExperienceUnload(&pEngineState->userExperience, *pfReloadApp); return hr; } diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 4325a6ee..87ef4de1 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp @@ -122,7 +122,6 @@ extern "C" HRESULT UserExperienceLoad( pUserExperience->pfnBAProc = results.pfnBootstrapperApplicationProc; pUserExperience->pvBAProcContext = results.pvBootstrapperApplicationProcContext; - pUserExperience->fDisableUnloading = results.fDisableUnloading; LExit: return hr; @@ -133,10 +132,18 @@ LExit: *******************************************************************/ extern "C" HRESULT UserExperienceUnload( - __in BURN_USER_EXPERIENCE* pUserExperience + __in BURN_USER_EXPERIENCE* pUserExperience, + __in BOOL fReload ) { HRESULT hr = S_OK; + BOOTSTRAPPER_DESTROY_ARGS args = { }; + BOOTSTRAPPER_DESTROY_RESULTS results = { }; + + args.cbSize = sizeof(BOOTSTRAPPER_DESTROY_ARGS); + args.fReload = fReload; + + results.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS); if (pUserExperience->hUXModule) { @@ -144,11 +151,11 @@ extern "C" HRESULT UserExperienceUnload( PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = (PFN_BOOTSTRAPPER_APPLICATION_DESTROY)::GetProcAddress(pUserExperience->hUXModule, "BootstrapperApplicationDestroy"); if (pfnDestroy) { - pfnDestroy(); + pfnDestroy(&args, &results); } // Free BA DLL if it supports it. - if (!pUserExperience->fDisableUnloading && !::FreeLibrary(pUserExperience->hUXModule)) + if (!results.fDisableUnloading && !::FreeLibrary(pUserExperience->hUXModule)) { hr = HRESULT_FROM_WIN32(::GetLastError()); TraceError(hr, "Failed to unload BA DLL."); diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index e7489710..94b73f7d 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h @@ -22,7 +22,6 @@ typedef struct _BURN_USER_EXPERIENCE HMODULE hUXModule; PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBAProc; LPVOID pvBAProcContext; - BOOL fDisableUnloading; LPWSTR sczTempDirectory; CRITICAL_SECTION csEngineActive; // Changing the engine active state in the user experience must be @@ -61,7 +60,8 @@ HRESULT UserExperienceLoad( __in BOOTSTRAPPER_COMMAND* pCommand ); HRESULT UserExperienceUnload( - __in BURN_USER_EXPERIENCE* pUserExperience + __in BURN_USER_EXPERIENCE* pUserExperience, + __in BOOL fReload ); HRESULT UserExperienceEnsureWorkingFolder( __in BURN_CACHE* pCache, diff --git a/src/ext/Bal/Samples/bafunctions/bafunctions.cpp b/src/ext/Bal/Samples/bafunctions/bafunctions.cpp index b20f4230..fc9d1177 100644 --- a/src/ext/Bal/Samples/bafunctions/bafunctions.cpp +++ b/src/ext/Bal/Samples/bafunctions/bafunctions.cpp @@ -40,6 +40,8 @@ LExit: } extern "C" void WINAPI BAFunctionsDestroy( + __in const BA_FUNCTIONS_DESTROY_ARGS* /*pArgs*/, + __inout BA_FUNCTIONS_DESTROY_RESULTS* /*pResults*/ ) { BalUninitialize(); diff --git a/src/ext/Bal/dnchost/dnchost.cpp b/src/ext/Bal/dnchost/dnchost.cpp index 644ba30e..6c066f43 100644 --- a/src/ext/Bal/dnchost/dnchost.cpp +++ b/src/ext/Bal/dnchost/dnchost.cpp @@ -21,9 +21,8 @@ static HRESULT LoadManagedBootstrapperApplicationFactory( __in DNCSTATE* pState ); static HRESULT CreatePrerequisiteBA( - __in HRESULT hrHostInitialization, + __in DNCSTATE* pState, __in IBootstrapperEngine* pEngine, - __in LPCWSTR wzAppBase, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults ); @@ -58,13 +57,8 @@ 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. - // This means we also can't unload. - pResults->fDisableUnloading = TRUE; - hr = BalInitializeFromCreateArgs(pArgs, &pEngine); ExitOnFailure(hr, "Failed to initialize Bal."); @@ -106,16 +100,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( { if (DNCHOSTTYPE_SCD == vstate.type) { - hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE; + vstate.prereqData.hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE; BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error."); } + else if (vstate.prereqData.fCompleted) + { + hr = E_PREREQBA_INFINITE_LOOP; + BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); + vstate.prereqData.hrHostInitialization = hr; + } else { - hrHostInitialization = S_OK; + vstate.prereqData.hrHostInitialization = S_OK; } BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr); - hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults); + hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults); BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); } @@ -125,14 +125,21 @@ LExit: return hr; } -extern "C" void WINAPI BootstrapperApplicationDestroy() +extern "C" void WINAPI BootstrapperApplicationDestroy( + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults + ) { + BOOTSTRAPPER_DESTROY_RESULTS childResults = { }; + + childResults.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS); + if (vstate.hMbapreqModule) { - PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy")); + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy")); if (pfnDestroy) { - (*pfnDestroy)(); + (*pfnDestroy)(pArgs, &childResults); } ::FreeLibrary(vstate.hMbapreqModule); @@ -140,6 +147,9 @@ extern "C" void WINAPI BootstrapperApplicationDestroy() } BalUninitialize(); + + // Need to keep track of state between reloads. + pResults->fDisableUnloading = TRUE; } static HRESULT LoadModulePaths( @@ -262,9 +272,8 @@ static HRESULT LoadManagedBootstrapperApplicationFactory( } static HRESULT CreatePrerequisiteBA( - __in HRESULT hrHostInitialization, + __in DNCSTATE* pState, __in IBootstrapperEngine* pEngine, - __in LPCWSTR wzAppBase, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults ) @@ -273,19 +282,19 @@ static HRESULT CreatePrerequisiteBA( LPWSTR sczDncpreqPath = NULL; HMODULE hModule = NULL; - hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath); + hr = PathConcat(pState->sczAppBase, L"dncpreq.dll", &sczDncpreqPath); BalExitOnFailure(hr, "Failed to get path to pre-requisite BA."); - hModule = ::LoadLibraryW(sczDncpreqPath); + hModule = ::LoadLibraryExW(sczDncpreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 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); + PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate")); + BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath); - hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); + hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults); BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); - vstate.hMbapreqModule = hModule; + pState->hMbapreqModule = hModule; hModule = NULL; LExit: diff --git a/src/ext/Bal/dnchost/dnchost.h b/src/ext/Bal/dnchost/dnchost.h index b0ba9638..000cf43d 100644 --- a/src/ext/Bal/dnchost/dnchost.h +++ b/src/ext/Bal/dnchost/dnchost.h @@ -9,13 +9,6 @@ enum DNCHOSTTYPE DNCHOSTTYPE_SCD, }; -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; @@ -31,4 +24,5 @@ struct DNCSTATE HOSTFXR_STATE hostfxrState; IBootstrapperApplicationFactory* pAppFactory; HMODULE hMbapreqModule; + PREQBA_DATA prereqData; }; diff --git a/src/ext/Bal/dnchost/dnchost.vcxproj b/src/ext/Bal/dnchost/dnchost.vcxproj index ca0c09d6..b258ccae 100644 --- a/src/ext/Bal/dnchost/dnchost.vcxproj +++ b/src/ext/Bal/dnchost/dnchost.vcxproj @@ -50,7 +50,7 @@ $(Platform) x86 ..\..\..\..\packages\runtime.win-$(NetHostPlatform).Microsoft.NETCore.DotNetAppHost.6.0.4\runtimes\win-$(NetHostPlatform)\native\ - $(BaseOutputPath)obj;$(NetHostPath) + $(BaseOutputPath)obj;$(NetHostPath);..\wixstdba\inc shlwapi.lib;$(NetHostPath)libnethost.lib diff --git a/src/ext/Bal/dnchost/precomp.h b/src/ext/Bal/dnchost/precomp.h index 7aefc4e3..5f365fba 100644 --- a/src/ext/Bal/dnchost/precomp.h +++ b/src/ext/Bal/dnchost/precomp.h @@ -25,6 +25,8 @@ #include #include +#include + #include "coreclrhost.h" #include "dncutil.h" #include "dnchost.h" diff --git a/src/ext/Bal/mbahost/mbahost.cpp b/src/ext/Bal/mbahost/mbahost.cpp index a9585389..3de77a05 100644 --- a/src/ext/Bal/mbahost/mbahost.cpp +++ b/src/ext/Bal/mbahost/mbahost.cpp @@ -1,7 +1,6 @@ // 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. #include "precomp.h" -#include // includes the generated assembly name macros. static const DWORD NET452_RELEASE = 379893; @@ -14,26 +13,16 @@ extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)( __out LPVOID *ppv ); -extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( - __in HRESULT hrHostInitialization, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ); - -static HINSTANCE vhInstance = NULL; -static ICorRuntimeHost *vpCLRHost = NULL; -static _AppDomain *vpAppDomain = NULL; -static HMODULE vhMbapreqModule = NULL; +static MBASTATE vstate = { }; // internal function declarations static HRESULT GetAppDomain( - __out _AppDomain** ppAppDomain + __in MBASTATE* pState ); -static HRESULT GetAppBase( - __out LPWSTR* psczAppBase +static HRESULT LoadModulePaths( + __in MBASTATE* pState ); static HRESULT CheckSupportedFrameworks( __in LPCWSTR wzConfigPath @@ -43,9 +32,8 @@ static HRESULT UpdateSupportedRuntime( __in IXMLDOMNode* pixnSupportedFramework, __out BOOL* pfUpdatedManifest ); -static HRESULT GetCLRHost( - __in LPCWSTR wzConfigPath, - __out ICorRuntimeHost** ppCLRHost +static HRESULT LoadRuntime( + __in MBASTATE* pState ); static HRESULT CreateManagedBootstrapperApplication( __in _AppDomain* pAppDomain, @@ -57,7 +45,7 @@ static HRESULT CreateManagedBootstrapperApplicationFactory( __out IBootstrapperApplicationFactory** ppAppFactory ); static HRESULT CreatePrerequisiteBA( - __in HRESULT hrHostInitialization, + __in MBASTATE* pState, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults @@ -78,11 +66,11 @@ extern "C" BOOL WINAPI DllMain( { case DLL_PROCESS_ATTACH: ::DisableThreadLibraryCalls(hInstance); - vhInstance = hInstance; + vstate.hInstance = hInstance; break; case DLL_PROCESS_DETACH: - vhInstance = NULL; + vstate.hInstance = NULL; break; } @@ -96,18 +84,39 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( ) { HRESULT hr = S_OK; - HRESULT hrHostInitialization = S_OK; IBootstrapperEngine* pEngine = NULL; + if (vstate.fStoppedRuntime) + { + BalExitWithRootFailure(hr, E_INVALIDSTATE, "Reloaded mbahost after stopping .NET runtime."); + } + hr = BalInitializeFromCreateArgs(pArgs, &pEngine); ExitOnFailure(hr, "Failed to initialize Bal."); - hr = GetAppDomain(&vpAppDomain); - if (SUCCEEDED(hr)) + if (!vstate.fInitialized) + { + hr = LoadModulePaths(&vstate); + BalExitOnFailure(hr, "Failed to load the module paths."); + + vstate.fInitialized = TRUE; + } + + if (!vstate.fInitializedRuntime) + { + hr = LoadRuntime(&vstate); + + vstate.fInitializedRuntime = SUCCEEDED(hr); + } + + if (vstate.fInitializedRuntime) { + hr = GetAppDomain(&vstate); + BalExitOnFailure(hr, "Failed to create the AppDomain for the managed bootstrapper application."); + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application."); - hr = CreateManagedBootstrapperApplication(vpAppDomain, pArgs, pResults); + hr = CreateManagedBootstrapperApplication(vstate.pAppDomain, pArgs, pResults); BalExitOnFailure(hr, "Failed to create the managed bootstrapper application."); } else // fallback to the prerequisite BA. @@ -115,16 +124,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( if (E_MBAHOST_NET452_ON_WIN7RTM == hr) { BalLogError(hr, "The Burn engine cannot run with an MBA under the .NET 4 CLR on Windows 7 RTM with .NET 4.5.2 (or greater) installed."); - hrHostInitialization = hr; + vstate.prereqData.hrHostInitialization = hr; + } + else if (vstate.prereqData.fCompleted) + { + hr = E_PREREQBA_INFINITE_LOOP; + BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); + vstate.prereqData.hrHostInitialization = hr; } else { - hrHostInitialization = S_OK; + vstate.prereqData.hrHostInitialization = S_OK; } BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr); - hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, pArgs, pResults); + hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults); BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); } @@ -134,73 +149,65 @@ LExit: return hr; } -extern "C" void WINAPI BootstrapperApplicationDestroy() +extern "C" void WINAPI BootstrapperApplicationDestroy( + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults + ) { - if (vpAppDomain) + BOOTSTRAPPER_DESTROY_RESULTS childResults = { }; + + if (vstate.pAppDomain) { - HRESULT hr = vpCLRHost->UnloadDomain(vpAppDomain); + HRESULT hr = vstate.pCLRHost->UnloadDomain(vstate.pAppDomain); if (FAILED(hr)) { BalLogError(hr, "Failed to unload app domain."); } - vpAppDomain->Release(); + vstate.pAppDomain->Release(); + vstate.pAppDomain = NULL; } - if (vpCLRHost) + // pCLRHost can only be stopped once per process. + if (vstate.pCLRHost && !pArgs->fReload) { - vpCLRHost->Stop(); - vpCLRHost->Release(); + vstate.pCLRHost->Stop(); + vstate.pCLRHost->Release(); + vstate.pCLRHost = NULL; + vstate.fStoppedRuntime = TRUE; } - if (vhMbapreqModule) + if (vstate.hMbapreqModule) { - PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vhMbapreqModule, "MbaPrereqBootstrapperApplicationDestroy")); + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy")); if (pfnDestroy) { - (*pfnDestroy)(); + (*pfnDestroy)(pArgs, &childResults); } - ::FreeLibrary(vhMbapreqModule); - vhMbapreqModule = NULL; + ::FreeLibrary(vstate.hMbapreqModule); + vstate.hMbapreqModule = NULL; } BalUninitialize(); + + // Need to keep track of state between reloads. + pResults->fDisableUnloading = TRUE; } // Gets the custom AppDomain for loading managed BA. static HRESULT GetAppDomain( - __out _AppDomain **ppAppDomain + __in MBASTATE* pState ) { HRESULT hr = S_OK; - ICorRuntimeHost *pCLRHost = NULL; IUnknown *pUnk = NULL; - LPWSTR sczAppBase = NULL; - LPWSTR sczConfigPath = NULL; - IAppDomainSetup *pAppDomainSetup; + IAppDomainSetup* pAppDomainSetup = NULL; BSTR bstrAppBase = NULL; BSTR bstrConfigPath = NULL; - hr = GetAppBase(&sczAppBase); - ExitOnFailure(hr, "Failed to get the host base path."); - - hr = PathConcat(sczAppBase, MBA_CONFIG_FILE_NAME, &sczConfigPath); - ExitOnFailure(hr, "Failed to get the full path to the application configuration file."); - - // Check that the supported framework is installed. - hr = CheckSupportedFrameworks(sczConfigPath); - ExitOnFailure(hr, "Failed to find supported framework."); - - // Load the CLR. - hr = GetCLRHost(sczConfigPath, &pCLRHost); - ExitOnFailure(hr, "Failed to create the CLR host."); - - hr = pCLRHost->Start(); - ExitOnRootFailure(hr, "Failed to start the CLR host."); - // Create the setup information for a new AppDomain to set the app base and config. - hr = pCLRHost->CreateDomainSetup(&pUnk); + hr = pState->pCLRHost->CreateDomainSetup(&pUnk); ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object."); hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast(&pAppDomainSetup)); @@ -208,49 +215,49 @@ static HRESULT GetAppDomain( ReleaseNullObject(pUnk); // Set properties on the AppDomainSetup object. - bstrAppBase = ::SysAllocString(sczAppBase); + bstrAppBase = ::SysAllocString(pState->sczAppBase); ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup."); hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase); ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup."); - bstrConfigPath = ::SysAllocString(sczConfigPath); + bstrConfigPath = ::SysAllocString(pState->sczConfigPath); ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup."); hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath); ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup."); // Create the AppDomain to load the factory type. - hr = pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk); + hr = pState->pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk); ExitOnRootFailure(hr, "Failed to create the MBA AppDomain."); - hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast(ppAppDomain)); + hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast(&pState->pAppDomain)); ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface."); LExit: ReleaseBSTR(bstrConfigPath); ReleaseBSTR(bstrAppBase); - ReleaseStr(sczConfigPath); - ReleaseStr(sczAppBase); ReleaseNullObject(pUnk); - ReleaseNullObject(pCLRHost); return hr; } -static HRESULT GetAppBase( - __out LPWSTR *psczAppBase +static HRESULT LoadModulePaths( + __in MBASTATE* pState ) { HRESULT hr = S_OK; LPWSTR sczFullPath = NULL; - hr = PathForCurrentProcess(&sczFullPath, vhInstance); + hr = PathForCurrentProcess(&sczFullPath, pState->hInstance); ExitOnFailure(hr, "Failed to get the full host path."); - hr = PathGetDirectory(sczFullPath, psczAppBase); + hr = PathGetDirectory(sczFullPath, &pState->sczAppBase); ExitOnFailure(hr, "Failed to get the directory of the full process path."); + hr = PathConcat(pState->sczAppBase, MBA_CONFIG_FILE_NAME, &pState->sczConfigPath); + ExitOnFailure(hr, "Failed to get the full path to the application configuration file."); + LExit: ReleaseStr(sczFullPath); @@ -390,9 +397,8 @@ LExit: } // Gets the CLR host and caches it. -static HRESULT GetCLRHost( - __in LPCWSTR wzConfigPath, - __out ICorRuntimeHost **ppCLRHost +static HRESULT LoadRuntime( + __in MBASTATE* pState ) { HRESULT hr = S_OK; @@ -411,84 +417,81 @@ static HRESULT GetCLRHost( // Always set the error mode because we will always restore it below. uiMode = ::SetErrorMode(0); - // Cache the CLR host to be shutdown later. This can occur on a different thread. - if (!vpCLRHost) - { - // Disable message boxes from being displayed on error and blocking execution. - ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS); + // Check that the supported framework is installed. + hr = CheckSupportedFrameworks(pState->sczConfigPath); + ExitOnFailure(hr, "Failed to find supported framework."); - hr = LoadSystemLibrary(L"mscoree.dll", &hModule); - ExitOnFailure(hr, "Failed to load mscoree.dll"); + // Cache the CLR host to be shutdown later. This can occur on a different thread. + // Disable message boxes from being displayed on error and blocking execution. + ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS); - pfnCLRCreateInstance = reinterpret_cast(::GetProcAddress(hModule, "CLRCreateInstance")); - - if (pfnCLRCreateInstance) - { - hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast(&pCLRMetaHostPolicy)); - if (E_NOTIMPL != hr) - { - ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy."); + hr = LoadSystemLibrary(L"mscoree.dll", &hModule); + ExitOnFailure(hr, "Failed to load mscoree.dll"); - fFallbackToCorBindToCurrentRuntime = FALSE; - } - } + pfnCLRCreateInstance = reinterpret_cast(::GetProcAddress(hModule, "CLRCreateInstance")); - if (fFallbackToCorBindToCurrentRuntime) + if (pfnCLRCreateInstance) + { + hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast(&pCLRMetaHostPolicy)); + if (E_NOTIMPL != hr) { - pfnCorBindToCurrentRuntime = reinterpret_cast(::GetProcAddress(hModule, "CorBindToCurrentRuntime")); - ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime."); + ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy."); - hr = pfnCorBindToCurrentRuntime(wzConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&vpCLRHost)); - ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path."); + fFallbackToCorBindToCurrentRuntime = FALSE; } - else - { - - hr = SHCreateStreamOnFileEx(wzConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream); - ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath); + } - hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast(&pCLRRuntimeInfo)); - ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path."); + if (fFallbackToCorBindToCurrentRuntime) + { + pfnCorBindToCurrentRuntime = reinterpret_cast(::GetProcAddress(hModule, "CorBindToCurrentRuntime")); + ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime."); - // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL. - if (!cchVersion) - { - hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion); - if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) - { - ExitOnFailure(hr, "Failed to get the length of the CLR version string."); - } - } + hr = pfnCorBindToCurrentRuntime(pState->sczConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&pState->pCLRHost)); + ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path."); + } + else + { - hr = StrAlloc(&pwzVersion, cchVersion); - ExitOnFailure(hr, "Failed to allocate the CLR version string."); + hr = SHCreateStreamOnFileEx(pState->sczConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream); + ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", pState->sczConfigPath); - hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion); - ExitOnFailure(hr, "Failed to get the CLR version string."); + hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast(&pCLRRuntimeInfo)); + ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path."); - if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion)) + // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL. + if (!cchVersion) + { + hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion); + if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) { - hr = VerifyNET4RuntimeIsSupported(); - ExitOnFailure(hr, "Found unsupported .NET 4 Runtime."); + ExitOnFailure(hr, "Failed to get the length of the CLR version string."); } + } - if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags)) - { - hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime(); - ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime."); - } + hr = StrAlloc(&pwzVersion, cchVersion); + ExitOnFailure(hr, "Failed to allocate the CLR version string."); - hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&vpCLRHost)); - ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost."); + hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion); + ExitOnFailure(hr, "Failed to get the CLR version string."); + + if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion)) + { + hr = VerifyNET4RuntimeIsSupported(); + ExitOnFailure(hr, "Found unsupported .NET 4 Runtime."); + } - // TODO: use ICLRRuntimeHost instead of ICorRuntimeHost on .NET 4 since the former is faster and the latter is deprecated - //hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast(&pCLRRuntimeHost)); - //ExitOnRootFailure(hr, "Failed to get instance of ICLRRuntimeHost."); + if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags)) + { + hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime(); + ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime."); } + + hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&pState->pCLRHost)); + ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost."); } - vpCLRHost->AddRef(); - *ppCLRHost = vpCLRHost; + hr = pState->pCLRHost->Start(); + ExitOnRootFailure(hr, "Failed to start the CLR host."); LExit: ReleaseStr(pwzVersion); @@ -569,7 +572,7 @@ LExit: } static HRESULT CreatePrerequisiteBA( - __in HRESULT hrHostInitialization, + __in MBASTATE* pState, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults @@ -579,19 +582,19 @@ static HRESULT CreatePrerequisiteBA( LPWSTR sczMbapreqPath = NULL; HMODULE hModule = NULL; - hr = PathRelativeToModule(&sczMbapreqPath, L"mbapreq.dll", vhInstance); - ExitOnFailure(hr, "Failed to get path to pre-requisite BA."); + hr = PathConcat(pState->sczAppBase, L"mbapreq.dll", &sczMbapreqPath); + BalExitOnFailure(hr, "Failed to get path to pre-requisite BA."); - hModule = ::LoadLibraryW(sczMbapreqPath); + hModule = ::LoadLibraryExW(sczMbapreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); - PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast(::GetProcAddress(hModule, "MbaPrereqBootstrapperApplicationCreate")); - ExitOnNullWithLastError(pfnCreate, hr, "Failed to get MbaPrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath); + PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate")); + ExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath); - hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); + hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults); ExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); - vhMbapreqModule = hModule; + pState->hMbapreqModule = hModule; hModule = NULL; LExit: diff --git a/src/ext/Bal/mbahost/mbahost.h b/src/ext/Bal/mbahost/mbahost.h new file mode 100644 index 00000000..19cf8311 --- /dev/null +++ b/src/ext/Bal/mbahost/mbahost.h @@ -0,0 +1,17 @@ +#pragma once +// 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. + + +struct MBASTATE +{ + BOOL fInitialized; + BOOL fInitializedRuntime; + BOOL fStoppedRuntime; + HINSTANCE hInstance; + LPWSTR sczAppBase; + LPWSTR sczConfigPath; + mscorlib::_AppDomain* pAppDomain; + ICorRuntimeHost* pCLRHost; + HMODULE hMbapreqModule; + PREQBA_DATA prereqData; +}; diff --git a/src/ext/Bal/mbahost/mbahost.vcxproj b/src/ext/Bal/mbahost/mbahost.vcxproj index cd90776b..a8fbbcc2 100644 --- a/src/ext/Bal/mbahost/mbahost.vcxproj +++ b/src/ext/Bal/mbahost/mbahost.vcxproj @@ -41,7 +41,7 @@ - $(BaseOutputPath)obj + $(BaseOutputPath)obj;..\wixstdba\inc shlwapi.lib @@ -52,6 +52,7 @@ + diff --git a/src/ext/Bal/mbahost/precomp.h b/src/ext/Bal/mbahost/precomp.h index d29a23f3..a07f2fc0 100644 --- a/src/ext/Bal/mbahost/precomp.h +++ b/src/ext/Bal/mbahost/precomp.h @@ -16,10 +16,15 @@ #include #include -#include "BootstrapperEngine.h" -#include "BootstrapperApplication.h" -#include "IBootstrapperEngine.h" -#include "IBootstrapperApplication.h" -#include "IBootstrapperApplicationFactory.h" +#include +#include +#include +#include +#include -#include "balutil.h" +#include + +#include +#include // includes the generated assembly name macros. + +#include "mbahost.h" diff --git a/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp b/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp index 46fd9afa..3f290b86 100644 --- a/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp +++ b/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp @@ -31,7 +31,7 @@ HRESULT RunReloadEngine( hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER); ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); - pTestEngine->UnloadBA(); + pTestEngine->UnloadBA(TRUE); hr = pTestEngine->LoadBA(wzBAFilePath); ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to load BA."); @@ -48,7 +48,7 @@ HRESULT RunReloadEngine( hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART); ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); - pTestEngine->UnloadBA(); + pTestEngine->UnloadBA(FALSE); LExit: return hr; diff --git a/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp b/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp index 3b876e4e..b5c8c462 100644 --- a/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp +++ b/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp @@ -31,7 +31,7 @@ HRESULT RunShutdownEngine( hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER); ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); - pTestEngine->UnloadBA(); + pTestEngine->UnloadBA(FALSE); LExit: return hr; diff --git a/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp b/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp index 4c7ec1c3..5c6ed398 100644 --- a/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp +++ b/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp @@ -147,10 +147,18 @@ HRESULT TestEngine::SimulateQuit( return BAEngineQuit(&args, &results); } -void TestEngine::UnloadBA() +void TestEngine::UnloadBA( + __in BOOL fReload + ) { PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = NULL; - BOOL fDisableUnloading = m_pCreateResults && m_pCreateResults->fDisableUnloading; + BOOTSTRAPPER_DESTROY_ARGS args = { }; + BOOTSTRAPPER_DESTROY_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.fReload = fReload; + + results.cbSize = sizeof(results); ReleaseNullMem(m_pCreateResults); @@ -158,12 +166,12 @@ void TestEngine::UnloadBA() if (pfnDestroy) { - pfnDestroy(); + pfnDestroy(&args, &results); } if (m_hBAModule) { - if (!fDisableUnloading) + if (!results.fDisableUnloading) { ::FreeLibrary(m_hBAModule); } diff --git a/src/ext/Bal/test/examples/TestEngine/TestEngine.h b/src/ext/Bal/test/examples/TestEngine/TestEngine.h index 44e813bd..248e979a 100644 --- a/src/ext/Bal/test/examples/TestEngine/TestEngine.h +++ b/src/ext/Bal/test/examples/TestEngine/TestEngine.h @@ -44,7 +44,9 @@ public: __in DWORD dwExitCode ); - void UnloadBA(); + void UnloadBA( + __in BOOL fReload + ); private: HRESULT BAEngineLog( @@ -77,4 +79,4 @@ private: HMODULE m_hBAModule; BOOTSTRAPPER_CREATE_RESULTS* m_pCreateResults; DWORD m_dwThreadId; -}; \ No newline at end of file +}; diff --git a/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp b/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp index 2f80ba75..64b618f4 100644 --- a/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp +++ b/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp @@ -28,7 +28,7 @@ HRESULT RunWaitForQuitEngine( hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER); ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); - pTestEngine->UnloadBA(); + pTestEngine->UnloadBA(FALSE); LExit: return hr; diff --git a/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl index 19e79bac..f574bb9b 100644 --- a/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl @@ -29,5 +29,6 @@ 重新啟動(&R) 關閉(&C) [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl index e6e6f469..11d9f85a 100644 --- a/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl @@ -32,5 +32,6 @@ &Restartovat &Zavřít [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl index 98518edc..50412e12 100644 --- a/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl @@ -32,5 +32,6 @@ &Genstart &Luk [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl index e60b0c9a..4df66298 100644 --- a/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl @@ -35,5 +35,6 @@ &Neu starten &Schließen [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl index ea5dc130..05ac553f 100644 --- a/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl @@ -34,5 +34,6 @@ &Επανεκκίνηση &Κλείσιμο [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl index 803cacf5..2b7c0519 100644 --- a/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl @@ -32,5 +32,6 @@ &Käynnistä uudelleen &Sulje [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl index fb927f2b..3ae1cbd9 100644 --- a/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl @@ -32,5 +32,6 @@ &Redémarrer &Fermer [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl index 78c008b2..f491d6f2 100644 --- a/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl @@ -32,5 +32,6 @@ &Újraindítás &Bezárás [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl index b7966340..50bc73e8 100644 --- a/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl @@ -33,5 +33,6 @@ &Riavvia &Chiudi [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl index 9b7aa323..106c704a 100644 --- a/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl @@ -29,5 +29,6 @@ 再起動(&R) 閉じる(&C) [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl index 445d445b..24655588 100644 --- a/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl @@ -29,5 +29,6 @@ 다시 시작(&R) 닫기(&C) [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl index 60ba996e..d2e572fc 100644 --- a/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl @@ -32,5 +32,6 @@ &Opnieuw opstarten &Sluiten [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl index e0718b8d..cb6036ee 100644 --- a/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl @@ -32,5 +32,6 @@ &Start på nytt &Lukk [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl index 8b4eb758..41832b13 100644 --- a/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl @@ -32,5 +32,6 @@ &Uruchom ponownie &Zamknij [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl index 0155eb39..08968f93 100644 --- a/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl @@ -31,5 +31,6 @@ &Reiniciar &Fechar [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl index 87350745..271d5563 100644 --- a/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl @@ -31,5 +31,6 @@ &Перезагрузить &Закрыть [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl index 7645a37f..ce6f6eda 100644 --- a/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl @@ -32,5 +32,6 @@ &Reštartovať &Zavrieť [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl index b00205d8..2d0581b1 100644 --- a/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl @@ -32,5 +32,6 @@ &Starta om &Stäng [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl index 00c3c187..c48a44da 100644 --- a/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl @@ -32,5 +32,6 @@ &Yeniden Başlat &Kapat [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl index 72d48267..0398a7f1 100644 --- a/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl @@ -32,5 +32,6 @@ &Ponovni zagon &Zapri [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl index 365ee7e6..09f09cb3 100644 --- a/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl @@ -29,5 +29,6 @@ 重启(&R) 关闭(&C) [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl index 442a5571..f22822d8 100644 --- a/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl @@ -31,5 +31,6 @@ &Reiniciar &Fechar [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl index 37c0dc05..edbf01c4 100644 --- a/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl @@ -33,5 +33,6 @@ &Reiniciar &Cerrar [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/dncpreq.wxl b/src/ext/Bal/wixstdba/Resources/dncpreq.wxl index a53b1c83..22fcd3dc 100644 --- a/src/ext/Bal/wixstdba/Resources/dncpreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/dncpreq.wxl @@ -29,5 +29,6 @@ &Restart &Close [WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment. + [WixBundleName] failed to load the .NET Core runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/Resources/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/mbapreq.wxl index 5d410888..77859d31 100644 --- a/src/ext/Bal/wixstdba/Resources/mbapreq.wxl +++ b/src/ext/Bal/wixstdba/Resources/mbapreq.wxl @@ -29,5 +29,6 @@ &Restart &Close [WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment. + [WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed. No action was taken as a system reboot is required. diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp index dd00a563..3774f49c 100644 --- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp @@ -123,14 +123,6 @@ enum WIXSTDBA_CONTROL LAST_WIXSTDBA_CONTROL, }; -typedef struct _WIXSTDBA_PACKAGE_INFO -{ - LPWSTR sczPackageId; - BOOL fWasAlreadyInstalled; - BOOL fPlannedToBeInstalled; - BOOL fSuccessfullyInstalled; -} WIXSTDBA_PACKAGE_INFO; - static HRESULT DAPI EvaluateVariableConditionCallback( __in_z LPCWSTR wzCondition, @@ -229,10 +221,7 @@ public: // IBootstrapperApplication { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded."); *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER; - } - else if (m_fPrereqAlreadyInstalled) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); + m_pPrereqData->fCompleted = TRUE; } else if (m_fPrereq) { @@ -311,38 +300,14 @@ public: // IBootstrapperApplication if (!fMissingFromCache) { - if (SUCCEEDED(BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine, &pPackage))) - { - InitializePackageInfoForPackage(pPackage); - } + BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine, &pPackage); + // Best effort } return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel); } - virtual STDMETHODIMP OnDetectPackageComplete( - __in LPCWSTR wzPackageId, - __in HRESULT /*hrStatus*/, - __in BOOTSTRAPPER_PACKAGE_STATE state, - __in BOOL /*fCached*/ - ) - { - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; - BAL_INFO_PACKAGE* pPackage = NULL; - - if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state && - SUCCEEDED(GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage)) && - pPackageInfo) - { - // If the package is already installed, remember that. - pPackageInfo->fWasAlreadyInstalled = TRUE; - } - - return S_OK; - } - - virtual STDMETHODIMP OnDetectComplete( __in HRESULT hrStatus, __in BOOL /*fEligibleForCleanup*/ @@ -366,29 +331,10 @@ public: // IBootstrapperApplication if (fEvaluateConditions) { hrStatus = EvaluateConditions(); - } - if (FAILED(hrStatus)) - { - fSkipToPlan = FALSE; - } - else - { - if (m_fPrereq) + if (FAILED(hrStatus)) { - m_fPrereqAlreadyInstalled = TRUE; - - // At this point we have to assume that all prerequisite packages need to be installed, so set to false if any of them aren't installed. - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i) - { - BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i]; - WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast(pPackage->pvCustomData); - if (pPackage->fPrereqPackage && pPackageInfo && !pPackageInfo->fWasAlreadyInstalled) - { - m_fPrereqAlreadyInstalled = FALSE; - break; - } - } + fSkipToPlan = FALSE; } } @@ -403,20 +349,20 @@ public: // IBootstrapperApplication } - virtual STDMETHODIMP OnPlanRelatedBundle( + virtual STDMETHODIMP OnPlanRelatedBundleType( __in_z LPCWSTR wzBundleId, - __in BOOTSTRAPPER_REQUEST_STATE recommendedState, - __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState, + __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE recommendedType, + __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType, __inout BOOL* pfCancel ) { // If we're only installing prerequisites, do not touch related bundles. if (m_fPrereq) { - *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE; + *pRequestedType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE; } - return CBalBaseBootstrapperApplication::OnPlanRelatedBundle(wzBundleId, recommendedState, pRequestedState, pfCancel); + return CBalBaseBootstrapperApplication::OnPlanRelatedBundleType(wzBundleId, recommendedType, pRequestedType, pfCancel); } @@ -434,7 +380,6 @@ public: // IBootstrapperApplication ) { HRESULT hr = S_OK; - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; BAL_INFO_PACKAGE* pPackage = NULL; // If we're planning to install prerequisites, install them. The prerequisites need to be installed @@ -443,10 +388,11 @@ public: // IBootstrapperApplication { // Only install prerequisite packages, and check the InstallCondition on them. BOOL fInstall = FALSE; - hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); - if (SUCCEEDED(hr) && pPackage->fPrereqPackage && pPackageInfo) + + hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + if (SUCCEEDED(hr) && pPackage->fPrereqPackage) { - pPackageInfo->fPlannedToBeInstalled = fInstall = BOOTSTRAPPER_PACKAGE_CONDITION_FALSE != installCondition; + fInstall = BOOTSTRAPPER_PACKAGE_CONDITION_FALSE != installCondition; } if (fInstall) @@ -503,7 +449,6 @@ public: // IBootstrapperApplication ) { HRESULT hr = S_OK; - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; BAL_INFO_PACKAGE* pPackage = NULL; BOOL fShowInternalUI = FALSE; INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE; @@ -521,7 +466,7 @@ public: // IBootstrapperApplication if (INSTALLUILEVEL_NOCHANGE != uiLevel) { - hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); + hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); if (SUCCEEDED(hr) && pPackage->sczDisplayInternalUICondition) { hr = BalEvaluateCondition(pPackage->sczDisplayInternalUICondition, &fShowInternalUI); @@ -545,23 +490,6 @@ public: // IBootstrapperApplication { HRESULT hr = S_OK; - if (m_fPrereq) - { - m_fPrereqAlreadyInstalled = TRUE; - - // Now that we've planned the packages, we can focus on the prerequisite packages that are supposed to be installed. - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i) - { - BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i]; - WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast(pPackage->pvCustomData); - if (pPackage->fPrereqPackage && pPackageInfo && !pPackageInfo->fWasAlreadyInstalled && pPackageInfo->fPlannedToBeInstalled) - { - m_fPrereqAlreadyInstalled = FALSE; - break; - } - } - } - SetState(WIXSTDBA_STATE_PLANNED, hrStatus); if (SUCCEEDED(hrStatus)) @@ -1033,13 +961,10 @@ public: // IBootstrapperApplication hr = __super::OnExecutePackageComplete(wzPackageId, hrStatus, restart, recommendation, pAction); - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; - BAL_INFO_PACKAGE* pPackage; - HRESULT hrPrereq = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); - if (SUCCEEDED(hrPrereq) && pPackageInfo) + BAL_INFO_PACKAGE* pPackage = NULL; + HRESULT hrPrereq = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + if (SUCCEEDED(hrPrereq)) { - pPackageInfo->fSuccessfullyInstalled = SUCCEEDED(hrStatus); - // If the prerequisite required a restart (any restart) then do an immediate // restart to ensure that the bundle will get launched again post reboot. if (m_fPrereq && pPackage->fPrereqPackage && BOOTSTRAPPER_APPLY_RESTART_NONE != restart) @@ -1157,28 +1082,7 @@ public: // IBootstrapperApplication if (m_fPrereq) { - m_fPrereqInstalled = TRUE; - BOOL fInstalledAPackage = FALSE; - - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i) - { - BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i]; - WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast(pPackage->pvCustomData); - if (pPackage->fPrereqPackage && pPackageInfo && pPackageInfo->fPlannedToBeInstalled && !pPackageInfo->fWasAlreadyInstalled) - { - if (pPackageInfo->fSuccessfullyInstalled) - { - fInstalledAPackage = TRUE; - } - else - { - m_fPrereqInstalled = FALSE; - break; - } - } - } - - m_fPrereqInstalled = m_fPrereqInstalled && fInstalledAPackage; + m_fPrereqInstalled = SUCCEEDED(hrStatus); } // If we are showing UI, wait a beat before moving to the final screen. @@ -1223,10 +1127,10 @@ public: // IBootstrapperApplication { BAL_INFO_PACKAGE* pPackage = NULL; - if (SUCCEEDED(hrStatus) && wzNewPackageId && - SUCCEEDED(BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage))) + if (SUCCEEDED(hrStatus) && wzNewPackageId) { - InitializePackageInfoForPackage(pPackage); + BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage); + // Best effort } return S_OK; @@ -2201,6 +2105,36 @@ public: //CBalBaseBootstrapperApplication return hr; } + void Uninitialize( + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __in BOOTSTRAPPER_DESTROY_RESULTS* /*pResults*/ + ) + { + if (m_hBAFModule) + { + BA_FUNCTIONS_DESTROY_ARGS args = { }; + BA_FUNCTIONS_DESTROY_RESULTS results = { }; + + args.cbSize = sizeof(BA_FUNCTIONS_DESTROY_ARGS); + args.fReload = pArgs->fReload; + + results.cbSize = sizeof(BA_FUNCTIONS_DESTROY_RESULTS); + + PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy")); + if (pfnBAFunctionsDestroy) + { + pfnBAFunctionsDestroy(&args, &results); + } + + if (!results.fDisableUnloading) + { + ::FreeLibrary(m_hBAFModule); + m_hBAFModule = NULL; + } + } + } + + private: // // UiThreadProc - entrypoint for UI thread. @@ -2214,6 +2148,7 @@ private: BOOL fComInitialized = FALSE; BOOL fRet = FALSE; MSG msg = { }; + DWORD dwQuit = 0; // Initialize COM and theme. hr = ::CoInitialize(NULL); @@ -2274,8 +2209,6 @@ private: pThis->DestroyMainWindow(); pThis->UninitializeTaskbarButton(); - // initiate engine shutdown - DWORD dwQuit = HRESULT_CODE(hr); if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult) { dwQuit = ERROR_SUCCESS_REBOOT_INITIATED; @@ -2284,6 +2217,17 @@ private: { dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED; } + else if (SEVERITY_ERROR == HRESULT_SEVERITY(hr) && FACILITY_WIN32 == HRESULT_FACILITY(hr)) + { + // Convert Win32 HRESULTs back to the error code. + dwQuit = HRESULT_CODE(hr); + } + else + { + dwQuit = hr; + } + + // initiate engine shutdown pThis->m_pEngine->Quit(dwQuit); ReleaseTheme(pThis->m_pTheme); @@ -2335,9 +2279,6 @@ private: GetBundleFileVersion(); // don't fail if we couldn't get the version info; best-effort only - hr = InitializePackageInfo(); - BalExitOnFailure(hr, "Failed to initialize wixstdba package information."); - if (m_fPrereq) { hr = InitializePrerequisiteInformation(); @@ -2521,38 +2462,6 @@ private: } - HRESULT InitializePackageInfo() - { - HRESULT hr = S_OK; - BAL_INFO_PACKAGE* pPackage = NULL; - - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i) - { - pPackage = &m_Bundle.packages.rgPackages[i]; - - hr = InitializePackageInfoForPackage(pPackage); - BalExitOnFailure(hr, "Failed to initialize wixstdba package info for package: %ls.", pPackage->sczId); - } - - LExit: - return hr; - } - - - HRESULT InitializePackageInfoForPackage( - __in BAL_INFO_PACKAGE* pPackage - ) - { - HRESULT hr = S_OK; - - pPackage->pvCustomData = MemAlloc(sizeof(WIXSTDBA_PACKAGE_INFO), TRUE); - BalExitOnNull(pPackage->pvCustomData, hr, E_OUTOFMEMORY, "Failed to allocate memory for wixstdba package info."); - - LExit: - return hr; - } - - HRESULT InitializePrerequisiteInformation() { HRESULT hr = S_OK; @@ -2673,35 +2582,6 @@ private: return hr; } - HRESULT GetPackageInfo( - __in_z LPCWSTR wzPackageId, - __out WIXSTDBA_PACKAGE_INFO** ppPackageInfo, - __out BAL_INFO_PACKAGE** ppPackage - ) - { - HRESULT hr = E_NOTFOUND; - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; - BAL_INFO_PACKAGE* pPackage = NULL; - - Assert(wzPackageId && *wzPackageId); - Assert(ppPackage); - Assert(ppPackageInfo); - - hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); - if (E_NOTFOUND != hr) - { - ExitOnFailure(hr, "Failed trying to find the requested package."); - - pPackageInfo = reinterpret_cast(pPackage->pvCustomData); - } - - *ppPackageInfo = pPackageInfo; - *ppPackage = pPackage; - - LExit: - return hr; - } - // // Get the file version of the bootstrapper and record in bootstrapper log file @@ -3408,6 +3288,23 @@ private: } } } + else if (E_PREREQBA_INFINITE_LOOP == m_hrFinal) + { + HRESULT hr = StrAllocString(&sczUnformattedText, L"#(loc.PREREQBAINFINITELOOPErrorMessage)", 0); + if (FAILED(hr)) + { + BalLogError(hr, "Failed to initialize PREREQBAINFINITELOOPErrorMessage loc identifier."); + } + else + { + hr = LocLocalizeString(m_pWixLoc, &sczUnformattedText); + if (FAILED(hr)) + { + BalLogError(hr, "Failed to localize PREREQBAINFINITELOOPErrorMessage: %ls", sczUnformattedText); + ReleaseNullStr(sczUnformattedText); + } + } + } else // try to get the error message from the error code. { StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL); @@ -3424,14 +3321,9 @@ private: StrAllocString(&sczText, sczUnformattedText, 0); } } - else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal) - { - if (sczUnformattedText) - { - BalFormatString(sczUnformattedText, &sczText); - } - } - else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal) + else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal || + E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal || + E_PREREQBA_INFINITE_LOOP == m_hrFinal) { if (sczUnformattedText) { @@ -4180,8 +4072,7 @@ public: // CWixStandardBootstrapperApplication( __in HMODULE hModule, - __in BOOL fPrereq, - __in HRESULT hrHostInitialization, + __in_opt PREQBA_DATA* pPrereqData, __in IBootstrapperEngine* pEngine ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000) { @@ -4210,7 +4101,7 @@ public: m_hWnd = NULL; m_state = WIXSTDBA_STATE_INITIALIZING; - m_hrFinal = hrHostInitialization; + m_hrFinal = pPrereqData ? pPrereqData->hrHostInitialization : S_OK; m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; m_fRestartRequired = FALSE; @@ -4231,9 +4122,9 @@ public: m_fShowingInternalUiThisPackage = FALSE; m_fTriedToLaunchElevated = FALSE; - m_fPrereq = fPrereq; + m_pPrereqData = pPrereqData; + m_fPrereq = NULL != pPrereqData; m_fPrereqInstalled = FALSE; - m_fPrereqAlreadyInstalled = FALSE; pEngine->AddRef(); m_pEngine = pEngine; @@ -4418,11 +4309,6 @@ public: AssertSz(!m_pTaskbarList, "Taskbar should have been released before destructor."); AssertSz(!m_pTheme, "Theme should have been released before destructor."); - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i) - { - ReleaseMem(m_Bundle.packages.rgPackages[i].pvCustomData); - } - ::DeleteCriticalSection(&m_csShowingInternalUiThisPackage); ReleaseStr(m_sczFailedMessage); ReleaseStr(m_sczConfirmCloseMessage); @@ -4436,18 +4322,6 @@ public: ReleaseStr(m_sczBundleVersion); ReleaseStr(m_sczAfterForcedRestartPackage); ReleaseNullObject(m_pEngine); - - if (m_hBAFModule) - { - PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy")); - if (pfnBAFunctionsDestroy) - { - pfnBAFunctionsDestroy(); - } - - ::FreeLibrary(m_hBAFModule); - m_hBAFModule = NULL; - } } private: @@ -4529,9 +4403,9 @@ private: BOOL m_fSupportCacheOnly; BOOL m_fRequestedCacheOnly; + PREQBA_DATA* m_pPrereqData; BOOL m_fPrereq; BOOL m_fPrereqInstalled; - BOOL m_fPrereqAlreadyInstalled; ITaskbarList3* m_pTaskbarList; UINT m_uTaskbarButtonCreatedMessage; @@ -4551,8 +4425,7 @@ private: // HRESULT CreateBootstrapperApplication( __in HMODULE hModule, - __in BOOL fPrereq, - __in HRESULT hrHostInitialization, + __in_opt PREQBA_DATA* pPrereqData, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults, @@ -4567,7 +4440,7 @@ HRESULT CreateBootstrapperApplication( BalExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type."); } - pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine); + pApplication = new CWixStandardBootstrapperApplication(hModule, pPrereqData, pEngine); BalExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object."); hr = pApplication->Initialize(pArgs); @@ -4584,6 +4457,17 @@ LExit: } +void DestroyBootstrapperApplication( + __in IBootstrapperApplication* pApplication, + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults + ) +{ + CWixStandardBootstrapperApplication* pBA = (CWixStandardBootstrapperApplication*)pApplication; + pBA->Uninitialize(pArgs, pResults); +} + + static HRESULT DAPI EvaluateVariableConditionCallback( __in_z LPCWSTR wzCondition, __out BOOL* pf, diff --git a/src/ext/Bal/wixstdba/inc/preqba.h b/src/ext/Bal/wixstdba/inc/preqba.h new file mode 100644 index 00000000..93a547ed --- /dev/null +++ b/src/ext/Bal/wixstdba/inc/preqba.h @@ -0,0 +1,16 @@ +#pragma once +// 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. + + +struct PREQBA_DATA +{ + HRESULT hrHostInitialization; + BOOL fCompleted; +}; + +extern "C" typedef HRESULT(WINAPI* PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE)( + __in PREQBA_DATA* pPreqData, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ); diff --git a/src/ext/Bal/wixstdba/precomp.h b/src/ext/Bal/wixstdba/precomp.h index ba56ae6d..290c125b 100644 --- a/src/ext/Bal/wixstdba/precomp.h +++ b/src/ext/Bal/wixstdba/precomp.h @@ -17,43 +17,49 @@ #include #include -#include "dutil.h" -#include "apputil.h" -#include "memutil.h" -#include "dictutil.h" -#include "dirutil.h" -#include "fileutil.h" -#include "locutil.h" -#include "logutil.h" -#include "pathutil.h" -#include "resrutil.h" -#include "shelutil.h" -#include "strutil.h" -#include "wndutil.h" -#include "thmutil.h" -#include "verutil.h" -#include "uriutil.h" -#include "xmlutil.h" - -#include "BootstrapperEngine.h" -#include "BootstrapperApplication.h" -#include "IBootstrapperEngine.h" -#include "IBootstrapperApplication.h" - -#include "balutil.h" -#include "balinfo.h" -#include "balcondition.h" - -#include "BAFunctions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "inc\preqba.h" #include "wixstdba.messages.h" HRESULT CreateBootstrapperApplication( __in HMODULE hModule, - __in BOOL fPrereq, - __in HRESULT hrHostInitialization, + __in_opt PREQBA_DATA* pPrereqData, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults, __out IBootstrapperApplication** ppApplication ); + +void DestroyBootstrapperApplication( + __in IBootstrapperApplication* pApplication, + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults + ); diff --git a/src/ext/Bal/wixstdba/wixstdba.cpp b/src/ext/Bal/wixstdba/wixstdba.cpp index a96f1738..47f3f677 100644 --- a/src/ext/Bal/wixstdba/wixstdba.cpp +++ b/src/ext/Bal/wixstdba/wixstdba.cpp @@ -50,7 +50,7 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate( hr = BalInitializeFromCreateArgs(pArgs, &pEngine); ExitOnFailure(hr, "Failed to initialize Bal."); - hr = CreateBootstrapperApplication(vhInstance, FALSE, S_OK, pEngine, pArgs, pResults, &vpApplication); + hr = CreateBootstrapperApplication(vhInstance, NULL, pEngine, pArgs, pResults, &vpApplication); BalExitOnFailure(hr, "Failed to create bootstrapper application interface."); LExit: @@ -60,45 +60,24 @@ LExit: } -extern "C" void WINAPI BootstrapperApplicationDestroy() -{ - ReleaseNullObject(vpApplication); - BalUninitialize(); - DutilUninitialize(); -} - - -extern "C" HRESULT WINAPI DncPrereqBootstrapperApplicationCreate( - __in HRESULT hrHostInitialization, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults +extern "C" void WINAPI BootstrapperApplicationDestroy( + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults ) { - HRESULT hr = S_OK; - - DutilInitialize(&WixstdbaTraceError); - - 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; -} - + if (vpApplication) + { + DestroyBootstrapperApplication(vpApplication, pArgs, pResults); + } -extern "C" void WINAPI DncPrereqBootstrapperApplicationDestroy() -{ ReleaseNullObject(vpApplication); BalUninitialize(); DutilUninitialize(); } -extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate( - __in HRESULT hrHostInitialization, +extern "C" HRESULT WINAPI PrereqBootstrapperApplicationCreate( + __in_opt PREQBA_DATA* pPrereqData, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, __inout BOOTSTRAPPER_CREATE_RESULTS* pResults @@ -110,19 +89,20 @@ extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate( BalInitialize(pEngine); - hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication); - BalExitOnFailure(hr, "Failed to create managed prerequisite bootstrapper application interface."); + hr = CreateBootstrapperApplication(vhInstance, pPrereqData, pEngine, pArgs, pResults, &vpApplication); + BalExitOnFailure(hr, "Failed to create prerequisite bootstrapper application interface."); LExit: return hr; } -extern "C" void WINAPI MbaPrereqBootstrapperApplicationDestroy() +extern "C" void WINAPI PrereqBootstrapperApplicationDestroy( + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults + ) { - ReleaseNullObject(vpApplication); - BalUninitialize(); - DutilUninitialize(); + BootstrapperApplicationDestroy(pArgs, pResults); } static void CALLBACK WixstdbaTraceError( diff --git a/src/ext/Bal/wixstdba/wixstdba.def b/src/ext/Bal/wixstdba/wixstdba.def index ba9980d3..e377196b 100644 --- a/src/ext/Bal/wixstdba/wixstdba.def +++ b/src/ext/Bal/wixstdba/wixstdba.def @@ -4,7 +4,5 @@ EXPORTS BootstrapperApplicationCreate BootstrapperApplicationDestroy - DncPrereqBootstrapperApplicationCreate - DncPrereqBootstrapperApplicationDestroy - MbaPrereqBootstrapperApplicationCreate - MbaPrereqBootstrapperApplicationDestroy + PrereqBootstrapperApplicationCreate + PrereqBootstrapperApplicationDestroy diff --git a/src/ext/Bal/wixstdba/wixstdba.vcxproj b/src/ext/Bal/wixstdba/wixstdba.vcxproj index a43cc345..9273c1ed 100644 --- a/src/ext/Bal/wixstdba/wixstdba.vcxproj +++ b/src/ext/Bal/wixstdba/wixstdba.vcxproj @@ -52,6 +52,7 @@ + diff --git a/src/test/burn/TestBA/TestBA.cs b/src/test/burn/TestBA/TestBA.cs index 5f492efd..1548c05b 100644 --- a/src/test/burn/TestBA/TestBA.cs +++ b/src/test/burn/TestBA/TestBA.cs @@ -171,7 +171,13 @@ namespace WixToolset.Test.BA this.dummyWindow.Dispose(); } - this.Engine.Quit(this.result & 0xFFFF); // return plain old Win32 error, not HRESULT. + var exitCode = this.result; + if ((exitCode & 0xFFFF0000) == unchecked(0x80070000)) + { + exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT. + } + + this.Engine.Quit(exitCode); } protected override void OnDetectUpdateBegin(DetectUpdateBeginEventArgs args) diff --git a/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp b/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp index b20f4230..fc9d1177 100644 --- a/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp +++ b/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp @@ -40,6 +40,8 @@ LExit: } extern "C" void WINAPI BAFunctionsDestroy( + __in const BA_FUNCTIONS_DESTROY_ARGS* /*pArgs*/, + __inout BA_FUNCTIONS_DESTROY_RESULTS* /*pResults*/ ) { BalUninitialize(); diff --git a/src/test/burn/WixToolset.WixBA/WixBA.cs b/src/test/burn/WixToolset.WixBA/WixBA.cs index 68288f2d..60426ca8 100644 --- a/src/test/burn/WixToolset.WixBA/WixBA.cs +++ b/src/test/burn/WixToolset.WixBA/WixBA.cs @@ -179,7 +179,14 @@ namespace WixToolset.WixBA Threading.Dispatcher.Run(); this.PostTelemetry(); - this.Engine.Quit(WixBA.Model.Result); + + var exitCode = WixBA.Model.Result; + if ((exitCode & 0xFFFF0000) == unchecked(0x80070000)) + { + exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT. + } + + this.Engine.Quit(exitCode); } private void PostTelemetry() diff --git a/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs index ec828f89..52e165b4 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs @@ -12,6 +12,8 @@ namespace WixToolsetTest.BurnE2E { public PrereqBaTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } + const int E_PREREQBA_INFINITE_LOOP = -2_114_714_646; + /// /// This bundle purposely provides a .runtimeconfig.json file that requires a version of .NET Core that doesn't exist, /// with an MSI package to represent the prerequisite package. @@ -32,7 +34,7 @@ namespace WixToolsetTest.BurnE2E // Source file should *not* be installed Assert.False(File.Exists(packageASourceCodeInstalled), $"Package A payload should not be there on test start: {packageASourceCodeInstalled}"); - bundleA.Install(); + bundleA.Install(E_PREREQBA_INFINITE_LOOP); // Part of the test is Install actually completing. @@ -63,7 +65,7 @@ namespace WixToolsetTest.BurnE2E // Source file should *not* be installed Assert.False(File.Exists(packageBSourceCodeInstalled), $"Package B payload should not be there on test start: {packageBSourceCodeInstalled}"); - bundleB.Install(); + bundleB.Install(E_PREREQBA_INFINITE_LOOP); // Part of the test is Install actually completing. -- cgit v1.2.3-55-g6feb