@joebigelow / wix-1 / commits / 6a6974a1

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.

Sean Hall committed May 13, 2022 at 13:50 UTC 6a6974a15deb6edf593736cdb8043bfb93064782
55 files changed +500 -493
src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+16 -2
@@ -1494,7 +1494,22 @@ extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_PROC)(
1494 __in_opt LPVOID pvContext
1495 );
1496
1497 -extern "C" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)();
1497 +struct BOOTSTRAPPER_DESTROY_ARGS
1498 +{
1499 + DWORD cbSize;
1500 + BOOL fReload;
1501 +};
1502 +
1503 +struct BOOTSTRAPPER_DESTROY_RESULTS
1504 +{
1505 + DWORD cbSize;
1506 + BOOL fDisableUnloading; // indicates the BA dll must not be unloaded after BootstrapperApplicationDestroy.
1507 +};
1508 +
1509 +extern "C" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)(
1510 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
1511 + __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
1512 + );
1513
1514
1515
@@ -1512,7 +1527,6 @@ struct BOOTSTRAPPER_CREATE_RESULTS
1527 DWORD cbSize;
1528 PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBootstrapperApplicationProc;
1529 LPVOID pvBootstrapperApplicationProcContext;
1515 - BOOL fDisableUnloading; // indicates the BA dll must not be unloaded after BootstrapperApplicationDestroy.
1530 };
1531
1532 extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_CREATE)(
src/api/burn/balutil/inc/BAFunctions.h
+16 -1
@@ -126,6 +126,18 @@ struct BA_FUNCTIONS_CREATE_RESULTS
126 LPVOID pvBAFunctionsProcContext;
127 };
128
129 +struct BA_FUNCTIONS_DESTROY_ARGS
130 +{
131 + DWORD cbSize;
132 + BOOL fReload;
133 +};
134 +
135 +struct BA_FUNCTIONS_DESTROY_RESULTS
136 +{
137 + DWORD cbSize;
138 + BOOL fDisableUnloading; // indicates the BAFunctions dll must not be unloaded after BAFunctionsDestroy.
139 +};
140 +
141 struct BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS
142 {
143 DWORD cbSize;
@@ -218,7 +230,10 @@ typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_CREATE)(
230 __inout BA_FUNCTIONS_CREATE_RESULTS* pResults
231 );
232
221 -typedef void (WINAPI *PFN_BA_FUNCTIONS_DESTROY)();
233 +typedef void (WINAPI *PFN_BA_FUNCTIONS_DESTROY)(
234 + __in const BA_FUNCTIONS_DESTROY_ARGS* pArgs,
235 + __inout BA_FUNCTIONS_DESTROY_RESULTS* pResults
236 + );
237
238 #ifdef __cplusplus
239 }
src/api/burn/balutil/inc/balutil.h
+1
@@ -39,6 +39,7 @@ static const HRESULT E_WIXSTDBA_CONDITION_FAILED = MAKE_HRESULT(SEVERITY_ERROR,
39
40 static const HRESULT E_MBAHOST_NET452_ON_WIN7RTM = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1000);
41 static const HRESULT E_DNCHOST_SCD_RUNTIME_FAILURE = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1001);
42 +static const HRESULT E_PREREQBA_INFINITE_LOOP = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1002);
43
44
45 /*******************************************************************
src/burn/engine/engine.cpp
+2 -2
@@ -796,7 +796,7 @@ LExit:
796 else if (BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER == shutdownAction)
797 {
798 LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RELOAD);
799 - *pfReloadApp = TRUE;
799 + *pfReloadApp = SUCCEEDED(hr);
800 }
801 else if (BOOTSTRAPPER_SHUTDOWN_ACTION_SKIP_CLEANUP == shutdownAction)
802 {
@@ -806,7 +806,7 @@ LExit:
806 }
807
808 // Unload BA.
809 - UserExperienceUnload(&pEngineState->userExperience);
809 + UserExperienceUnload(&pEngineState->userExperience, *pfReloadApp);
810
811 return hr;
812 }
src/burn/engine/userexperience.cpp
+11 -4
@@ -122,7 +122,6 @@ extern "C" HRESULT UserExperienceLoad(
122
123 pUserExperience->pfnBAProc = results.pfnBootstrapperApplicationProc;
124 pUserExperience->pvBAProcContext = results.pvBootstrapperApplicationProcContext;
125 - pUserExperience->fDisableUnloading = results.fDisableUnloading;
125
126 LExit:
127 return hr;
@@ -133,10 +132,18 @@ LExit:
132
133 *******************************************************************/
134 extern "C" HRESULT UserExperienceUnload(
136 - __in BURN_USER_EXPERIENCE* pUserExperience
135 + __in BURN_USER_EXPERIENCE* pUserExperience,
136 + __in BOOL fReload
137 )
138 {
139 HRESULT hr = S_OK;
140 + BOOTSTRAPPER_DESTROY_ARGS args = { };
141 + BOOTSTRAPPER_DESTROY_RESULTS results = { };
142 +
143 + args.cbSize = sizeof(BOOTSTRAPPER_DESTROY_ARGS);
144 + args.fReload = fReload;
145 +
146 + results.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS);
147
148 if (pUserExperience->hUXModule)
149 {
@@ -144,11 +151,11 @@ extern "C" HRESULT UserExperienceUnload(
151 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = (PFN_BOOTSTRAPPER_APPLICATION_DESTROY)::GetProcAddress(pUserExperience->hUXModule, "BootstrapperApplicationDestroy");
152 if (pfnDestroy)
153 {
147 - pfnDestroy();
154 + pfnDestroy(&args, &results);
155 }
156
157 // Free BA DLL if it supports it.
151 - if (!pUserExperience->fDisableUnloading && !::FreeLibrary(pUserExperience->hUXModule))
158 + if (!results.fDisableUnloading && !::FreeLibrary(pUserExperience->hUXModule))
159 {
160 hr = HRESULT_FROM_WIN32(::GetLastError());
161 TraceError(hr, "Failed to unload BA DLL.");
src/burn/engine/userexperience.h
+2 -2
@@ -22,7 +22,6 @@ typedef struct _BURN_USER_EXPERIENCE
22 HMODULE hUXModule;
23 PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBAProc;
24 LPVOID pvBAProcContext;
25 - BOOL fDisableUnloading;
25 LPWSTR sczTempDirectory;
26
27 CRITICAL_SECTION csEngineActive; // Changing the engine active state in the user experience must be
@@ -61,7 +60,8 @@ HRESULT UserExperienceLoad(
60 __in BOOTSTRAPPER_COMMAND* pCommand
61 );
62 HRESULT UserExperienceUnload(
64 - __in BURN_USER_EXPERIENCE* pUserExperience
63 + __in BURN_USER_EXPERIENCE* pUserExperience,
64 + __in BOOL fReload
65 );
66 HRESULT UserExperienceEnsureWorkingFolder(
67 __in BURN_CACHE* pCache,
src/ext/Bal/Samples/bafunctions/bafunctions.cpp
+2
@@ -40,6 +40,8 @@ LExit:
40 }
41
42 extern "C" void WINAPI BAFunctionsDestroy(
43 + __in const BA_FUNCTIONS_DESTROY_ARGS* /*pArgs*/,
44 + __inout BA_FUNCTIONS_DESTROY_RESULTS* /*pResults*/
45 )
46 {
47 BalUninitialize();
src/ext/Bal/dnchost/dnchost.cpp
+30 -21
@@ -21,9 +21,8 @@ static HRESULT LoadManagedBootstrapperApplicationFactory(
21 __in DNCSTATE* pState
22 );
23 static HRESULT CreatePrerequisiteBA(
24 - __in HRESULT hrHostInitialization,
24 + __in DNCSTATE* pState,
25 __in IBootstrapperEngine* pEngine,
26 - __in LPCWSTR wzAppBase,
26 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
27 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
28 );
@@ -58,13 +57,8 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
57 )
58 {
59 HRESULT hr = S_OK;
61 - HRESULT hrHostInitialization = S_OK;
60 IBootstrapperEngine* pEngine = NULL;
61
64 - // coreclr.dll doesn't support unloading, so the rest of the .NET Core hosting stack doesn't support it either.
65 - // This means we also can't unload.
66 - pResults->fDisableUnloading = TRUE;
67 -
62 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
63 ExitOnFailure(hr, "Failed to initialize Bal.");
64
@@ -106,16 +100,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
100 {
101 if (DNCHOSTTYPE_SCD == vstate.type)
102 {
109 - hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE;
103 + vstate.prereqData.hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE;
104 BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error.");
105 }
106 + else if (vstate.prereqData.fCompleted)
107 + {
108 + hr = E_PREREQBA_INFINITE_LOOP;
109 + BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
110 + vstate.prereqData.hrHostInitialization = hr;
111 + }
112 else
113 {
114 - hrHostInitialization = S_OK;
114 + vstate.prereqData.hrHostInitialization = S_OK;
115 }
116 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr);
117
118 - hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults);
118 + hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
119 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
120 }
121
@@ -125,14 +125,21 @@ LExit:
125 return hr;
126 }
127
128 -extern "C" void WINAPI BootstrapperApplicationDestroy()
128 +extern "C" void WINAPI BootstrapperApplicationDestroy(
129 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
130 + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
131 + )
132 {
133 + BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
134 +
135 + childResults.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS);
136 +
137 if (vstate.hMbapreqModule)
138 {
132 - PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy"));
139 + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy"));
140 if (pfnDestroy)
141 {
135 - (*pfnDestroy)();
142 + (*pfnDestroy)(pArgs, &childResults);
143 }
144
145 ::FreeLibrary(vstate.hMbapreqModule);
@@ -140,6 +147,9 @@ extern "C" void WINAPI BootstrapperApplicationDestroy()
147 }
148
149 BalUninitialize();
150 +
151 + // Need to keep track of state between reloads.
152 + pResults->fDisableUnloading = TRUE;
153 }
154
155 static HRESULT LoadModulePaths(
@@ -262,9 +272,8 @@ static HRESULT LoadManagedBootstrapperApplicationFactory(
272 }
273
274 static HRESULT CreatePrerequisiteBA(
265 - __in HRESULT hrHostInitialization,
275 + __in DNCSTATE* pState,
276 __in IBootstrapperEngine* pEngine,
267 - __in LPCWSTR wzAppBase,
277 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
278 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
279 )
@@ -273,19 +282,19 @@ static HRESULT CreatePrerequisiteBA(
282 LPWSTR sczDncpreqPath = NULL;
283 HMODULE hModule = NULL;
284
276 - hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath);
285 + hr = PathConcat(pState->sczAppBase, L"dncpreq.dll", &sczDncpreqPath);
286 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
287
279 - hModule = ::LoadLibraryW(sczDncpreqPath);
288 + hModule = ::LoadLibraryExW(sczDncpreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
289 BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
290
282 - PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "DncPrereqBootstrapperApplicationCreate"));
283 - BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get DncPrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath);
291 + PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
292 + BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath);
293
285 - hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults);
294 + hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
295 BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
296
288 - vstate.hMbapreqModule = hModule;
297 + pState->hMbapreqModule = hModule;
298 hModule = NULL;
299
300 LExit:
src/ext/Bal/dnchost/dnchost.h
+1 -7
@@ -9,13 +9,6 @@ enum DNCHOSTTYPE
9 DNCHOSTTYPE_SCD,
10 };
11
12 -extern "C" typedef HRESULT(WINAPI* PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE)(
13 - __in HRESULT hrHostInitialization,
14 - __in IBootstrapperEngine* pEngine,
15 - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
16 - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
17 - );
18 -
12 struct DNCSTATE
13 {
14 BOOL fInitialized;
@@ -31,4 +24,5 @@ struct DNCSTATE
24 HOSTFXR_STATE hostfxrState;
25 IBootstrapperApplicationFactory* pAppFactory;
26 HMODULE hMbapreqModule;
27 + PREQBA_DATA prereqData;
28 };
src/ext/Bal/dnchost/dnchost.vcxproj
+1 -1
@@ -50,7 +50,7 @@
50 <NetHostPlatform>$(Platform)</NetHostPlatform>
51 <NetHostPlatform Condition=" '$(NetHostPlatform)'=='Win32' ">x86</NetHostPlatform>
52 <NetHostPath>..\..\..\..\packages\runtime.win-$(NetHostPlatform).Microsoft.NETCore.DotNetAppHost.6.0.4\runtimes\win-$(NetHostPlatform)\native\</NetHostPath>
53 - <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj;$(NetHostPath)</ProjectAdditionalIncludeDirectories>
53 + <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj;$(NetHostPath);..\wixstdba\inc</ProjectAdditionalIncludeDirectories>
54 <ProjectAdditionalLinkLibraries>shlwapi.lib;$(NetHostPath)libnethost.lib</ProjectAdditionalLinkLibraries>
55 </PropertyGroup>
56
src/ext/Bal/dnchost/precomp.h
+2
@@ -25,6 +25,8 @@
25 #include <hostfxr.h>
26 #include <coreclr_delegates.h>
27
28 +#include <preqba.h>
29 +
30 #include "coreclrhost.h"
31 #include "dncutil.h"
32 #include "dnchost.h"
src/ext/Bal/mbahost/mbahost.cpp
+146 -143
@@ -1,7 +1,6 @@
1 // 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.
2
3 #include "precomp.h"
4 -#include <WixToolset.Mba.Host.h> // includes the generated assembly name macros.
4
5 static const DWORD NET452_RELEASE = 379893;
6
@@ -14,26 +13,16 @@ extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)(
13 __out LPVOID *ppv
14 );
15
17 -extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)(
18 - __in HRESULT hrHostInitialization,
19 - __in IBootstrapperEngine* pEngine,
20 - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
21 - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
22 - );
23 -
24 -static HINSTANCE vhInstance = NULL;
25 -static ICorRuntimeHost *vpCLRHost = NULL;
26 -static _AppDomain *vpAppDomain = NULL;
27 -static HMODULE vhMbapreqModule = NULL;
16 +static MBASTATE vstate = { };
17
18
19 // internal function declarations
20
21 static HRESULT GetAppDomain(
33 - __out _AppDomain** ppAppDomain
22 + __in MBASTATE* pState
23 );
35 -static HRESULT GetAppBase(
36 - __out LPWSTR* psczAppBase
24 +static HRESULT LoadModulePaths(
25 + __in MBASTATE* pState
26 );
27 static HRESULT CheckSupportedFrameworks(
28 __in LPCWSTR wzConfigPath
@@ -43,9 +32,8 @@ static HRESULT UpdateSupportedRuntime(
32 __in IXMLDOMNode* pixnSupportedFramework,
33 __out BOOL* pfUpdatedManifest
34 );
46 -static HRESULT GetCLRHost(
47 - __in LPCWSTR wzConfigPath,
48 - __out ICorRuntimeHost** ppCLRHost
35 +static HRESULT LoadRuntime(
36 + __in MBASTATE* pState
37 );
38 static HRESULT CreateManagedBootstrapperApplication(
39 __in _AppDomain* pAppDomain,
@@ -57,7 +45,7 @@ static HRESULT CreateManagedBootstrapperApplicationFactory(
45 __out IBootstrapperApplicationFactory** ppAppFactory
46 );
47 static HRESULT CreatePrerequisiteBA(
60 - __in HRESULT hrHostInitialization,
48 + __in MBASTATE* pState,
49 __in IBootstrapperEngine* pEngine,
50 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
51 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -78,11 +66,11 @@ extern "C" BOOL WINAPI DllMain(
66 {
67 case DLL_PROCESS_ATTACH:
68 ::DisableThreadLibraryCalls(hInstance);
81 - vhInstance = hInstance;
69 + vstate.hInstance = hInstance;
70 break;
71
72 case DLL_PROCESS_DETACH:
85 - vhInstance = NULL;
73 + vstate.hInstance = NULL;
74 break;
75 }
76
@@ -96,18 +84,39 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
84 )
85 {
86 HRESULT hr = S_OK;
99 - HRESULT hrHostInitialization = S_OK;
87 IBootstrapperEngine* pEngine = NULL;
88
89 + if (vstate.fStoppedRuntime)
90 + {
91 + BalExitWithRootFailure(hr, E_INVALIDSTATE, "Reloaded mbahost after stopping .NET runtime.");
92 + }
93 +
94 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
95 ExitOnFailure(hr, "Failed to initialize Bal.");
96
105 - hr = GetAppDomain(&vpAppDomain);
106 - if (SUCCEEDED(hr))
97 + if (!vstate.fInitialized)
98 + {
99 + hr = LoadModulePaths(&vstate);
100 + BalExitOnFailure(hr, "Failed to load the module paths.");
101 +
102 + vstate.fInitialized = TRUE;
103 + }
104 +
105 + if (!vstate.fInitializedRuntime)
106 + {
107 + hr = LoadRuntime(&vstate);
108 +
109 + vstate.fInitializedRuntime = SUCCEEDED(hr);
110 + }
111 +
112 + if (vstate.fInitializedRuntime)
113 {
114 + hr = GetAppDomain(&vstate);
115 + BalExitOnFailure(hr, "Failed to create the AppDomain for the managed bootstrapper application.");
116 +
117 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application.");
118
110 - hr = CreateManagedBootstrapperApplication(vpAppDomain, pArgs, pResults);
119 + hr = CreateManagedBootstrapperApplication(vstate.pAppDomain, pArgs, pResults);
120 BalExitOnFailure(hr, "Failed to create the managed bootstrapper application.");
121 }
122 else // fallback to the prerequisite BA.
@@ -115,16 +124,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
124 if (E_MBAHOST_NET452_ON_WIN7RTM == hr)
125 {
126 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.");
118 - hrHostInitialization = hr;
127 + vstate.prereqData.hrHostInitialization = hr;
128 + }
129 + else if (vstate.prereqData.fCompleted)
130 + {
131 + hr = E_PREREQBA_INFINITE_LOOP;
132 + BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
133 + vstate.prereqData.hrHostInitialization = hr;
134 }
135 else
136 {
122 - hrHostInitialization = S_OK;
137 + vstate.prereqData.hrHostInitialization = S_OK;
138 }
139
140 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr);
141
127 - hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, pArgs, pResults);
142 + hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
143 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
144 }
145
@@ -134,73 +149,65 @@ LExit:
149 return hr;
150 }
151
137 -extern "C" void WINAPI BootstrapperApplicationDestroy()
152 +extern "C" void WINAPI BootstrapperApplicationDestroy(
153 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
154 + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
155 + )
156 {
139 - if (vpAppDomain)
157 + BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
158 +
159 + if (vstate.pAppDomain)
160 {
141 - HRESULT hr = vpCLRHost->UnloadDomain(vpAppDomain);
161 + HRESULT hr = vstate.pCLRHost->UnloadDomain(vstate.pAppDomain);
162 if (FAILED(hr))
163 {
164 BalLogError(hr, "Failed to unload app domain.");
165 }
166
147 - vpAppDomain->Release();
167 + vstate.pAppDomain->Release();
168 + vstate.pAppDomain = NULL;
169 }
170
150 - if (vpCLRHost)
171 + // pCLRHost can only be stopped once per process.
172 + if (vstate.pCLRHost && !pArgs->fReload)
173 {
152 - vpCLRHost->Stop();
153 - vpCLRHost->Release();
174 + vstate.pCLRHost->Stop();
175 + vstate.pCLRHost->Release();
176 + vstate.pCLRHost = NULL;
177 + vstate.fStoppedRuntime = TRUE;
178 }
179
156 - if (vhMbapreqModule)
180 + if (vstate.hMbapreqModule)
181 {
158 - PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vhMbapreqModule, "MbaPrereqBootstrapperApplicationDestroy"));
182 + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy"));
183 if (pfnDestroy)
184 {
161 - (*pfnDestroy)();
185 + (*pfnDestroy)(pArgs, &childResults);
186 }
187
164 - ::FreeLibrary(vhMbapreqModule);
165 - vhMbapreqModule = NULL;
188 + ::FreeLibrary(vstate.hMbapreqModule);
189 + vstate.hMbapreqModule = NULL;
190 }
191
192 BalUninitialize();
193 +
194 + // Need to keep track of state between reloads.
195 + pResults->fDisableUnloading = TRUE;
196 }
197
198 // Gets the custom AppDomain for loading managed BA.
199 static HRESULT GetAppDomain(
173 - __out _AppDomain **ppAppDomain
200 + __in MBASTATE* pState
201 )
202 {
203 HRESULT hr = S_OK;
177 - ICorRuntimeHost *pCLRHost = NULL;
204 IUnknown *pUnk = NULL;
179 - LPWSTR sczAppBase = NULL;
180 - LPWSTR sczConfigPath = NULL;
181 - IAppDomainSetup *pAppDomainSetup;
205 + IAppDomainSetup* pAppDomainSetup = NULL;
206 BSTR bstrAppBase = NULL;
207 BSTR bstrConfigPath = NULL;
208
185 - hr = GetAppBase(&sczAppBase);
186 - ExitOnFailure(hr, "Failed to get the host base path.");
187 -
188 - hr = PathConcat(sczAppBase, MBA_CONFIG_FILE_NAME, &sczConfigPath);
189 - ExitOnFailure(hr, "Failed to get the full path to the application configuration file.");
190 -
191 - // Check that the supported framework is installed.
192 - hr = CheckSupportedFrameworks(sczConfigPath);
193 - ExitOnFailure(hr, "Failed to find supported framework.");
194 -
195 - // Load the CLR.
196 - hr = GetCLRHost(sczConfigPath, &pCLRHost);
197 - ExitOnFailure(hr, "Failed to create the CLR host.");
198 -
199 - hr = pCLRHost->Start();
200 - ExitOnRootFailure(hr, "Failed to start the CLR host.");
201 -
209 // Create the setup information for a new AppDomain to set the app base and config.
203 - hr = pCLRHost->CreateDomainSetup(&pUnk);
210 + hr = pState->pCLRHost->CreateDomainSetup(&pUnk);
211 ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object.");
212
213 hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup));
@@ -208,49 +215,49 @@ static HRESULT GetAppDomain(
215 ReleaseNullObject(pUnk);
216
217 // Set properties on the AppDomainSetup object.
211 - bstrAppBase = ::SysAllocString(sczAppBase);
218 + bstrAppBase = ::SysAllocString(pState->sczAppBase);
219 ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup.");
220
221 hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase);
222 ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup.");
223
217 - bstrConfigPath = ::SysAllocString(sczConfigPath);
224 + bstrConfigPath = ::SysAllocString(pState->sczConfigPath);
225 ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup.");
226
227 hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath);
228 ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup.");
229
230 // Create the AppDomain to load the factory type.
224 - hr = pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk);
231 + hr = pState->pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk);
232 ExitOnRootFailure(hr, "Failed to create the MBA AppDomain.");
233
227 - hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(ppAppDomain));
234 + hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(&pState->pAppDomain));
235 ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface.");
236
237 LExit:
238 ReleaseBSTR(bstrConfigPath);
239 ReleaseBSTR(bstrAppBase);
233 - ReleaseStr(sczConfigPath);
234 - ReleaseStr(sczAppBase);
240 ReleaseNullObject(pUnk);
236 - ReleaseNullObject(pCLRHost);
241
242 return hr;
243 }
244
241 -static HRESULT GetAppBase(
242 - __out LPWSTR *psczAppBase
245 +static HRESULT LoadModulePaths(
246 + __in MBASTATE* pState
247 )
248 {
249 HRESULT hr = S_OK;
250 LPWSTR sczFullPath = NULL;
251
248 - hr = PathForCurrentProcess(&sczFullPath, vhInstance);
252 + hr = PathForCurrentProcess(&sczFullPath, pState->hInstance);
253 ExitOnFailure(hr, "Failed to get the full host path.");
254
251 - hr = PathGetDirectory(sczFullPath, psczAppBase);
255 + hr = PathGetDirectory(sczFullPath, &pState->sczAppBase);
256 ExitOnFailure(hr, "Failed to get the directory of the full process path.");
257
258 + hr = PathConcat(pState->sczAppBase, MBA_CONFIG_FILE_NAME, &pState->sczConfigPath);
259 + ExitOnFailure(hr, "Failed to get the full path to the application configuration file.");
260 +
261 LExit:
262 ReleaseStr(sczFullPath);
263
@@ -390,9 +397,8 @@ LExit:
397 }
398
399 // Gets the CLR host and caches it.
393 -static HRESULT GetCLRHost(
394 - __in LPCWSTR wzConfigPath,
395 - __out ICorRuntimeHost **ppCLRHost
400 +static HRESULT LoadRuntime(
401 + __in MBASTATE* pState
402 )
403 {
404 HRESULT hr = S_OK;
@@ -411,84 +417,81 @@ static HRESULT GetCLRHost(
417 // Always set the error mode because we will always restore it below.
418 uiMode = ::SetErrorMode(0);
419
414 - // Cache the CLR host to be shutdown later. This can occur on a different thread.
415 - if (!vpCLRHost)
416 - {
417 - // Disable message boxes from being displayed on error and blocking execution.
418 - ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
420 + // Check that the supported framework is installed.
421 + hr = CheckSupportedFrameworks(pState->sczConfigPath);
422 + ExitOnFailure(hr, "Failed to find supported framework.");
423
420 - hr = LoadSystemLibrary(L"mscoree.dll", &hModule);
421 - ExitOnFailure(hr, "Failed to load mscoree.dll");
424 + // Cache the CLR host to be shutdown later. This can occur on a different thread.
425 + // Disable message boxes from being displayed on error and blocking execution.
426 + ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
427
423 - pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance"));
424 -
425 - if (pfnCLRCreateInstance)
426 - {
427 - hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast<LPVOID*>(&pCLRMetaHostPolicy));
428 - if (E_NOTIMPL != hr)
429 - {
430 - ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy.");
428 + hr = LoadSystemLibrary(L"mscoree.dll", &hModule);
429 + ExitOnFailure(hr, "Failed to load mscoree.dll");
430
432 - fFallbackToCorBindToCurrentRuntime = FALSE;
433 - }
434 - }
431 + pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance"));
432
436 - if (fFallbackToCorBindToCurrentRuntime)
433 + if (pfnCLRCreateInstance)
434 + {
435 + hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast<LPVOID*>(&pCLRMetaHostPolicy));
436 + if (E_NOTIMPL != hr)
437 {
438 - pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime"));
439 - ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
438 + ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy.");
439
441 - hr = pfnCorBindToCurrentRuntime(wzConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&vpCLRHost));
442 - ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
440 + fFallbackToCorBindToCurrentRuntime = FALSE;
441 }
444 - else
445 - {
446 -
447 - hr = SHCreateStreamOnFileEx(wzConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream);
448 - ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath);
442 + }
443
450 - hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo));
451 - ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path.");
444 + if (fFallbackToCorBindToCurrentRuntime)
445 + {
446 + pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime"));
447 + ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
448
453 - // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL.
454 - if (!cchVersion)
455 - {
456 - hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion);
457 - if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
458 - {
459 - ExitOnFailure(hr, "Failed to get the length of the CLR version string.");
460 - }
461 - }
449 + hr = pfnCorBindToCurrentRuntime(pState->sczConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
450 + ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
451 + }
452 + else
453 + {
454
463 - hr = StrAlloc(&pwzVersion, cchVersion);
464 - ExitOnFailure(hr, "Failed to allocate the CLR version string.");
455 + hr = SHCreateStreamOnFileEx(pState->sczConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream);
456 + ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", pState->sczConfigPath);
457
466 - hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion);
467 - ExitOnFailure(hr, "Failed to get the CLR version string.");
458 + hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo));
459 + ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path.");
460
469 - if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion))
461 + // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL.
462 + if (!cchVersion)
463 + {
464 + hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion);
465 + if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
466 {
471 - hr = VerifyNET4RuntimeIsSupported();
472 - ExitOnFailure(hr, "Found unsupported .NET 4 Runtime.");
467 + ExitOnFailure(hr, "Failed to get the length of the CLR version string.");
468 }
469 + }
470
475 - if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags))
476 - {
477 - hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
478 - ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
479 - }
471 + hr = StrAlloc(&pwzVersion, cchVersion);
472 + ExitOnFailure(hr, "Failed to allocate the CLR version string.");
473
481 - hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&vpCLRHost));
482 - ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost.");
474 + hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion);
475 + ExitOnFailure(hr, "Failed to get the CLR version string.");
476 +
477 + if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion))
478 + {
479 + hr = VerifyNET4RuntimeIsSupported();
480 + ExitOnFailure(hr, "Found unsupported .NET 4 Runtime.");
481 + }
482
484 - // TODO: use ICLRRuntimeHost instead of ICorRuntimeHost on .NET 4 since the former is faster and the latter is deprecated
485 - //hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast<LPVOID*>(&pCLRRuntimeHost));
486 - //ExitOnRootFailure(hr, "Failed to get instance of ICLRRuntimeHost.");
483 + if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags))
484 + {
485 + hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
486 + ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
487 }
488 +
489 + hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
490 + ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost.");
491 }
492
490 - vpCLRHost->AddRef();
491 - *ppCLRHost = vpCLRHost;
493 + hr = pState->pCLRHost->Start();
494 + ExitOnRootFailure(hr, "Failed to start the CLR host.");
495
496 LExit:
497 ReleaseStr(pwzVersion);
@@ -569,7 +572,7 @@ LExit:
572 }
573
574 static HRESULT CreatePrerequisiteBA(
572 - __in HRESULT hrHostInitialization,
575 + __in MBASTATE* pState,
576 __in IBootstrapperEngine* pEngine,
577 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
578 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -579,19 +582,19 @@ static HRESULT CreatePrerequisiteBA(
582 LPWSTR sczMbapreqPath = NULL;
583 HMODULE hModule = NULL;
584
582 - hr = PathRelativeToModule(&sczMbapreqPath, L"mbapreq.dll", vhInstance);
583 - ExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
585 + hr = PathConcat(pState->sczAppBase, L"mbapreq.dll", &sczMbapreqPath);
586 + BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
587
585 - hModule = ::LoadLibraryW(sczMbapreqPath);
588 + hModule = ::LoadLibraryExW(sczMbapreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
589 ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
590
588 - PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "MbaPrereqBootstrapperApplicationCreate"));
589 - ExitOnNullWithLastError(pfnCreate, hr, "Failed to get MbaPrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath);
591 + PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
592 + ExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath);
593
591 - hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults);
594 + hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
595 ExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
596
594 - vhMbapreqModule = hModule;
597 + pState->hMbapreqModule = hModule;
598 hModule = NULL;
599
600 LExit:
src/ext/Bal/mbahost/mbahost.h new
+17
@@ -0,0 +1,17 @@
1 +#pragma once
2 +// 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.
3 +
4 +
5 +struct MBASTATE
6 +{
7 + BOOL fInitialized;
8 + BOOL fInitializedRuntime;
9 + BOOL fStoppedRuntime;
10 + HINSTANCE hInstance;
11 + LPWSTR sczAppBase;
12 + LPWSTR sczConfigPath;
13 + mscorlib::_AppDomain* pAppDomain;
14 + ICorRuntimeHost* pCLRHost;
15 + HMODULE hMbapreqModule;
16 + PREQBA_DATA prereqData;
17 +};
src/ext/Bal/mbahost/mbahost.vcxproj
+2 -1
@@ -41,7 +41,7 @@
41 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
42
43 <PropertyGroup>
44 - <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj</ProjectAdditionalIncludeDirectories>
44 + <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj;..\wixstdba\inc</ProjectAdditionalIncludeDirectories>
45 <ProjectAdditionalLinkLibraries>shlwapi.lib</ProjectAdditionalLinkLibraries>
46 </PropertyGroup>
47
@@ -52,6 +52,7 @@
52 </ClCompile>
53 </ItemGroup>
54 <ItemGroup>
55 + <ClInclude Include="mbahost.h" />
56 <ClInclude Include="precomp.h" />
57 </ItemGroup>
58 <ItemGroup>
src/ext/Bal/mbahost/precomp.h
+11 -6
@@ -16,10 +16,15 @@
16 #include <strutil.h>
17 #include <xmlutil.h>
18
19 -#include "BootstrapperEngine.h"
20 -#include "BootstrapperApplication.h"
21 -#include "IBootstrapperEngine.h"
22 -#include "IBootstrapperApplication.h"
23 -#include "IBootstrapperApplicationFactory.h"
19 +#include <BootstrapperEngine.h>
20 +#include <BootstrapperApplication.h>
21 +#include <IBootstrapperEngine.h>
22 +#include <IBootstrapperApplication.h>
23 +#include <IBootstrapperApplicationFactory.h>
24
25 -#include "balutil.h"
25 +#include <balutil.h>
26 +
27 +#include <preqba.h>
28 +#include <WixToolset.Mba.Host.h> // includes the generated assembly name macros.
29 +
30 +#include "mbahost.h"
src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp
+2 -2
@@ -31,7 +31,7 @@ HRESULT RunReloadEngine(
31 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER);
32 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
33
34 - pTestEngine->UnloadBA();
34 + pTestEngine->UnloadBA(TRUE);
35
36 hr = pTestEngine->LoadBA(wzBAFilePath);
37 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to load BA.");
@@ -48,7 +48,7 @@ HRESULT RunReloadEngine(
48 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART);
49 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
50
51 - pTestEngine->UnloadBA();
51 + pTestEngine->UnloadBA(FALSE);
52
53 LExit:
54 return hr;
src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp
+1 -1
@@ -31,7 +31,7 @@ HRESULT RunShutdownEngine(
31 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER);
32 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
33
34 - pTestEngine->UnloadBA();
34 + pTestEngine->UnloadBA(FALSE);
35
36 LExit:
37 return hr;
src/ext/Bal/test/examples/TestEngine/TestEngine.cpp
+12 -4
@@ -147,10 +147,18 @@ HRESULT TestEngine::SimulateQuit(
147 return BAEngineQuit(&args, &results);
148 }
149
150 -void TestEngine::UnloadBA()
150 +void TestEngine::UnloadBA(
151 + __in BOOL fReload
152 + )
153 {
154 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = NULL;
153 - BOOL fDisableUnloading = m_pCreateResults && m_pCreateResults->fDisableUnloading;
155 + BOOTSTRAPPER_DESTROY_ARGS args = { };
156 + BOOTSTRAPPER_DESTROY_RESULTS results = { };
157 +
158 + args.cbSize = sizeof(args);
159 + args.fReload = fReload;
160 +
161 + results.cbSize = sizeof(results);
162
163 ReleaseNullMem(m_pCreateResults);
164
@@ -158,12 +166,12 @@ void TestEngine::UnloadBA()
166
167 if (pfnDestroy)
168 {
161 - pfnDestroy();
169 + pfnDestroy(&args, &results);
170 }
171
172 if (m_hBAModule)
173 {
166 - if (!fDisableUnloading)
174 + if (!results.fDisableUnloading)
175 {
176 ::FreeLibrary(m_hBAModule);
177 }
src/ext/Bal/test/examples/TestEngine/TestEngine.h
+4 -2
@@ -44,7 +44,9 @@ public:
44 __in DWORD dwExitCode
45 );
46
47 - void UnloadBA();
47 + void UnloadBA(
48 + __in BOOL fReload
49 + );
50
51 private:
52 HRESULT BAEngineLog(
@@ -77,4 +79,4 @@ private:
79 HMODULE m_hBAModule;
80 BOOTSTRAPPER_CREATE_RESULTS* m_pCreateResults;
81 DWORD m_dwThreadId;
80 -};
\ No newline at end of file
82 +};
src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp
+1 -1
@@ -28,7 +28,7 @@ HRESULT RunWaitForQuitEngine(
28 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER);
29 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
30
31 - pTestEngine->UnloadBA();
31 + pTestEngine->UnloadBA(FALSE);
32
33 LExit:
34 return hr;
src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl
+1
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">重新啟動(&amp;R)</String>
30 <String Id="FailureCloseButton">關閉(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Restartovat</String>
33 <String Id="FailureCloseButton">&amp;Zavřít</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Genstart</String>
33 <String Id="FailureCloseButton">&amp;Luk</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl
+1
@@ -35,5 +35,6 @@
35 <String Id="FailureRestartButton">&amp;Neu starten</String>
36 <String Id="FailureCloseButton">&amp;Schließen</String>
37 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
38 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
39 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
40 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl
+1
@@ -34,5 +34,6 @@
34 <String Id="FailureRestartButton">&amp;Επανεκκίνηση</String>
35 <String Id="FailureCloseButton">&amp;Κλείσιμο</String>
36 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
37 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
38 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
39 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Käynnistä uudelleen</String>
33 <String Id="FailureCloseButton">&amp;Sulje</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Redémarrer</String>
33 <String Id="FailureCloseButton">&amp;Fermer</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Újraindítás</String>
33 <String Id="FailureCloseButton">&amp;Bezárás</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl
+1
@@ -33,5 +33,6 @@
33 <String Id="FailureRestartButton">&amp;Riavvia</String>
34 <String Id="FailureCloseButton">&amp;Chiudi</String>
35 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
36 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
37 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
38 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl
+1
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">再起動(&amp;R)</String>
30 <String Id="FailureCloseButton">閉じる(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl
+1
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">다시 시작(&amp;R)</String>
30 <String Id="FailureCloseButton">닫기(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Opnieuw opstarten</String>
33 <String Id="FailureCloseButton">&amp;Sluiten</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Start på nytt</String>
33 <String Id="FailureCloseButton">&amp;Lukk</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Uruchom ponownie</String>
33 <String Id="FailureCloseButton">&amp;Zamknij</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl
+1
@@ -31,5 +31,6 @@
31 <String Id="FailureRestartButton">&amp;Reiniciar</String>
32 <String Id="FailureCloseButton">&amp;Fechar</String>
33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
34 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl
+1
@@ -31,5 +31,6 @@
31 <String Id="FailureRestartButton">&amp;Перезагрузить</String>
32 <String Id="FailureCloseButton">&amp;Закрыть</String>
33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
34 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Reštartovať</String>
33 <String Id="FailureCloseButton">&amp;Zavrieť</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Starta om</String>
33 <String Id="FailureCloseButton">&amp;Stäng</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Yeniden Başlat</String>
33 <String Id="FailureCloseButton">&amp;Kapat</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl
+1
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Ponovni zagon</String>
33 <String Id="FailureCloseButton">&amp;Zapri</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37 </WixLocalization>
src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl
+1
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">重启(&amp;R)</String>
30 <String Id="FailureCloseButton">关闭(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34 </WixLocalization>
src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl
+1
@@ -31,5 +31,6 @@
31 <String Id="FailureRestartButton">&amp;Reiniciar</String>
32 <String Id="FailureCloseButton">&amp;Fechar</String>
33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
34 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36 </WixLocalization>
src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl
+1
@@ -33,5 +33,6 @@
33 <String Id="FailureRestartButton">&amp;Reiniciar</String>
34 <String Id="FailureCloseButton">&amp;Cerrar</String>
35 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
36 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
37 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
38 </WixLocalization>
src/ext/Bal/wixstdba/Resources/dncpreq.wxl
+1
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">&amp;Restart</String>
30 <String Id="FailureCloseButton">&amp;Close</String>
31 <String Id="SCDRUNTIMEFAILUREErrorMessage">[WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment.</String>
32 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Core runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34 </WixLocalization>
src/ext/Bal/wixstdba/Resources/mbapreq.wxl
+1
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">&amp;Restart</String>
30 <String Id="FailureCloseButton">&amp;Close</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 + <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34 </WixLocalization>
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+102 -218
@@ -123,14 +123,6 @@ enum WIXSTDBA_CONTROL
123 LAST_WIXSTDBA_CONTROL,
124 };
125
126 -typedef struct _WIXSTDBA_PACKAGE_INFO
127 -{
128 - LPWSTR sczPackageId;
129 - BOOL fWasAlreadyInstalled;
130 - BOOL fPlannedToBeInstalled;
131 - BOOL fSuccessfullyInstalled;
132 -} WIXSTDBA_PACKAGE_INFO;
133 -
126
127 static HRESULT DAPI EvaluateVariableConditionCallback(
128 __in_z LPCWSTR wzCondition,
@@ -229,10 +221,7 @@ public: // IBootstrapperApplication
221 {
222 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded.");
223 *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER;
232 - }
233 - else if (m_fPrereqAlreadyInstalled)
234 - {
235 - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
224 + m_pPrereqData->fCompleted = TRUE;
225 }
226 else if (m_fPrereq)
227 {
@@ -311,38 +300,14 @@ public: // IBootstrapperApplication
300
301 if (!fMissingFromCache)
302 {
314 - if (SUCCEEDED(BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine, &pPackage)))
315 - {
316 - InitializePackageInfoForPackage(pPackage);
317 - }
303 + BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine, &pPackage);
304 + // Best effort
305 }
306
307 return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel);
308 }
309
310
324 - virtual STDMETHODIMP OnDetectPackageComplete(
325 - __in LPCWSTR wzPackageId,
326 - __in HRESULT /*hrStatus*/,
327 - __in BOOTSTRAPPER_PACKAGE_STATE state,
328 - __in BOOL /*fCached*/
329 - )
330 - {
331 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
332 - BAL_INFO_PACKAGE* pPackage = NULL;
333 -
334 - if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state &&
335 - SUCCEEDED(GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage)) &&
336 - pPackageInfo)
337 - {
338 - // If the package is already installed, remember that.
339 - pPackageInfo->fWasAlreadyInstalled = TRUE;
340 - }
341 -
342 - return S_OK;
343 - }
344 -
345 -
311 virtual STDMETHODIMP OnDetectComplete(
312 __in HRESULT hrStatus,
313 __in BOOL /*fEligibleForCleanup*/
@@ -366,29 +331,10 @@ public: // IBootstrapperApplication
331 if (fEvaluateConditions)
332 {
333 hrStatus = EvaluateConditions();
369 - }
334
371 - if (FAILED(hrStatus))
372 - {
373 - fSkipToPlan = FALSE;
374 - }
375 - else
376 - {
377 - if (m_fPrereq)
335 + if (FAILED(hrStatus))
336 {
379 - m_fPrereqAlreadyInstalled = TRUE;
380 -
381 - // 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.
382 - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
383 - {
384 - BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i];
385 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
386 - if (pPackage->fPrereqPackage && pPackageInfo && !pPackageInfo->fWasAlreadyInstalled)
387 - {
388 - m_fPrereqAlreadyInstalled = FALSE;
389 - break;
390 - }
391 - }
337 + fSkipToPlan = FALSE;
338 }
339 }
340
@@ -403,20 +349,20 @@ public: // IBootstrapperApplication
349 }
350
351
406 - virtual STDMETHODIMP OnPlanRelatedBundle(
352 + virtual STDMETHODIMP OnPlanRelatedBundleType(
353 __in_z LPCWSTR wzBundleId,
408 - __in BOOTSTRAPPER_REQUEST_STATE recommendedState,
409 - __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState,
354 + __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE recommendedType,
355 + __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType,
356 __inout BOOL* pfCancel
357 )
358 {
359 // If we're only installing prerequisites, do not touch related bundles.
360 if (m_fPrereq)
361 {
416 - *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE;
362 + *pRequestedType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
363 }
364
419 - return CBalBaseBootstrapperApplication::OnPlanRelatedBundle(wzBundleId, recommendedState, pRequestedState, pfCancel);
365 + return CBalBaseBootstrapperApplication::OnPlanRelatedBundleType(wzBundleId, recommendedType, pRequestedType, pfCancel);
366 }
367
368
@@ -434,7 +380,6 @@ public: // IBootstrapperApplication
380 )
381 {
382 HRESULT hr = S_OK;
437 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
383 BAL_INFO_PACKAGE* pPackage = NULL;
384
385 // If we're planning to install prerequisites, install them. The prerequisites need to be installed
@@ -443,10 +388,11 @@ public: // IBootstrapperApplication
388 {
389 // Only install prerequisite packages, and check the InstallCondition on them.
390 BOOL fInstall = FALSE;
446 - hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage);
447 - if (SUCCEEDED(hr) && pPackage->fPrereqPackage && pPackageInfo)
391 +
392 + hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
393 + if (SUCCEEDED(hr) && pPackage->fPrereqPackage)
394 {
449 - pPackageInfo->fPlannedToBeInstalled = fInstall = BOOTSTRAPPER_PACKAGE_CONDITION_FALSE != installCondition;
395 + fInstall = BOOTSTRAPPER_PACKAGE_CONDITION_FALSE != installCondition;
396 }
397
398 if (fInstall)
@@ -503,7 +449,6 @@ public: // IBootstrapperApplication
449 )
450 {
451 HRESULT hr = S_OK;
506 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
452 BAL_INFO_PACKAGE* pPackage = NULL;
453 BOOL fShowInternalUI = FALSE;
454 INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE;
@@ -521,7 +466,7 @@ public: // IBootstrapperApplication
466
467 if (INSTALLUILEVEL_NOCHANGE != uiLevel)
468 {
524 - hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage);
469 + hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
470 if (SUCCEEDED(hr) && pPackage->sczDisplayInternalUICondition)
471 {
472 hr = BalEvaluateCondition(pPackage->sczDisplayInternalUICondition, &fShowInternalUI);
@@ -545,23 +490,6 @@ public: // IBootstrapperApplication
490 {
491 HRESULT hr = S_OK;
492
548 - if (m_fPrereq)
549 - {
550 - m_fPrereqAlreadyInstalled = TRUE;
551 -
552 - // Now that we've planned the packages, we can focus on the prerequisite packages that are supposed to be installed.
553 - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
554 - {
555 - BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i];
556 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
557 - if (pPackage->fPrereqPackage && pPackageInfo && !pPackageInfo->fWasAlreadyInstalled && pPackageInfo->fPlannedToBeInstalled)
558 - {
559 - m_fPrereqAlreadyInstalled = FALSE;
560 - break;
561 - }
562 - }
563 - }
564 -
493 SetState(WIXSTDBA_STATE_PLANNED, hrStatus);
494
495 if (SUCCEEDED(hrStatus))
@@ -1033,13 +961,10 @@ public: // IBootstrapperApplication
961
962 hr = __super::OnExecutePackageComplete(wzPackageId, hrStatus, restart, recommendation, pAction);
963
1036 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
1037 - BAL_INFO_PACKAGE* pPackage;
1038 - HRESULT hrPrereq = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage);
1039 - if (SUCCEEDED(hrPrereq) && pPackageInfo)
964 + BAL_INFO_PACKAGE* pPackage = NULL;
965 + HRESULT hrPrereq = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
966 + if (SUCCEEDED(hrPrereq))
967 {
1041 - pPackageInfo->fSuccessfullyInstalled = SUCCEEDED(hrStatus);
1042 -
968 // If the prerequisite required a restart (any restart) then do an immediate
969 // restart to ensure that the bundle will get launched again post reboot.
970 if (m_fPrereq && pPackage->fPrereqPackage && BOOTSTRAPPER_APPLY_RESTART_NONE != restart)
@@ -1157,28 +1082,7 @@ public: // IBootstrapperApplication
1082
1083 if (m_fPrereq)
1084 {
1160 - m_fPrereqInstalled = TRUE;
1161 - BOOL fInstalledAPackage = FALSE;
1162 -
1163 - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
1164 - {
1165 - BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i];
1166 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
1167 - if (pPackage->fPrereqPackage && pPackageInfo && pPackageInfo->fPlannedToBeInstalled && !pPackageInfo->fWasAlreadyInstalled)
1168 - {
1169 - if (pPackageInfo->fSuccessfullyInstalled)
1170 - {
1171 - fInstalledAPackage = TRUE;
1172 - }
1173 - else
1174 - {
1175 - m_fPrereqInstalled = FALSE;
1176 - break;
1177 - }
1178 - }
1179 - }
1180 -
1181 - m_fPrereqInstalled = m_fPrereqInstalled && fInstalledAPackage;
1085 + m_fPrereqInstalled = SUCCEEDED(hrStatus);
1086 }
1087
1088 // If we are showing UI, wait a beat before moving to the final screen.
@@ -1223,10 +1127,10 @@ public: // IBootstrapperApplication
1127 {
1128 BAL_INFO_PACKAGE* pPackage = NULL;
1129
1226 - if (SUCCEEDED(hrStatus) && wzNewPackageId &&
1227 - SUCCEEDED(BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage)))
1130 + if (SUCCEEDED(hrStatus) && wzNewPackageId)
1131 {
1229 - InitializePackageInfoForPackage(pPackage);
1132 + BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage);
1133 + // Best effort
1134 }
1135
1136 return S_OK;
@@ -2201,6 +2105,36 @@ public: //CBalBaseBootstrapperApplication
2105 return hr;
2106 }
2107
2108 + void Uninitialize(
2109 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
2110 + __in BOOTSTRAPPER_DESTROY_RESULTS* /*pResults*/
2111 + )
2112 + {
2113 + if (m_hBAFModule)
2114 + {
2115 + BA_FUNCTIONS_DESTROY_ARGS args = { };
2116 + BA_FUNCTIONS_DESTROY_RESULTS results = { };
2117 +
2118 + args.cbSize = sizeof(BA_FUNCTIONS_DESTROY_ARGS);
2119 + args.fReload = pArgs->fReload;
2120 +
2121 + results.cbSize = sizeof(BA_FUNCTIONS_DESTROY_RESULTS);
2122 +
2123 + PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast<PFN_BA_FUNCTIONS_DESTROY>(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy"));
2124 + if (pfnBAFunctionsDestroy)
2125 + {
2126 + pfnBAFunctionsDestroy(&args, &results);
2127 + }
2128 +
2129 + if (!results.fDisableUnloading)
2130 + {
2131 + ::FreeLibrary(m_hBAFModule);
2132 + m_hBAFModule = NULL;
2133 + }
2134 + }
2135 + }
2136 +
2137 +
2138 private:
2139 //
2140 // UiThreadProc - entrypoint for UI thread.
@@ -2214,6 +2148,7 @@ private:
2148 BOOL fComInitialized = FALSE;
2149 BOOL fRet = FALSE;
2150 MSG msg = { };
2151 + DWORD dwQuit = 0;
2152
2153 // Initialize COM and theme.
2154 hr = ::CoInitialize(NULL);
@@ -2274,8 +2209,6 @@ private:
2209 pThis->DestroyMainWindow();
2210 pThis->UninitializeTaskbarButton();
2211
2277 - // initiate engine shutdown
2278 - DWORD dwQuit = HRESULT_CODE(hr);
2212 if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult)
2213 {
2214 dwQuit = ERROR_SUCCESS_REBOOT_INITIATED;
@@ -2284,6 +2217,17 @@ private:
2217 {
2218 dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED;
2219 }
2220 + else if (SEVERITY_ERROR == HRESULT_SEVERITY(hr) && FACILITY_WIN32 == HRESULT_FACILITY(hr))
2221 + {
2222 + // Convert Win32 HRESULTs back to the error code.
2223 + dwQuit = HRESULT_CODE(hr);
2224 + }
2225 + else
2226 + {
2227 + dwQuit = hr;
2228 + }
2229 +
2230 + // initiate engine shutdown
2231 pThis->m_pEngine->Quit(dwQuit);
2232
2233 ReleaseTheme(pThis->m_pTheme);
@@ -2335,9 +2279,6 @@ private:
2279 GetBundleFileVersion();
2280 // don't fail if we couldn't get the version info; best-effort only
2281
2338 - hr = InitializePackageInfo();
2339 - BalExitOnFailure(hr, "Failed to initialize wixstdba package information.");
2340 -
2282 if (m_fPrereq)
2283 {
2284 hr = InitializePrerequisiteInformation();
@@ -2521,38 +2462,6 @@ private:
2462 }
2463
2464
2524 - HRESULT InitializePackageInfo()
2525 - {
2526 - HRESULT hr = S_OK;
2527 - BAL_INFO_PACKAGE* pPackage = NULL;
2528 -
2529 - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
2530 - {
2531 - pPackage = &m_Bundle.packages.rgPackages[i];
2532 -
2533 - hr = InitializePackageInfoForPackage(pPackage);
2534 - BalExitOnFailure(hr, "Failed to initialize wixstdba package info for package: %ls.", pPackage->sczId);
2535 - }
2536 -
2537 - LExit:
2538 - return hr;
2539 - }
2540 -
2541 -
2542 - HRESULT InitializePackageInfoForPackage(
2543 - __in BAL_INFO_PACKAGE* pPackage
2544 - )
2545 - {
2546 - HRESULT hr = S_OK;
2547 -
2548 - pPackage->pvCustomData = MemAlloc(sizeof(WIXSTDBA_PACKAGE_INFO), TRUE);
2549 - BalExitOnNull(pPackage->pvCustomData, hr, E_OUTOFMEMORY, "Failed to allocate memory for wixstdba package info.");
2550 -
2551 - LExit:
2552 - return hr;
2553 - }
2554 -
2555 -
2465 HRESULT InitializePrerequisiteInformation()
2466 {
2467 HRESULT hr = S_OK;
@@ -2673,35 +2582,6 @@ private:
2582 return hr;
2583 }
2584
2676 - HRESULT GetPackageInfo(
2677 - __in_z LPCWSTR wzPackageId,
2678 - __out WIXSTDBA_PACKAGE_INFO** ppPackageInfo,
2679 - __out BAL_INFO_PACKAGE** ppPackage
2680 - )
2681 - {
2682 - HRESULT hr = E_NOTFOUND;
2683 - WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
2684 - BAL_INFO_PACKAGE* pPackage = NULL;
2685 -
2686 - Assert(wzPackageId && *wzPackageId);
2687 - Assert(ppPackage);
2688 - Assert(ppPackageInfo);
2689 -
2690 - hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
2691 - if (E_NOTFOUND != hr)
2692 - {
2693 - ExitOnFailure(hr, "Failed trying to find the requested package.");
2694 -
2695 - pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
2696 - }
2697 -
2698 - *ppPackageInfo = pPackageInfo;
2699 - *ppPackage = pPackage;
2700 -
2701 - LExit:
2702 - return hr;
2703 - }
2704 -
2585
2586 //
2587 // Get the file version of the bootstrapper and record in bootstrapper log file
@@ -3408,6 +3288,23 @@ private:
3288 }
3289 }
3290 }
3291 + else if (E_PREREQBA_INFINITE_LOOP == m_hrFinal)
3292 + {
3293 + HRESULT hr = StrAllocString(&sczUnformattedText, L"#(loc.PREREQBAINFINITELOOPErrorMessage)", 0);
3294 + if (FAILED(hr))
3295 + {
3296 + BalLogError(hr, "Failed to initialize PREREQBAINFINITELOOPErrorMessage loc identifier.");
3297 + }
3298 + else
3299 + {
3300 + hr = LocLocalizeString(m_pWixLoc, &sczUnformattedText);
3301 + if (FAILED(hr))
3302 + {
3303 + BalLogError(hr, "Failed to localize PREREQBAINFINITELOOPErrorMessage: %ls", sczUnformattedText);
3304 + ReleaseNullStr(sczUnformattedText);
3305 + }
3306 + }
3307 + }
3308 else // try to get the error message from the error code.
3309 {
3310 StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL);
@@ -3424,14 +3321,9 @@ private:
3321 StrAllocString(&sczText, sczUnformattedText, 0);
3322 }
3323 }
3427 - else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal)
3428 - {
3429 - if (sczUnformattedText)
3430 - {
3431 - BalFormatString(sczUnformattedText, &sczText);
3432 - }
3433 - }
3434 - else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal)
3324 + else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal ||
3325 + E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal ||
3326 + E_PREREQBA_INFINITE_LOOP == m_hrFinal)
3327 {
3328 if (sczUnformattedText)
3329 {
@@ -4180,8 +4072,7 @@ public:
4072 //
4073 CWixStandardBootstrapperApplication(
4074 __in HMODULE hModule,
4183 - __in BOOL fPrereq,
4184 - __in HRESULT hrHostInitialization,
4075 + __in_opt PREQBA_DATA* pPrereqData,
4076 __in IBootstrapperEngine* pEngine
4077 ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000)
4078 {
@@ -4210,7 +4101,7 @@ public:
4101 m_hWnd = NULL;
4102
4103 m_state = WIXSTDBA_STATE_INITIALIZING;
4213 - m_hrFinal = hrHostInitialization;
4104 + m_hrFinal = pPrereqData ? pPrereqData->hrHostInitialization : S_OK;
4105
4106 m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
4107 m_fRestartRequired = FALSE;
@@ -4231,9 +4122,9 @@ public:
4122 m_fShowingInternalUiThisPackage = FALSE;
4123 m_fTriedToLaunchElevated = FALSE;
4124
4234 - m_fPrereq = fPrereq;
4125 + m_pPrereqData = pPrereqData;
4126 + m_fPrereq = NULL != pPrereqData;
4127 m_fPrereqInstalled = FALSE;
4236 - m_fPrereqAlreadyInstalled = FALSE;
4128
4129 pEngine->AddRef();
4130 m_pEngine = pEngine;
@@ -4418,11 +4309,6 @@ public:
4309 AssertSz(!m_pTaskbarList, "Taskbar should have been released before destructor.");
4310 AssertSz(!m_pTheme, "Theme should have been released before destructor.");
4311
4421 - for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
4422 - {
4423 - ReleaseMem(m_Bundle.packages.rgPackages[i].pvCustomData);
4424 - }
4425 -
4312 ::DeleteCriticalSection(&m_csShowingInternalUiThisPackage);
4313 ReleaseStr(m_sczFailedMessage);
4314 ReleaseStr(m_sczConfirmCloseMessage);
@@ -4436,18 +4322,6 @@ public:
4322 ReleaseStr(m_sczBundleVersion);
4323 ReleaseStr(m_sczAfterForcedRestartPackage);
4324 ReleaseNullObject(m_pEngine);
4439 -
4440 - if (m_hBAFModule)
4441 - {
4442 - PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast<PFN_BA_FUNCTIONS_DESTROY>(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy"));
4443 - if (pfnBAFunctionsDestroy)
4444 - {
4445 - pfnBAFunctionsDestroy();
4446 - }
4447 -
4448 - ::FreeLibrary(m_hBAFModule);
4449 - m_hBAFModule = NULL;
4450 - }
4325 }
4326
4327 private:
@@ -4529,9 +4403,9 @@ private:
4403 BOOL m_fSupportCacheOnly;
4404 BOOL m_fRequestedCacheOnly;
4405
4406 + PREQBA_DATA* m_pPrereqData;
4407 BOOL m_fPrereq;
4408 BOOL m_fPrereqInstalled;
4534 - BOOL m_fPrereqAlreadyInstalled;
4409
4410 ITaskbarList3* m_pTaskbarList;
4411 UINT m_uTaskbarButtonCreatedMessage;
@@ -4551,8 +4425,7 @@ private:
4425 //
4426 HRESULT CreateBootstrapperApplication(
4427 __in HMODULE hModule,
4554 - __in BOOL fPrereq,
4555 - __in HRESULT hrHostInitialization,
4428 + __in_opt PREQBA_DATA* pPrereqData,
4429 __in IBootstrapperEngine* pEngine,
4430 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
4431 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults,
@@ -4567,7 +4440,7 @@ HRESULT CreateBootstrapperApplication(
4440 BalExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type.");
4441 }
4442
4570 - pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine);
4443 + pApplication = new CWixStandardBootstrapperApplication(hModule, pPrereqData, pEngine);
4444 BalExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object.");
4445
4446 hr = pApplication->Initialize(pArgs);
@@ -4584,6 +4457,17 @@ LExit:
4457 }
4458
4459
4460 +void DestroyBootstrapperApplication(
4461 + __in IBootstrapperApplication* pApplication,
4462 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
4463 + __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
4464 + )
4465 +{
4466 + CWixStandardBootstrapperApplication* pBA = (CWixStandardBootstrapperApplication*)pApplication;
4467 + pBA->Uninitialize(pArgs, pResults);
4468 +}
4469 +
4470 +
4471 static HRESULT DAPI EvaluateVariableConditionCallback(
4472 __in_z LPCWSTR wzCondition,
4473 __out BOOL* pf,
src/ext/Bal/wixstdba/inc/preqba.h new
+16
@@ -0,0 +1,16 @@
1 +#pragma once
2 +// 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.
3 +
4 +
5 +struct PREQBA_DATA
6 +{
7 + HRESULT hrHostInitialization;
8 + BOOL fCompleted;
9 +};
10 +
11 +extern "C" typedef HRESULT(WINAPI* PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE)(
12 + __in PREQBA_DATA* pPreqData,
13 + __in IBootstrapperEngine* pEngine,
14 + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
15 + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
16 + );
src/ext/Bal/wixstdba/precomp.h
+36 -30
@@ -17,43 +17,49 @@
17 #include <strsafe.h>
18 #include <stddef.h>
19
20 -#include "dutil.h"
21 -#include "apputil.h"
22 -#include "memutil.h"
23 -#include "dictutil.h"
24 -#include "dirutil.h"
25 -#include "fileutil.h"
26 -#include "locutil.h"
27 -#include "logutil.h"
28 -#include "pathutil.h"
29 -#include "resrutil.h"
30 -#include "shelutil.h"
31 -#include "strutil.h"
32 -#include "wndutil.h"
33 -#include "thmutil.h"
34 -#include "verutil.h"
35 -#include "uriutil.h"
36 -#include "xmlutil.h"
37 -
38 -#include "BootstrapperEngine.h"
39 -#include "BootstrapperApplication.h"
40 -#include "IBootstrapperEngine.h"
41 -#include "IBootstrapperApplication.h"
42 -
43 -#include "balutil.h"
44 -#include "balinfo.h"
45 -#include "balcondition.h"
46 -
47 -#include "BAFunctions.h"
20 +#include <dutil.h>
21 +#include <apputil.h>
22 +#include <memutil.h>
23 +#include <dictutil.h>
24 +#include <dirutil.h>
25 +#include <fileutil.h>
26 +#include <locutil.h>
27 +#include <logutil.h>
28 +#include <pathutil.h>
29 +#include <resrutil.h>
30 +#include <shelutil.h>
31 +#include <strutil.h>
32 +#include <wndutil.h>
33 +#include <thmutil.h>
34 +#include <verutil.h>
35 +#include <uriutil.h>
36 +#include <xmlutil.h>
37
38 +#include <BootstrapperEngine.h>
39 +#include <BootstrapperApplication.h>
40 +#include <IBootstrapperEngine.h>
41 +#include <IBootstrapperApplication.h>
42 +
43 +#include <balutil.h>
44 +#include <balinfo.h>
45 +#include <balcondition.h>
46 +
47 +#include <BAFunctions.h>
48 +
49 +#include "inc\preqba.h"
50 #include "wixstdba.messages.h"
51
52 HRESULT CreateBootstrapperApplication(
53 __in HMODULE hModule,
53 - __in BOOL fPrereq,
54 - __in HRESULT hrHostInitialization,
54 + __in_opt PREQBA_DATA* pPrereqData,
55 __in IBootstrapperEngine* pEngine,
56 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
57 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults,
58 __out IBootstrapperApplication** ppApplication
59 );
60 +
61 +void DestroyBootstrapperApplication(
62 + __in IBootstrapperApplication* pApplication,
63 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
64 + __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
65 + );
src/ext/Bal/wixstdba/wixstdba.cpp
+17 -37
@@ -50,7 +50,7 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
50 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
51 ExitOnFailure(hr, "Failed to initialize Bal.");
52
53 - hr = CreateBootstrapperApplication(vhInstance, FALSE, S_OK, pEngine, pArgs, pResults, &vpApplication);
53 + hr = CreateBootstrapperApplication(vhInstance, NULL, pEngine, pArgs, pResults, &vpApplication);
54 BalExitOnFailure(hr, "Failed to create bootstrapper application interface.");
55
56 LExit:
@@ -60,45 +60,24 @@ LExit:
60 }
61
62
63 -extern "C" void WINAPI BootstrapperApplicationDestroy()
64 -{
65 - ReleaseNullObject(vpApplication);
66 - BalUninitialize();
67 - DutilUninitialize();
68 -}
69 -
70 -
71 -extern "C" HRESULT WINAPI DncPrereqBootstrapperApplicationCreate(
72 - __in HRESULT hrHostInitialization,
73 - __in IBootstrapperEngine* pEngine,
74 - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
75 - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
63 +extern "C" void WINAPI BootstrapperApplicationDestroy(
64 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
65 + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
66 )
67 {
78 - HRESULT hr = S_OK;
79 -
80 - DutilInitialize(&WixstdbaTraceError);
81 -
82 - BalInitialize(pEngine);
83 -
84 - hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication);
85 - BalExitOnFailure(hr, "Failed to create .NET Core prerequisite bootstrapper application interface.");
86 -
87 -LExit:
88 - return hr;
89 -}
90 -
68 + if (vpApplication)
69 + {
70 + DestroyBootstrapperApplication(vpApplication, pArgs, pResults);
71 + }
72
92 -extern "C" void WINAPI DncPrereqBootstrapperApplicationDestroy()
93 -{
73 ReleaseNullObject(vpApplication);
74 BalUninitialize();
75 DutilUninitialize();
76 }
77
78
100 -extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate(
101 - __in HRESULT hrHostInitialization,
79 +extern "C" HRESULT WINAPI PrereqBootstrapperApplicationCreate(
80 + __in_opt PREQBA_DATA* pPrereqData,
81 __in IBootstrapperEngine* pEngine,
82 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
83 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -110,19 +89,20 @@ extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate(
89
90 BalInitialize(pEngine);
91
113 - hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication);
114 - BalExitOnFailure(hr, "Failed to create managed prerequisite bootstrapper application interface.");
92 + hr = CreateBootstrapperApplication(vhInstance, pPrereqData, pEngine, pArgs, pResults, &vpApplication);
93 + BalExitOnFailure(hr, "Failed to create prerequisite bootstrapper application interface.");
94
95 LExit:
96 return hr;
97 }
98
99
121 -extern "C" void WINAPI MbaPrereqBootstrapperApplicationDestroy()
100 +extern "C" void WINAPI PrereqBootstrapperApplicationDestroy(
101 + __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
102 + __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
103 + )
104 {
123 - ReleaseNullObject(vpApplication);
124 - BalUninitialize();
125 - DutilUninitialize();
105 + BootstrapperApplicationDestroy(pArgs, pResults);
106 }
107
108 static void CALLBACK WixstdbaTraceError(
src/ext/Bal/wixstdba/wixstdba.def
+2 -4
@@ -4,7 +4,5 @@
4 EXPORTS
5 BootstrapperApplicationCreate
6 BootstrapperApplicationDestroy
7 - DncPrereqBootstrapperApplicationCreate
8 - DncPrereqBootstrapperApplicationDestroy
9 - MbaPrereqBootstrapperApplicationCreate
10 - MbaPrereqBootstrapperApplicationDestroy
7 + PrereqBootstrapperApplicationCreate
8 + PrereqBootstrapperApplicationDestroy
src/ext/Bal/wixstdba/wixstdba.vcxproj
+1
@@ -52,6 +52,7 @@
52 <ClCompile Include="wixstdba.cpp" />
53 </ItemGroup>
54 <ItemGroup>
55 + <ClInclude Include="inc\preqba.h" />
56 <ClInclude Include="precomp.h" />
57 <ClInclude Include="resource.h" />
58 </ItemGroup>
src/test/burn/TestBA/TestBA.cs
+7 -1
@@ -171,7 +171,13 @@ namespace WixToolset.Test.BA
171 this.dummyWindow.Dispose();
172 }
173
174 - this.Engine.Quit(this.result & 0xFFFF); // return plain old Win32 error, not HRESULT.
174 + var exitCode = this.result;
175 + if ((exitCode & 0xFFFF0000) == unchecked(0x80070000))
176 + {
177 + exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT.
178 + }
179 +
180 + this.Engine.Quit(exitCode);
181 }
182
183 protected override void OnDetectUpdateBegin(DetectUpdateBeginEventArgs args)
src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp
+2
@@ -40,6 +40,8 @@ LExit:
40 }
41
42 extern "C" void WINAPI BAFunctionsDestroy(
43 + __in const BA_FUNCTIONS_DESTROY_ARGS* /*pArgs*/,
44 + __inout BA_FUNCTIONS_DESTROY_RESULTS* /*pResults*/
45 )
46 {
47 BalUninitialize();
src/test/burn/WixToolset.WixBA/WixBA.cs
+8 -1
@@ -179,7 +179,14 @@ namespace WixToolset.WixBA
179 Threading.Dispatcher.Run();
180
181 this.PostTelemetry();
182 - this.Engine.Quit(WixBA.Model.Result);
182 +
183 + var exitCode = WixBA.Model.Result;
184 + if ((exitCode & 0xFFFF0000) == unchecked(0x80070000))
185 + {
186 + exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT.
187 + }
188 +
189 + this.Engine.Quit(exitCode);
190 }
191
192 private void PostTelemetry()
src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs
+4 -2
@@ -12,6 +12,8 @@ namespace WixToolsetTest.BurnE2E
12 {
13 public PrereqBaTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
14
15 + const int E_PREREQBA_INFINITE_LOOP = -2_114_714_646;
16 +
17 /// <summary>
18 /// This bundle purposely provides a .runtimeconfig.json file that requires a version of .NET Core that doesn't exist,
19 /// with an MSI package to represent the prerequisite package.
@@ -32,7 +34,7 @@ namespace WixToolsetTest.BurnE2E
34 // Source file should *not* be installed
35 Assert.False(File.Exists(packageASourceCodeInstalled), $"Package A payload should not be there on test start: {packageASourceCodeInstalled}");
36
35 - bundleA.Install();
37 + bundleA.Install(E_PREREQBA_INFINITE_LOOP);
38
39 // Part of the test is Install actually completing.
40
@@ -63,7 +65,7 @@ namespace WixToolsetTest.BurnE2E
65 // Source file should *not* be installed
66 Assert.False(File.Exists(packageBSourceCodeInstalled), $"Package B payload should not be there on test start: {packageBSourceCodeInstalled}");
67
66 - bundleB.Install();
68 + bundleB.Install(E_PREREQBA_INFINITE_LOOP);
69
70 // Part of the test is Install actually completing.
71