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