diff options
Diffstat (limited to 'src/ext/Bal/mbahost/mbahost.cpp')
-rw-r--r-- | src/ext/Bal/mbahost/mbahost.cpp | 289 |
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 | ||
6 | static const DWORD NET452_RELEASE = 379893; | 5 | static 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 | ||
17 | extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( | 16 | static 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 | |||
24 | static HINSTANCE vhInstance = NULL; | ||
25 | static ICorRuntimeHost *vpCLRHost = NULL; | ||
26 | static _AppDomain *vpAppDomain = NULL; | ||
27 | static HMODULE vhMbapreqModule = NULL; | ||
28 | 17 | ||
29 | 18 | ||
30 | // internal function declarations | 19 | // internal function declarations |
31 | 20 | ||
32 | static HRESULT GetAppDomain( | 21 | static HRESULT GetAppDomain( |
33 | __out _AppDomain** ppAppDomain | 22 | __in MBASTATE* pState |
34 | ); | 23 | ); |
35 | static HRESULT GetAppBase( | 24 | static HRESULT LoadModulePaths( |
36 | __out LPWSTR* psczAppBase | 25 | __in MBASTATE* pState |
37 | ); | 26 | ); |
38 | static HRESULT CheckSupportedFrameworks( | 27 | static 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 | ); |
46 | static HRESULT GetCLRHost( | 35 | static HRESULT LoadRuntime( |
47 | __in LPCWSTR wzConfigPath, | 36 | __in MBASTATE* pState |
48 | __out ICorRuntimeHost** ppCLRHost | ||
49 | ); | 37 | ); |
50 | static HRESULT CreateManagedBootstrapperApplication( | 38 | static 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 | ); |
59 | static HRESULT CreatePrerequisiteBA( | 47 | static 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 | ||
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 | ) | ||
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. |
172 | static HRESULT GetAppDomain( | 199 | static 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 | ||
230 | LExit: | 237 | LExit: |
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 | ||
241 | static HRESULT GetAppBase( | 245 | static 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 | |||
254 | LExit: | 261 | LExit: |
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. |
393 | static HRESULT GetCLRHost( | 400 | static 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 | ||
493 | LExit: | 496 | LExit: |
494 | ReleaseStr(pwzVersion); | 497 | ReleaseStr(pwzVersion); |
@@ -569,7 +572,7 @@ LExit: | |||
569 | } | 572 | } |
570 | 573 | ||
571 | static HRESULT CreatePrerequisiteBA( | 574 | static 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 | ||
597 | LExit: | 600 | LExit: |