aboutsummaryrefslogtreecommitdiff
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.cpp693
1 files changed, 0 insertions, 693 deletions
diff --git a/src/ext/Bal/mbahost/mbahost.cpp b/src/ext/Bal/mbahost/mbahost.cpp
deleted file mode 100644
index 9d8acc8a..00000000
--- a/src/ext/Bal/mbahost/mbahost.cpp
+++ /dev/null
@@ -1,693 +0,0 @@
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
5static const DWORD NET452_RELEASE = 379893;
6
7using namespace mscorlib;
8
9extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)(
10 __in LPCWSTR pwszFileName,
11 __in REFCLSID rclsid,
12 __in REFIID riid,
13 __out LPVOID *ppv
14 );
15
16static MBASTATE vstate = { };
17
18
19// internal function declarations
20
21static HRESULT GetAppDomain(
22 __in MBASTATE* pState
23 );
24static HRESULT LoadModulePaths(
25 __in MBASTATE* pState
26 );
27static HRESULT LoadMbaConfiguration(
28 __in MBASTATE* pState,
29 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs
30 );
31static HRESULT CheckSupportedFrameworks(
32 __in LPCWSTR wzConfigPath
33 );
34static HRESULT UpdateSupportedRuntime(
35 __in IXMLDOMDocument* pixdManifest,
36 __in IXMLDOMNode* pixnSupportedFramework,
37 __out BOOL* pfUpdatedManifest
38 );
39static HRESULT LoadRuntime(
40 __in MBASTATE* pState
41 );
42static HRESULT CreateManagedBootstrapperApplication(
43 __in _AppDomain* pAppDomain,
44 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
45 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
46 );
47static HRESULT CreateManagedBootstrapperApplicationFactory(
48 __in _AppDomain* pAppDomain,
49 __out IBootstrapperApplicationFactory** ppAppFactory
50 );
51static HRESULT CreatePrerequisiteBA(
52 __in MBASTATE* pState,
53 __in IBootstrapperEngine* pEngine,
54 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
55 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
56 );
57static HRESULT VerifyNET4RuntimeIsSupported(
58 );
59
60
61// function definitions
62
63extern "C" BOOL WINAPI DllMain(
64 IN HINSTANCE hInstance,
65 IN DWORD dwReason,
66 IN LPVOID /* pvReserved */
67 )
68{
69 switch (dwReason)
70 {
71 case DLL_PROCESS_ATTACH:
72 ::DisableThreadLibraryCalls(hInstance);
73 vstate.hInstance = hInstance;
74 break;
75
76 case DLL_PROCESS_DETACH:
77 vstate.hInstance = NULL;
78 break;
79 }
80
81 return TRUE;
82}
83
84// Note: This function assumes that COM was already initialized on the thread.
85extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
86 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
87 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
88 )
89{
90 HRESULT hr = S_OK;
91 IBootstrapperEngine* pEngine = NULL;
92
93 if (vstate.fStoppedRuntime)
94 {
95 BalExitWithRootFailure(hr, E_INVALIDSTATE, "Reloaded mbahost after stopping .NET runtime.");
96 }
97
98 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
99 ExitOnFailure(hr, "Failed to initialize Bal.");
100
101 if (!vstate.fInitialized)
102 {
103 hr = XmlInitialize();
104 BalExitOnFailure(hr, "Failed to initialize XML.");
105
106 hr = LoadModulePaths(&vstate);
107 BalExitOnFailure(hr, "Failed to load the module paths.");
108
109 hr = LoadMbaConfiguration(&vstate, pArgs);
110 BalExitOnFailure(hr, "Failed to get the mba configuration.");
111
112 vstate.fInitialized = TRUE;
113 }
114
115 if (vstate.prereqData.fAlwaysInstallPrereqs && !vstate.prereqData.fCompleted)
116 {
117 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application since it's configured to always run before loading the runtime.");
118
119 hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
120 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
121
122 ExitFunction();
123 }
124
125 if (!vstate.fInitializedRuntime)
126 {
127 hr = LoadRuntime(&vstate);
128
129 vstate.fInitializedRuntime = SUCCEEDED(hr);
130 }
131
132 if (vstate.fInitializedRuntime)
133 {
134 hr = GetAppDomain(&vstate);
135 BalExitOnFailure(hr, "Failed to create the AppDomain for the managed bootstrapper application.");
136
137 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application.");
138
139 hr = CreateManagedBootstrapperApplication(vstate.pAppDomain, pArgs, pResults);
140 BalExitOnFailure(hr, "Failed to create the managed bootstrapper application.");
141 }
142 else // fallback to the prerequisite BA.
143 {
144 if (E_MBAHOST_NET452_ON_WIN7RTM == hr)
145 {
146 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.");
147 vstate.prereqData.hrFatalError = hr;
148 }
149 else if (vstate.prereqData.fCompleted)
150 {
151 hr = E_PREREQBA_INFINITE_LOOP;
152 BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
153 vstate.prereqData.hrFatalError = hr;
154 }
155 else
156 {
157 vstate.prereqData.hrFatalError = S_OK;
158 }
159
160 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr);
161
162 hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
163 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
164 }
165
166LExit:
167 ReleaseNullObject(pEngine);
168
169 return hr;
170}
171
172extern "C" void WINAPI BootstrapperApplicationDestroy(
173 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
174 __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
175 )
176{
177 BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
178
179 if (vstate.pAppDomain)
180 {
181 HRESULT hr = vstate.pCLRHost->UnloadDomain(vstate.pAppDomain);
182 if (FAILED(hr))
183 {
184 BalLogError(hr, "Failed to unload app domain.");
185 }
186
187 vstate.pAppDomain->Release();
188 vstate.pAppDomain = NULL;
189 }
190
191 // pCLRHost can only be stopped once per process.
192 if (vstate.pCLRHost && !pArgs->fReload)
193 {
194 vstate.pCLRHost->Stop();
195 vstate.pCLRHost->Release();
196 vstate.pCLRHost = NULL;
197 vstate.fStoppedRuntime = TRUE;
198 }
199
200 if (vstate.hMbapreqModule)
201 {
202 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy"));
203 if (pfnDestroy)
204 {
205 (*pfnDestroy)(pArgs, &childResults);
206 }
207
208 ::FreeLibrary(vstate.hMbapreqModule);
209 vstate.hMbapreqModule = NULL;
210 }
211
212 BalUninitialize();
213
214 // Need to keep track of state between reloads.
215 pResults->fDisableUnloading = TRUE;
216}
217
218// Gets the custom AppDomain for loading managed BA.
219static HRESULT GetAppDomain(
220 __in MBASTATE* pState
221 )
222{
223 HRESULT hr = S_OK;
224 IUnknown *pUnk = NULL;
225 IAppDomainSetup* pAppDomainSetup = NULL;
226 BSTR bstrAppBase = NULL;
227 BSTR bstrConfigPath = NULL;
228
229 // Create the setup information for a new AppDomain to set the app base and config.
230 hr = pState->pCLRHost->CreateDomainSetup(&pUnk);
231 BalExitOnRootFailure(hr, "Failed to create the AppDomainSetup object.");
232
233 hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup));
234 BalExitOnRootFailure(hr, "Failed to query for the IAppDomainSetup interface.");
235 ReleaseNullObject(pUnk);
236
237 // Set properties on the AppDomainSetup object.
238 bstrAppBase = ::SysAllocString(pState->sczAppBase);
239 BalExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup.");
240
241 hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase);
242 BalExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup.");
243
244 bstrConfigPath = ::SysAllocString(pState->sczConfigPath);
245 BalExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup.");
246
247 hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath);
248 BalExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup.");
249
250 // Create the AppDomain to load the factory type.
251 hr = pState->pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk);
252 BalExitOnRootFailure(hr, "Failed to create the MBA AppDomain.");
253
254 hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(&pState->pAppDomain));
255 BalExitOnRootFailure(hr, "Failed to query for the _AppDomain interface.");
256
257LExit:
258 ReleaseBSTR(bstrConfigPath);
259 ReleaseBSTR(bstrAppBase);
260 ReleaseNullObject(pUnk);
261
262 return hr;
263}
264
265static HRESULT LoadModulePaths(
266 __in MBASTATE* pState
267 )
268{
269 HRESULT hr = S_OK;
270 LPWSTR sczFullPath = NULL;
271
272 hr = PathForCurrentProcess(&sczFullPath, pState->hInstance);
273 BalExitOnFailure(hr, "Failed to get the full host path.");
274
275 hr = PathGetDirectory(sczFullPath, &pState->sczAppBase);
276 BalExitOnFailure(hr, "Failed to get the directory of the full process path.");
277
278 hr = PathConcat(pState->sczAppBase, MBA_CONFIG_FILE_NAME, &pState->sczConfigPath);
279 BalExitOnFailure(hr, "Failed to get the full path to the application configuration file.");
280
281LExit:
282 ReleaseStr(sczFullPath);
283
284 return hr;
285}
286
287static HRESULT LoadMbaConfiguration(
288 __in MBASTATE* pState,
289 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs
290 )
291{
292 HRESULT hr = S_OK;
293 IXMLDOMDocument* pixdManifest = NULL;
294 IXMLDOMNode* pixnHost = NULL;
295 BOOL fXmlFound = FALSE;
296
297 hr = XmlLoadDocumentFromFile(pArgs->pCommand->wzBootstrapperApplicationDataPath, &pixdManifest);
298 BalExitOnFailure(hr, "Failed to load BalManifest '%ls'", pArgs->pCommand->wzBootstrapperApplicationDataPath);
299
300 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqOptions", &pixnHost);
301 BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find WixMbaPrereqOptions element in bootstrapper application config.");
302
303 if (fXmlFound)
304 {
305 hr = XmlGetAttributeNumber(pixnHost, L"AlwaysInstallPrereqs", reinterpret_cast<DWORD*>(&pState->prereqData.fAlwaysInstallPrereqs));
306 BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get AlwaysInstallPrereqs value.");
307 }
308
309 pState->prereqData.fPerformHelp = !pState->prereqData.fAlwaysInstallPrereqs;
310
311LExit:
312 ReleaseObject(pixnHost);
313 ReleaseObject(pixdManifest);
314
315 return hr;
316}
317
318// Checks whether at least one of required supported frameworks is installed via the NETFX registry keys.
319static HRESULT CheckSupportedFrameworks(
320 __in LPCWSTR wzConfigPath
321 )
322{
323 HRESULT hr = S_OK;
324 IXMLDOMDocument* pixdManifest = NULL;
325 IXMLDOMNodeList* pNodeList = NULL;
326 IXMLDOMNode* pNode = NULL;
327 DWORD cSupportedFrameworks = 0;
328 LPWSTR sczSupportedFrameworkVersion = NULL;
329 LPWSTR sczFrameworkRegistryKey = NULL;
330 HKEY hkFramework = NULL;
331 DWORD dwFrameworkInstalled = 0;
332 BOOL fUpdatedManifest = FALSE;
333
334 hr = XmlLoadDocumentFromFile(wzConfigPath, &pixdManifest);
335 BalExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath);
336
337 hr = XmlSelectNodes(pixdManifest, L"/configuration/wix.bootstrapper/host/supportedFramework", &pNodeList);
338 BalExitOnFailure(hr, "Failed to select all supportedFramework elements.");
339
340 hr = pNodeList->get_length(reinterpret_cast<long*>(&cSupportedFrameworks));
341 BalExitOnFailure(hr, "Failed to get the supported framework count.");
342
343 if (cSupportedFrameworks)
344 {
345 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL)))
346 {
347 hr = XmlGetAttributeEx(pNode, L"version", &sczSupportedFrameworkVersion);
348 BalExitOnRequiredXmlQueryFailure(hr, "Failed to get supportedFramework/@version.");
349
350 hr = StrAllocFormatted(&sczFrameworkRegistryKey, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\%ls", sczSupportedFrameworkVersion);
351 BalExitOnFailure(hr, "Failed to allocate path to supported framework Install registry key.");
352
353 hr = RegOpen(HKEY_LOCAL_MACHINE, sczFrameworkRegistryKey, KEY_READ, &hkFramework);
354 if (SUCCEEDED(hr))
355 {
356 hr = RegReadNumber(hkFramework, L"Install", &dwFrameworkInstalled);
357 if (dwFrameworkInstalled)
358 {
359 hr = S_OK;
360 break;
361 }
362 }
363
364 ReleaseNullObject(pNode);
365 }
366
367 // If we looped through all the supported frameworks but didn't find anything, ensure we return a failure.
368 if (S_FALSE == hr)
369 {
370 BalExitWithRootFailure(hr, E_NOTFOUND, "Failed to find a supported framework.");
371 }
372
373 hr = UpdateSupportedRuntime(pixdManifest, pNode, &fUpdatedManifest);
374 BalExitOnFailure(hr, "Failed to update supportedRuntime.");
375 }
376 // else no supported frameworks specified, so the startup/supportedRuntime must be enough.
377
378 if (fUpdatedManifest)
379 {
380 hr = XmlSaveDocument(pixdManifest, wzConfigPath);
381 BalExitOnFailure(hr, "Failed to save updated manifest over config file: %ls", wzConfigPath);
382 }
383
384LExit:
385 ReleaseRegKey(hkFramework);
386 ReleaseStr(sczFrameworkRegistryKey);
387 ReleaseStr(sczSupportedFrameworkVersion);
388 ReleaseObject(pNode);
389 ReleaseObject(pNodeList);
390 ReleaseObject(pixdManifest);
391
392 return hr;
393}
394
395// Fixes the supportedRuntime element if necessary.
396static HRESULT UpdateSupportedRuntime(
397 __in IXMLDOMDocument* pixdManifest,
398 __in IXMLDOMNode* pixnSupportedFramework,
399 __out BOOL* pfUpdatedManifest
400 )
401{
402 HRESULT hr = S_OK;
403 LPWSTR sczSupportedRuntimeVersion = NULL;
404 IXMLDOMNode* pixnStartup = NULL;
405 IXMLDOMNode* pixnSupportedRuntime = NULL;
406 BOOL fXmlFound = FALSE;
407
408 *pfUpdatedManifest = FALSE;
409
410 // If the runtime version attribute is not specified, don't update the manifest.
411 hr = XmlGetAttributeEx(pixnSupportedFramework, L"runtimeVersion", &sczSupportedRuntimeVersion);
412 BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get supportedFramework/@runtimeVersion.");
413
414 if (!fXmlFound)
415 {
416 ExitFunction();
417 }
418
419 // Get the startup element. Fail if we can't find it since it'll be necessary to load the
420 // correct runtime.
421 hr = XmlSelectSingleNode(pixdManifest, L"/configuration/startup", &pixnStartup);
422 BalExitOnRequiredXmlQueryFailure(hr, "Failed to get startup element.");
423
424 // Remove any pre-existing supported runtimes because they'll just get in the way and create our new one.
425 hr = XmlRemoveChildren(pixnStartup, L"supportedRuntime");
426 BalExitOnFailure(hr, "Failed to remove pre-existing supportedRuntime elements.");
427
428 hr = XmlCreateChild(pixnStartup, L"supportedRuntime", &pixnSupportedRuntime);
429 BalExitOnFailure(hr, "Failed to create supportedRuntime element.");
430
431 hr = XmlSetAttribute(pixnSupportedRuntime, L"version", sczSupportedRuntimeVersion);
432 BalExitOnFailure(hr, "Failed to set supportedRuntime/@version to '%ls'.", sczSupportedRuntimeVersion);
433
434 *pfUpdatedManifest = TRUE;
435
436LExit:
437 ReleaseObject(pixnSupportedRuntime);
438 ReleaseObject(pixnStartup);
439 ReleaseStr(sczSupportedRuntimeVersion);
440
441 return hr;
442}
443
444// Gets the CLR host and caches it.
445static HRESULT LoadRuntime(
446 __in MBASTATE* pState
447 )
448{
449 HRESULT hr = S_OK;
450 UINT uiMode = 0;
451 HMODULE hModule = NULL;
452 BOOL fFallbackToCorBindToCurrentRuntime = TRUE;
453 CLRCreateInstanceFnPtr pfnCLRCreateInstance = NULL;
454 ICLRMetaHostPolicy* pCLRMetaHostPolicy = NULL;
455 IStream* pCfgStream = NULL;
456 LPWSTR pwzVersion = NULL;
457 DWORD cchVersion = 0;
458 DWORD dwConfigFlags = 0;
459 ICLRRuntimeInfo* pCLRRuntimeInfo = NULL;
460 PFN_CORBINDTOCURRENTRUNTIME pfnCorBindToCurrentRuntime = NULL;
461
462 // Always set the error mode because we will always restore it below.
463 uiMode = ::SetErrorMode(0);
464
465 // Check that the supported framework is installed.
466 hr = CheckSupportedFrameworks(pState->sczConfigPath);
467 BalExitOnFailure(hr, "Failed to find supported framework.");
468
469 // Cache the CLR host to be shutdown later. This can occur on a different thread.
470 // Disable message boxes from being displayed on error and blocking execution.
471 ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
472
473 hr = LoadSystemLibrary(L"mscoree.dll", &hModule);
474 BalExitOnFailure(hr, "Failed to load mscoree.dll");
475
476 pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance"));
477
478 if (pfnCLRCreateInstance)
479 {
480 hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast<LPVOID*>(&pCLRMetaHostPolicy));
481 if (E_NOTIMPL != hr)
482 {
483 BalExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy.");
484
485 fFallbackToCorBindToCurrentRuntime = FALSE;
486 }
487 }
488
489 if (fFallbackToCorBindToCurrentRuntime)
490 {
491 pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime"));
492 BalExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
493
494 hr = pfnCorBindToCurrentRuntime(pState->sczConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
495 BalExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
496 }
497 else
498 {
499
500 hr = SHCreateStreamOnFileEx(pState->sczConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream);
501 BalExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", pState->sczConfigPath);
502
503 hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo));
504 BalExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path.");
505
506 // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL.
507 if (!cchVersion)
508 {
509 hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion);
510 if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
511 {
512 BalExitOnFailure(hr, "Failed to get the length of the CLR version string.");
513 }
514 }
515
516 hr = StrAlloc(&pwzVersion, cchVersion);
517 ExitOnFailure(hr, "Failed to allocate the CLR version string.");
518
519 hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion);
520 ExitOnFailure(hr, "Failed to get the CLR version string.");
521
522 if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion))
523 {
524 hr = VerifyNET4RuntimeIsSupported();
525 BalExitOnFailure(hr, "Found unsupported .NET 4 Runtime.");
526 }
527
528 if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags))
529 {
530 hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
531 BalExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
532 }
533
534 hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
535 BalExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost.");
536 }
537
538 hr = pState->pCLRHost->Start();
539 BalExitOnRootFailure(hr, "Failed to start the CLR host.");
540
541LExit:
542 ReleaseStr(pwzVersion);
543 ReleaseNullObject(pCLRRuntimeInfo);
544 ReleaseNullObject(pCfgStream);
545 ReleaseNullObject(pCLRMetaHostPolicy);
546
547 // Unload the module so it's not in use when we install .NET.
548 if (FAILED(hr))
549 {
550 ::FreeLibrary(hModule);
551 }
552
553 ::SetErrorMode(uiMode); // restore the previous error mode.
554
555 return hr;
556}
557
558// Creates the bootstrapper app and returns it for the engine.
559static HRESULT CreateManagedBootstrapperApplication(
560 __in _AppDomain* pAppDomain,
561 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
562 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
563 )
564{
565 HRESULT hr = S_OK;
566 IBootstrapperApplicationFactory* pAppFactory = NULL;
567
568 hr = CreateManagedBootstrapperApplicationFactory(pAppDomain, &pAppFactory);
569 BalExitOnFailure(hr, "Failed to create the factory to create the bootstrapper application.");
570
571 hr = pAppFactory->Create(pArgs, pResults);
572 BalExitOnFailure(hr, "Failed to create the bootstrapper application.");
573
574LExit:
575 ReleaseNullObject(pAppFactory);
576
577 return hr;
578}
579
580// Creates the app factory to create the managed app in the default AppDomain.
581static HRESULT CreateManagedBootstrapperApplicationFactory(
582 __in _AppDomain* pAppDomain,
583 __out IBootstrapperApplicationFactory** ppAppFactory
584 )
585{
586 HRESULT hr = S_OK;
587 BSTR bstrAssemblyName = NULL;
588 BSTR bstrTypeName = NULL;
589 _ObjectHandle* pObj = NULL;
590 VARIANT vtBAFactory;
591
592 ::VariantInit(&vtBAFactory);
593
594 bstrAssemblyName = ::SysAllocString(MBA_ASSEMBLY_FULL_NAME);
595 BalExitOnNull(bstrAssemblyName, hr, E_OUTOFMEMORY, "Failed to allocate the full assembly name for the bootstrapper application factory.");
596
597 bstrTypeName = ::SysAllocString(MBA_ENTRY_TYPE);
598 BalExitOnNull(bstrTypeName, hr, E_OUTOFMEMORY, "Failed to allocate the full type name for the BA factory.");
599
600 hr = pAppDomain->CreateInstance(bstrAssemblyName, bstrTypeName, &pObj);
601 BalExitOnRootFailure(hr, "Failed to create the BA factory object.");
602
603 hr = pObj->Unwrap(&vtBAFactory);
604 BalExitOnRootFailure(hr, "Failed to unwrap the BA factory object into the host domain.");
605 BalExitOnNull(vtBAFactory.punkVal, hr, E_UNEXPECTED, "The variant did not contain the expected IUnknown pointer.");
606
607 hr = vtBAFactory.punkVal->QueryInterface(__uuidof(IBootstrapperApplicationFactory), reinterpret_cast<LPVOID*>(ppAppFactory));
608 BalExitOnRootFailure(hr, "Failed to query for the bootstrapper app factory interface.");
609
610LExit:
611 ReleaseVariant(vtBAFactory);
612 ReleaseNullObject(pObj);
613 ReleaseBSTR(bstrTypeName);
614 ReleaseBSTR(bstrAssemblyName);
615
616 return hr;
617}
618
619static HRESULT CreatePrerequisiteBA(
620 __in MBASTATE* pState,
621 __in IBootstrapperEngine* pEngine,
622 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
623 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
624 )
625{
626 HRESULT hr = S_OK;
627 LPWSTR sczMbapreqPath = NULL;
628 HMODULE hModule = NULL;
629
630 hr = PathConcat(pState->sczAppBase, L"mbapreq.dll", &sczMbapreqPath);
631 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
632
633 hModule = ::LoadLibraryExW(sczMbapreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
634 BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
635
636 PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
637 BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath);
638
639 hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
640 BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
641
642 pState->hMbapreqModule = hModule;
643 hModule = NULL;
644
645LExit:
646 if (hModule)
647 {
648 ::FreeLibrary(hModule);
649 }
650 ReleaseStr(sczMbapreqPath);
651
652 return hr;
653}
654
655static HRESULT VerifyNET4RuntimeIsSupported(
656 )
657{
658 HRESULT hr = S_OK;
659 OS_VERSION osv = OS_VERSION_UNKNOWN;
660 DWORD dwServicePack = 0;
661 HKEY hKey = NULL;
662 DWORD er = ERROR_SUCCESS;
663 DWORD dwRelease = 0;
664 DWORD cchRelease = sizeof(dwRelease);
665
666 OsGetVersion(&osv, &dwServicePack);
667 if (OS_VERSION_WIN7 == osv && 0 == dwServicePack)
668 {
669 hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full", KEY_QUERY_VALUE, &hKey);
670 if (E_FILENOTFOUND == hr)
671 {
672 ExitFunction1(hr = S_OK);
673 }
674 BalExitOnFailure(hr, "Failed to open registry key for .NET 4.");
675
676 er = ::RegQueryValueExW(hKey, L"Release", NULL, NULL, reinterpret_cast<LPBYTE>(&dwRelease), &cchRelease);
677 if (ERROR_FILE_NOT_FOUND == er)
678 {
679 ExitFunction1(hr = S_OK);
680 }
681 BalExitOnWin32Error(er, hr, "Failed to get Release value.");
682
683 if (NET452_RELEASE <= dwRelease)
684 {
685 hr = E_MBAHOST_NET452_ON_WIN7RTM;
686 }
687 }
688
689LExit:
690 ReleaseRegKey(hKey);
691
692 return hr;
693}