// Gets the custom AppDomain for loading managed BA. static HRESULT GetAppDomain( __out _AppDomain **ppAppDomain ) { HRESULT hr = S_OK; ICorRuntimeHost *pCLRHost = NULL; IUnknown *pUnk = NULL; LPWSTR sczAppBase = NULL; LPWSTR sczConfigPath = NULL; IAppDomainSetup *pAppDomainSetup; BSTR bstrAppBase = NULL; BSTR bstrConfigPath = NULL; hr = GetAppBase(&sczAppBase); ExitOnFailure(hr, "Failed to get the host base path."); hr = PathConcat(sczAppBase, L"BootstrapperCore.config", &sczConfigPath); ExitOnFailure(hr, "Failed to get the full path to the application configuration file."); // Check that the supported framework is installed. hr = CheckSupportedFrameworks(sczConfigPath); ExitOnFailure(hr, "Failed to find supported framework."); // Load the CLR. hr = GetCLRHost(sczConfigPath, &pCLRHost); ExitOnFailure(hr, "Failed to create the CLR host."); hr = pCLRHost->Start(); ExitOnRootFailure(hr, "Failed to start the CLR host."); // Create the setup information for a new AppDomain to set the app base and config. hr = pCLRHost->CreateDomainSetup(&pUnk); ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object."); hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup)); ExitOnRootFailure(hr, "Failed to query for the IAppDomainSetup interface."); ReleaseNullObject(pUnk); // Set properties on the AppDomainSetup object. bstrAppBase = ::SysAllocString(sczAppBase); ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup."); hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase); ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup."); bstrConfigPath = ::SysAllocString(sczConfigPath); ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup."); hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath); ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup."); // Create the AppDomain to load the factory type. hr = pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk); ExitOnRootFailure(hr, "Failed to create the MBA AppDomain."); hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(ppAppDomain)); ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface."); LExit: ReleaseBSTR(bstrConfigPath); ReleaseBSTR(bstrAppBase); ReleaseStr(sczConfigPath); ReleaseStr(sczAppBase); ReleaseNullObject(pUnk); ReleaseNullObject(pCLRHost); return hr; }
bool CLRHost::LoadInteropLibrary() { if (!isInitialized) { Log(TEXT("CLRHost::LoadInteropLibrary() Runtime not initialized, examine log for cause")); return false; } HRESULT hr; IUnknown *appDomainSetupUnknown = NULL; IAppDomainSetup *appDomainSetup = NULL; IUnknown *appDomainUnknown = NULL; bstr_t bstrPluginPath(INTEROP_PATH); bstr_t isShadowCopyFiles("true"); bstr_t interopAssemblyDll(INTEROP_ASSEMBLY); bstr_t interopAssemblyName("CLRHost.Interop"); bstr_t assemblyClassName("CLROBS.API"); bstr_t pluginClassName("CLROBS.Plugin"); bstr_t imageSourceTypeName("CLROBS.ImageSource"); bstr_t imageSourceFactoryTypeName("CLROBS.ImageSourceFactory"); bstr_t settingsPaneTypeName("CLROBS.SettingsPane"); bstr_t xElementTypeName("CLROBS.XElement"); SAFEARRAY *constructorArgs = nullptr; SAFEARRAY *apiArgs = nullptr; LONG argIndex; variant_t clrApiPtr((long long)clrApi); variant_t libraryPtr; hr = corRuntimeHost->CreateDomainSetup(&appDomainSetupUnknown); if (FAILED(hr)) { Log(TEXT("ICorRuntimeHost::CreateDomainSetup() failed: 0x%08lx"), hr); goto errorCleanup; } hr = appDomainSetupUnknown->QueryInterface( __uuidof( mscorlib::IAppDomainSetup), (void**)&appDomainSetup); if (FAILED(hr)) { Log(TEXT("IAppDomainSetup::QueryInterface() failed: 0x%08lx"), hr); goto errorCleanup; } hr = appDomainSetup->put_ApplicationBase(bstrPluginPath); if (FAILED(hr)) { Log(TEXT("IAppDomainSetup::put_ApplicationBase(%s) failed: 0x%08lx"), INTEROP_PATH, hr); goto errorCleanup; } hr = appDomainSetup->put_ShadowCopyFiles(isShadowCopyFiles); if (FAILED(hr)) { Log(TEXT("IAppDomainSetup::put_ShadowCopyFiles(%s) failed: 0x%08lx"), TEXT("TRUE"), hr); goto errorCleanup; } hr = appDomainSetup->put_ApplicationName(interopAssemblyDll); if (FAILED(hr)) { Log(TEXT("IAppDomainSetup::put_ApplicationName(%s) failed: 0x%08lx"), INTEROP_ASSEMBLY, hr); goto errorCleanup; } { std::vector<std::wstring> files; GetFilesInDirectory(files, INTEROP_PATH TEXT("*"), FILE_ATTRIBUTE_DIRECTORY); std::wstring combinedPath; for(auto itor = files.begin(); itor < files.end(); itor++) { if (*itor != TEXT(".") && *itor != TEXT("..")) { combinedPath.append(*itor).append(L";"); } } bstr_t combinedPathString(combinedPath.c_str()); hr = appDomainSetup->put_PrivateBinPath(combinedPathString); if (FAILED(hr)) { Log(TEXT("IAppDomainSetup::put_PrivateBinPath(%s) failed: 0x%08lx"), INTEROP_ASSEMBLY, hr); goto errorCleanup; } } hr = corRuntimeHost->CreateDomainEx(interopAssemblyDll, appDomainSetup, nullptr, &appDomainUnknown); if (FAILED(hr)) { Log(TEXT("ICorRuntimeHost::CreateDomainEx(%s, ...) failed: 0x%08lx"), INTEROP_ASSEMBLY, hr); goto errorCleanup; } appDomainSetup->Release(); appDomainSetup = nullptr; hr = appDomainUnknown->QueryInterface(__uuidof( mscorlib::_AppDomain ), (void**)&appDomain); if (FAILED(hr)) { Log(TEXT("IAppDomain::QueryInterface(%s, ...) failed: 0x%08lx"), hr); goto errorCleanup; } appDomainUnknown->Release(); appDomainUnknown = nullptr; Log(TEXT("CLRHost::LoadInteropLibrary() load the assembly %s"), INTEROP_ASSEMBLY_PATH); hr = appDomain->Load_2(interopAssemblyName, &libraryAssembly); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to load the assembly: 0x%08lx"), hr); goto errorCleanup; } hr = libraryAssembly->GetType_2(assemblyClassName, &libraryType); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to get type definition of interop library API class: 0x%08lx"), hr); goto errorCleanup; } hr = libraryAssembly->GetType_2(pluginClassName, &pluginType); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to get type definition of Plugin class: 0x%08lx"), hr); goto errorCleanup; } hr = libraryAssembly->GetType_2(imageSourceTypeName, &imageSourceType); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to get type definition of ImageSource class: 0x%08lx"), hr); goto errorCleanup; } hr = libraryAssembly->GetType_2(imageSourceFactoryTypeName, &imageSourceFactoryType); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to get type definition of ImageSourceFactory class: 0x%08lx"), hr); goto errorCleanup; } hr = libraryAssembly->GetType_2(settingsPaneTypeName, &settingsPaneType); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to get type definition of SettingsPane class: 0x%08lx"), hr); goto errorCleanup; } hr = libraryAssembly->GetType_2(xElementTypeName, &xElementType); if (FAILED(hr)) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to get type definition of XElement class: 0x%08lx"), hr); goto errorCleanup; } apiArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1); argIndex = 0; hr = SafeArrayPutElement(apiArgs, &argIndex, &clrApiPtr); if (FAILED(hr)) { wprintf(L"SafeArrayPutElement failed: 0x%08lx", hr); goto errorCleanup; } hr = libraryAssembly->CreateInstance_3(assemblyClassName, false, BindingFlags_Default, nullptr, apiArgs, nullptr, nullptr, &libraryPtr); if (FAILED(hr) || !libraryPtr.punkVal) { Log(TEXT("CLRHost::LoadInteropLibrary() failed to instantiate our interop library class: 0x%08lx"), hr); goto errorCleanup; } libraryInstance = libraryPtr.punkVal; libraryInstance->AddRef(); SafeArrayDestroy(apiArgs); apiArgs = nullptr; isLibraryLoaded = true; goto success; errorCleanup: if (appDomainSetup) { appDomainSetup->Release(); appDomainSetup = nullptr; } if (appDomainUnknown) { appDomainUnknown->Release(); appDomainUnknown = nullptr; } if (appDomain) { appDomain->Release(); appDomain = nullptr; } if (libraryAssembly) { libraryAssembly->Release(); libraryAssembly = nullptr; } if (libraryType) { libraryType->Release(); libraryType = nullptr; } if (imageSourceType) { imageSourceType->Release(); imageSourceType = nullptr; } if (imageSourceFactoryType) { imageSourceFactoryType->Release(); imageSourceFactoryType = nullptr; } if (settingsPaneType) { settingsPaneType->Release(); settingsPaneType = nullptr; } if (xElementType) { xElementType->Release(); xElementType = nullptr; } if (apiArgs) { SafeArrayDestroy(apiArgs); } return false; success: return true; }
/// <summary> /// Creates a new CLR application domain. /// </summary> /// <param name="hSession">Handle to the installer session, /// used just for logging</param> /// <param name="pHost">Interface to the runtime host where the /// app domain will be created.</param> /// <param name="szName">Name of the app domain to create.</param> /// <param name="szAppBase">Application base directory path, where /// the app domain will look first to load its assemblies.</param> /// <param name="szConfigFile">Optional XML .config file containing any /// configuration for thae app domain.</param> /// <param name="ppAppDomain">Returned app domain interface.</param> /// <returns>True if the app domain was created successfully, false if /// there was some error.</returns> bool CreateAppDomain(MSIHANDLE hSession, ICorRuntimeHost* pHost, const wchar_t* szName, const wchar_t* szAppBase, const wchar_t* szConfigFile, _AppDomain** ppAppDomain) { IUnknown* punkAppDomainSetup = NULL; IAppDomainSetup* pAppDomainSetup = NULL; HRESULT hr = pHost->CreateDomainSetup(&punkAppDomainSetup); if (SUCCEEDED(hr)) { hr = punkAppDomainSetup->QueryInterface(__uuidof(IAppDomainSetup), (void**) &pAppDomainSetup); punkAppDomainSetup->Release(); } if (FAILED(hr)) { Log(hSession, L"Failed to create app domain setup. Error code 0x%X", hr); return false; } const wchar_t* szUrlPrefix = L"file:///"; size_t cchApplicationBase = wcslen(szUrlPrefix) + wcslen(szAppBase); wchar_t* szApplicationBase = (wchar_t*) _alloca((cchApplicationBase + 1) * sizeof(wchar_t)); if (szApplicationBase == NULL) hr = E_OUTOFMEMORY; else { StringCchCopy(szApplicationBase, cchApplicationBase + 1, szUrlPrefix); StringCchCat(szApplicationBase, cchApplicationBase + 1, szAppBase); BSTR bstrApplicationBase = SysAllocString(szApplicationBase); if (bstrApplicationBase == NULL) hr = E_OUTOFMEMORY; else { hr = pAppDomainSetup->put_ApplicationBase(bstrApplicationBase); SysFreeString(bstrApplicationBase); } } if (SUCCEEDED(hr) && szConfigFile != NULL) { BSTR bstrConfigFile = SysAllocString(szConfigFile); if (bstrConfigFile == NULL) hr = E_OUTOFMEMORY; else { hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigFile); SysFreeString(bstrConfigFile); } } if (FAILED(hr)) { Log(hSession, L"Failed to configure app domain setup. Error code 0x%X", hr); pAppDomainSetup->Release(); return false; } IUnknown* punkAppDomain; hr = pHost->CreateDomainEx(szName, pAppDomainSetup, NULL, &punkAppDomain); pAppDomainSetup->Release(); if (SUCCEEDED(hr)) { hr = punkAppDomain->QueryInterface(__uuidof(_AppDomain), (void**) ppAppDomain); punkAppDomain->Release(); } if (FAILED(hr)) { Log(hSession, L"Failed to create app domain. Error code 0x%X", hr); return false; } return true; }