summaryrefslogtreecommitdiff
path: root/src/ext/Bal/mbahost/mbahost.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Bal/mbahost/mbahost.cpp')
-rw-r--r--src/ext/Bal/mbahost/mbahost.cpp289
1 files changed, 146 insertions, 143 deletions
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 @@
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. 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 2
3#include "precomp.h" 3#include "precomp.h"
4#include <WixToolset.Mba.Host.h> // includes the generated assembly name macros.
5 4
6static const DWORD NET452_RELEASE = 379893; 5static const DWORD NET452_RELEASE = 379893;
7 6
@@ -14,26 +13,16 @@ extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)(
14 __out LPVOID *ppv 13 __out LPVOID *ppv
15 ); 14 );
16 15
17extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( 16static MBASTATE vstate = { };
18 __in HRESULT hrHostInitialization,
19 __in IBootstrapperEngine* pEngine,
20 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
21 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
22 );
23
24static HINSTANCE vhInstance = NULL;
25static ICorRuntimeHost *vpCLRHost = NULL;
26static _AppDomain *vpAppDomain = NULL;
27static HMODULE vhMbapreqModule = NULL;
28 17
29 18
30// internal function declarations 19// internal function declarations
31 20
32static HRESULT GetAppDomain( 21static HRESULT GetAppDomain(
33 __out _AppDomain** ppAppDomain 22 __in MBASTATE* pState
34 ); 23 );
35static HRESULT GetAppBase( 24static HRESULT LoadModulePaths(
36 __out LPWSTR* psczAppBase 25 __in MBASTATE* pState
37 ); 26 );
38static HRESULT CheckSupportedFrameworks( 27static HRESULT CheckSupportedFrameworks(
39 __in LPCWSTR wzConfigPath 28 __in LPCWSTR wzConfigPath
@@ -43,9 +32,8 @@ static HRESULT UpdateSupportedRuntime(
43 __in IXMLDOMNode* pixnSupportedFramework, 32 __in IXMLDOMNode* pixnSupportedFramework,
44 __out BOOL* pfUpdatedManifest 33 __out BOOL* pfUpdatedManifest
45 ); 34 );
46static HRESULT GetCLRHost( 35static HRESULT LoadRuntime(
47 __in LPCWSTR wzConfigPath, 36 __in MBASTATE* pState
48 __out ICorRuntimeHost** ppCLRHost
49 ); 37 );
50static HRESULT CreateManagedBootstrapperApplication( 38static HRESULT CreateManagedBootstrapperApplication(
51 __in _AppDomain* pAppDomain, 39 __in _AppDomain* pAppDomain,
@@ -57,7 +45,7 @@ static HRESULT CreateManagedBootstrapperApplicationFactory(
57 __out IBootstrapperApplicationFactory** ppAppFactory 45 __out IBootstrapperApplicationFactory** ppAppFactory
58 ); 46 );
59static HRESULT CreatePrerequisiteBA( 47static HRESULT CreatePrerequisiteBA(
60 __in HRESULT hrHostInitialization, 48 __in MBASTATE* pState,
61 __in IBootstrapperEngine* pEngine, 49 __in IBootstrapperEngine* pEngine,
62 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 50 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
63 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 51 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -78,11 +66,11 @@ extern "C" BOOL WINAPI DllMain(
78 { 66 {
79 case DLL_PROCESS_ATTACH: 67 case DLL_PROCESS_ATTACH:
80 ::DisableThreadLibraryCalls(hInstance); 68 ::DisableThreadLibraryCalls(hInstance);
81 vhInstance = hInstance; 69 vstate.hInstance = hInstance;
82 break; 70 break;
83 71
84 case DLL_PROCESS_DETACH: 72 case DLL_PROCESS_DETACH:
85 vhInstance = NULL; 73 vstate.hInstance = NULL;
86 break; 74 break;
87 } 75 }
88 76
@@ -96,18 +84,39 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
96 ) 84 )
97{ 85{
98 HRESULT hr = S_OK; 86 HRESULT hr = S_OK;
99 HRESULT hrHostInitialization = S_OK;
100 IBootstrapperEngine* pEngine = NULL; 87 IBootstrapperEngine* pEngine = NULL;
101 88
89 if (vstate.fStoppedRuntime)
90 {
91 BalExitWithRootFailure(hr, E_INVALIDSTATE, "Reloaded mbahost after stopping .NET runtime.");
92 }
93
102 hr = BalInitializeFromCreateArgs(pArgs, &pEngine); 94 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
103 ExitOnFailure(hr, "Failed to initialize Bal."); 95 ExitOnFailure(hr, "Failed to initialize Bal.");
104 96
105 hr = GetAppDomain(&vpAppDomain); 97 if (!vstate.fInitialized)
106 if (SUCCEEDED(hr)) 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)
107 { 113 {
114 hr = GetAppDomain(&vstate);
115 BalExitOnFailure(hr, "Failed to create the AppDomain for the managed bootstrapper application.");
116
108 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application."); 117 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application.");
109 118
110 hr = CreateManagedBootstrapperApplication(vpAppDomain, pArgs, pResults); 119 hr = CreateManagedBootstrapperApplication(vstate.pAppDomain, pArgs, pResults);
111 BalExitOnFailure(hr, "Failed to create the managed bootstrapper application."); 120 BalExitOnFailure(hr, "Failed to create the managed bootstrapper application.");
112 } 121 }
113 else // fallback to the prerequisite BA. 122 else // fallback to the prerequisite BA.
@@ -115,16 +124,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
115 if (E_MBAHOST_NET452_ON_WIN7RTM == hr) 124 if (E_MBAHOST_NET452_ON_WIN7RTM == hr)
116 { 125 {
117 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."); 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;
119 } 134 }
120 else 135 else
121 { 136 {
122 hrHostInitialization = S_OK; 137 vstate.prereqData.hrHostInitialization = S_OK;
123 } 138 }
124 139
125 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr); 140 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr);
126 141
127 hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, pArgs, pResults); 142 hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
128 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); 143 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
129 } 144 }
130 145
@@ -134,73 +149,65 @@ LExit:
134 return hr; 149 return hr;
135} 150}
136 151
137extern "C" void WINAPI BootstrapperApplicationDestroy() 152extern "C" void WINAPI BootstrapperApplicationDestroy(
153 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
154 __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
155 )
138{ 156{
139 if (vpAppDomain) 157 BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
158
159 if (vstate.pAppDomain)
140 { 160 {
141 HRESULT hr = vpCLRHost->UnloadDomain(vpAppDomain); 161 HRESULT hr = vstate.pCLRHost->UnloadDomain(vstate.pAppDomain);
142 if (FAILED(hr)) 162 if (FAILED(hr))
143 { 163 {
144 BalLogError(hr, "Failed to unload app domain."); 164 BalLogError(hr, "Failed to unload app domain.");
145 } 165 }
146 166
147 vpAppDomain->Release(); 167 vstate.pAppDomain->Release();
168 vstate.pAppDomain = NULL;
148 } 169 }
149 170
150 if (vpCLRHost) 171 // pCLRHost can only be stopped once per process.
172 if (vstate.pCLRHost && !pArgs->fReload)
151 { 173 {
152 vpCLRHost->Stop(); 174 vstate.pCLRHost->Stop();
153 vpCLRHost->Release(); 175 vstate.pCLRHost->Release();
176 vstate.pCLRHost = NULL;
177 vstate.fStoppedRuntime = TRUE;
154 } 178 }
155 179
156 if (vhMbapreqModule) 180 if (vstate.hMbapreqModule)
157 { 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"));
159 if (pfnDestroy) 183 if (pfnDestroy)
160 { 184 {
161 (*pfnDestroy)(); 185 (*pfnDestroy)(pArgs, &childResults);
162 } 186 }
163 187
164 ::FreeLibrary(vhMbapreqModule); 188 ::FreeLibrary(vstate.hMbapreqModule);
165 vhMbapreqModule = NULL; 189 vstate.hMbapreqModule = NULL;
166 } 190 }
167 191
168 BalUninitialize(); 192 BalUninitialize();
193
194 // Need to keep track of state between reloads.
195 pResults->fDisableUnloading = TRUE;
169} 196}
170 197
171// Gets the custom AppDomain for loading managed BA. 198// Gets the custom AppDomain for loading managed BA.
172static HRESULT GetAppDomain( 199static HRESULT GetAppDomain(
173 __out _AppDomain **ppAppDomain 200 __in MBASTATE* pState
174 ) 201 )
175{ 202{
176 HRESULT hr = S_OK; 203 HRESULT hr = S_OK;
177 ICorRuntimeHost *pCLRHost = NULL;
178 IUnknown *pUnk = NULL; 204 IUnknown *pUnk = NULL;
179 LPWSTR sczAppBase = NULL; 205 IAppDomainSetup* pAppDomainSetup = NULL;
180 LPWSTR sczConfigPath = NULL;
181 IAppDomainSetup *pAppDomainSetup;
182 BSTR bstrAppBase = NULL; 206 BSTR bstrAppBase = NULL;
183 BSTR bstrConfigPath = NULL; 207 BSTR bstrConfigPath = NULL;
184 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
202 // Create the setup information for a new AppDomain to set the app base and config. 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);
204 ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object."); 211 ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object.");
205 212
206 hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup)); 213 hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup));
@@ -208,49 +215,49 @@ static HRESULT GetAppDomain(
208 ReleaseNullObject(pUnk); 215 ReleaseNullObject(pUnk);
209 216
210 // Set properties on the AppDomainSetup object. 217 // Set properties on the AppDomainSetup object.
211 bstrAppBase = ::SysAllocString(sczAppBase); 218 bstrAppBase = ::SysAllocString(pState->sczAppBase);
212 ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup."); 219 ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup.");
213 220
214 hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase); 221 hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase);
215 ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup."); 222 ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup.");
216 223
217 bstrConfigPath = ::SysAllocString(sczConfigPath); 224 bstrConfigPath = ::SysAllocString(pState->sczConfigPath);
218 ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup."); 225 ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup.");
219 226
220 hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath); 227 hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath);
221 ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup."); 228 ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup.");
222 229
223 // Create the AppDomain to load the factory type. 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);
225 ExitOnRootFailure(hr, "Failed to create the MBA AppDomain."); 232 ExitOnRootFailure(hr, "Failed to create the MBA AppDomain.");
226 233
227 hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(ppAppDomain)); 234 hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(&pState->pAppDomain));
228 ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface."); 235 ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface.");
229 236
230LExit: 237LExit:
231 ReleaseBSTR(bstrConfigPath); 238 ReleaseBSTR(bstrConfigPath);
232 ReleaseBSTR(bstrAppBase); 239 ReleaseBSTR(bstrAppBase);
233 ReleaseStr(sczConfigPath);
234 ReleaseStr(sczAppBase);
235 ReleaseNullObject(pUnk); 240 ReleaseNullObject(pUnk);
236 ReleaseNullObject(pCLRHost);
237 241
238 return hr; 242 return hr;
239} 243}
240 244
241static HRESULT GetAppBase( 245static HRESULT LoadModulePaths(
242 __out LPWSTR *psczAppBase 246 __in MBASTATE* pState
243 ) 247 )
244{ 248{
245 HRESULT hr = S_OK; 249 HRESULT hr = S_OK;
246 LPWSTR sczFullPath = NULL; 250 LPWSTR sczFullPath = NULL;
247 251
248 hr = PathForCurrentProcess(&sczFullPath, vhInstance); 252 hr = PathForCurrentProcess(&sczFullPath, pState->hInstance);
249 ExitOnFailure(hr, "Failed to get the full host path."); 253 ExitOnFailure(hr, "Failed to get the full host path.");
250 254
251 hr = PathGetDirectory(sczFullPath, psczAppBase); 255 hr = PathGetDirectory(sczFullPath, &pState->sczAppBase);
252 ExitOnFailure(hr, "Failed to get the directory of the full process path."); 256 ExitOnFailure(hr, "Failed to get the directory of the full process path.");
253 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
254LExit: 261LExit:
255 ReleaseStr(sczFullPath); 262 ReleaseStr(sczFullPath);
256 263
@@ -390,9 +397,8 @@ LExit:
390} 397}
391 398
392// Gets the CLR host and caches it. 399// Gets the CLR host and caches it.
393static HRESULT GetCLRHost( 400static HRESULT LoadRuntime(
394 __in LPCWSTR wzConfigPath, 401 __in MBASTATE* pState
395 __out ICorRuntimeHost **ppCLRHost
396 ) 402 )
397{ 403{
398 HRESULT hr = S_OK; 404 HRESULT hr = S_OK;
@@ -411,84 +417,81 @@ static HRESULT GetCLRHost(
411 // Always set the error mode because we will always restore it below. 417 // Always set the error mode because we will always restore it below.
412 uiMode = ::SetErrorMode(0); 418 uiMode = ::SetErrorMode(0);
413 419
414 // Cache the CLR host to be shutdown later. This can occur on a different thread. 420 // Check that the supported framework is installed.
415 if (!vpCLRHost) 421 hr = CheckSupportedFrameworks(pState->sczConfigPath);
416 { 422 ExitOnFailure(hr, "Failed to find supported framework.");
417 // Disable message boxes from being displayed on error and blocking execution.
418 ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
419 423
420 hr = LoadSystemLibrary(L"mscoree.dll", &hModule); 424 // Cache the CLR host to be shutdown later. This can occur on a different thread.
421 ExitOnFailure(hr, "Failed to load mscoree.dll"); 425 // Disable message boxes from being displayed on error and blocking execution.
426 ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
422 427
423 pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance")); 428 hr = LoadSystemLibrary(L"mscoree.dll", &hModule);
424 429 ExitOnFailure(hr, "Failed to load mscoree.dll");
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.");
431 430
432 fFallbackToCorBindToCurrentRuntime = FALSE; 431 pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance"));
433 }
434 }
435 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 { 437 {
438 pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime")); 438 ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy.");
439 ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
440 439
441 hr = pfnCorBindToCurrentRuntime(wzConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&vpCLRHost)); 440 fFallbackToCorBindToCurrentRuntime = FALSE;
442 ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
443 } 441 }
444 else 442 }
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);
449 443
450 hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo)); 444 if (fFallbackToCorBindToCurrentRuntime)
451 ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path."); 445 {
446 pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime"));
447 ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
452 448
453 // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL. 449 hr = pfnCorBindToCurrentRuntime(pState->sczConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
454 if (!cchVersion) 450 ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
455 { 451 }
456 hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion); 452 else
457 if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) 453 {
458 {
459 ExitOnFailure(hr, "Failed to get the length of the CLR version string.");
460 }
461 }
462 454
463 hr = StrAlloc(&pwzVersion, cchVersion); 455 hr = SHCreateStreamOnFileEx(pState->sczConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream);
464 ExitOnFailure(hr, "Failed to allocate the CLR version string."); 456 ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", pState->sczConfigPath);
465 457
466 hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion); 458 hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo));
467 ExitOnFailure(hr, "Failed to get the CLR version string."); 459 ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path.");
468 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)
470 { 466 {
471 hr = VerifyNET4RuntimeIsSupported(); 467 ExitOnFailure(hr, "Failed to get the length of the CLR version string.");
472 ExitOnFailure(hr, "Found unsupported .NET 4 Runtime.");
473 } 468 }
469 }
474 470
475 if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags)) 471 hr = StrAlloc(&pwzVersion, cchVersion);
476 { 472 ExitOnFailure(hr, "Failed to allocate the CLR version string.");
477 hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
478 ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
479 }
480 473
481 hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&vpCLRHost)); 474 hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion);
482 ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost."); 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 }
483 482
484 // TODO: use ICLRRuntimeHost instead of ICorRuntimeHost on .NET 4 since the former is faster and the latter is deprecated 483 if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags))
485 //hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast<LPVOID*>(&pCLRRuntimeHost)); 484 {
486 //ExitOnRootFailure(hr, "Failed to get instance of ICLRRuntimeHost."); 485 hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
486 ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
487 } 487 }
488
489 hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
490 ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost.");
488 } 491 }
489 492
490 vpCLRHost->AddRef(); 493 hr = pState->pCLRHost->Start();
491 *ppCLRHost = vpCLRHost; 494 ExitOnRootFailure(hr, "Failed to start the CLR host.");
492 495
493LExit: 496LExit:
494 ReleaseStr(pwzVersion); 497 ReleaseStr(pwzVersion);
@@ -569,7 +572,7 @@ LExit:
569} 572}
570 573
571static HRESULT CreatePrerequisiteBA( 574static HRESULT CreatePrerequisiteBA(
572 __in HRESULT hrHostInitialization, 575 __in MBASTATE* pState,
573 __in IBootstrapperEngine* pEngine, 576 __in IBootstrapperEngine* pEngine,
574 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 577 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
575 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 578 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -579,19 +582,19 @@ static HRESULT CreatePrerequisiteBA(
579 LPWSTR sczMbapreqPath = NULL; 582 LPWSTR sczMbapreqPath = NULL;
580 HMODULE hModule = NULL; 583 HMODULE hModule = NULL;
581 584
582 hr = PathRelativeToModule(&sczMbapreqPath, L"mbapreq.dll", vhInstance); 585 hr = PathConcat(pState->sczAppBase, L"mbapreq.dll", &sczMbapreqPath);
583 ExitOnFailure(hr, "Failed to get path to pre-requisite BA."); 586 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
584 587
585 hModule = ::LoadLibraryW(sczMbapreqPath); 588 hModule = ::LoadLibraryExW(sczMbapreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
586 ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); 589 ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
587 590
588 PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "MbaPrereqBootstrapperApplicationCreate")); 591 PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
589 ExitOnNullWithLastError(pfnCreate, hr, "Failed to get MbaPrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath); 592 ExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath);
590 593
591 hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); 594 hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
592 ExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); 595 ExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
593 596
594 vhMbapreqModule = hModule; 597 pState->hMbapreqModule = hModule;
595 hModule = NULL; 598 hModule = NULL;
596 599
597LExit: 600LExit: