static void InitializeClr(void) { ICorRuntimeHost *runtimeHost; if (FAILED(CorBindToRuntimeEx(NULL, NULL, STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (void **)&runtimeHost))) { return; } runtimeHost->Start(); IUnknownPtr punkAppDomain = NULL; runtimeHost->GetDefaultDomain(&punkAppDomain); punkAppDomain->QueryInterface(__uuidof(mscorlib::_AppDomain), (void **)&l_AppDomain); runtimeHost->Release(); }
DWORD initialize_dotnet_host() { HRESULT hr = S_OK; ICLRMetaHost* clrMetaHost = NULL; ICLRRuntimeInfo* clrRuntimeInfo = NULL; ICorRuntimeHost* clrCorRuntimeHost = NULL; IUnknownPtr clrAppDomain = NULL; _AppDomainPtr clrAppDomainInterface = NULL; _AssemblyPtr clrPowershellAssembly = NULL; _TypePtr clrPowershellType = NULL; SAFEARRAY* clrByteArray = NULL; HMODULE hMsCoree = NULL; do { dprintf("[PSH] Locating CLR instance ..."); hMsCoree = LoadLibraryA("mscoree.dll"); if (hMsCoree == NULL) { hr = (HRESULT)GetLastError(); dprintf("[PSH] Failed to load mscoree, .NET probably isn't installed. 0x%x", hr); break; } pClrCreateInstance clrCreateInstance = (pClrCreateInstance)GetProcAddress(hMsCoree, "CLRCreateInstance"); if (clrCreateInstance != NULL) { dprintf("[PSH] .NET 4 method in use"); if (FAILED(hr = clrCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&clrMetaHost)))) { dprintf("[PSH] Failed to create instace of the CLR metahost 0x%x", hr); break; } dprintf("[PSH] Getting a reference to the .NET runtime"); if (FAILED(hr = clrMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&clrRuntimeInfo)))) { dprintf("[PSH] Failed to get runtime v2.0.50727 instance 0x%x", hr); if (FAILED(hr = clrMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&clrRuntimeInfo)))) { dprintf("[PSH] Failed to get runtime v4.0.30319 instance 0x%x", hr); break; } } dprintf("[PSH] Determining loadablility"); BOOL loadable = FALSE; if (FAILED(hr = clrRuntimeInfo->IsLoadable(&loadable))) { dprintf("[PSH] Unable to determine of runtime is loadable 0x%x", hr); break; } if (!loadable) { dprintf("[PSH] Chosen runtime isn't loadable, exiting."); break; } dprintf("[PSH] Instantiating the COR runtime host"); hr = clrRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost)); if (FAILED(hr)) { dprintf("[PSH] Unable to get a reference to the COR runtime host 0x%x", hr); break; } } else { dprintf("[PSH] .NET 4 method is missing, attempting to locate .NEt 2 method"); pCorBindToRuntime corBindToRuntime = (pCorBindToRuntime)GetProcAddress(hMsCoree, "CorBindToRuntime"); if (corBindToRuntime == NULL) { dprintf("[PSH] Unable to find .NET clr instance loader"); hr = E_NOTIMPL; break; } if (FAILED(hr = corBindToRuntime(L"v2.0.50727", L"wks", CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost)))) { dprintf("[PSH] Unable to bind to .NET 2 runtime host: 0x%x", hr); break; } } dprintf("[PSH] Starting the COR runtime host"); if (FAILED(hr = clrCorRuntimeHost->Start())) { dprintf("[PSH] Unable to start the COR runtime host 0x%x", hr); break; } dprintf("[PSH] Getting a ref to the app domain"); if (FAILED(hr = clrCorRuntimeHost->GetDefaultDomain(&clrAppDomain))) { dprintf("[PSH] Unable to get the app domain 0x%x", hr); break; } dprintf("[PSH] Getting a ref to the app domain interface"); if (FAILED(hr = clrAppDomain->QueryInterface(IID_PPV_ARGS(&clrAppDomainInterface)))) { dprintf("[PSH] Unable to get the app domain interface 0x%x", hr); break; } dprintf("[PSH] CLR app domain ready to run, now loading the powershell runner"); SAFEARRAYBOUND bounds[1]; bounds[0].cElements = PSHRUNNER_DLL_LEN; bounds[0].lLbound = 0; clrByteArray = SafeArrayCreate(VT_UI1, 1, bounds); if (clrByteArray == NULL) { dprintf("[PSH] Failed to create a usable safe array"); hr = ERROR_OUTOFMEMORY; break; } if (FAILED(hr = SafeArrayLock(clrByteArray))) { dprintf("[PSH] Safe array lock failed 0x%x", hr); break; } memcpy(clrByteArray->pvData, PowerShellRunnerDll, PSHRUNNER_DLL_LEN); SafeArrayUnlock(clrByteArray); if (FAILED(hr = clrAppDomainInterface->Load_3(clrByteArray, &clrPowershellAssembly))) { dprintf("[PSH] Failed to load the powershell runner assembly 0x%x", hr); break; } dprintf("[PSH] Loading the type from memory"); _bstr_t pshClassName("MSF.Powershell.Runner"); if (FAILED(hr = clrPowershellAssembly->GetType_2(pshClassName, &clrPowershellType))) { dprintf("[PSH] Unable to locate the powershell class type 0x%x", hr); break; } dprintf("[PSH] Runtime has been initialized successfully"); } while(0); if (clrByteArray != NULL) { SafeArrayDestroy(clrByteArray); } if (FAILED(hr)) { SAFE_RELEASE(clrPowershellAssembly); SAFE_RELEASE(clrAppDomainInterface); SAFE_RELEASE(clrCorRuntimeHost); SAFE_RELEASE(clrRuntimeInfo); SAFE_RELEASE(clrMetaHost); return (DWORD)hr; } gClrMetaHost = clrMetaHost; gClrRuntimeInfo = clrRuntimeInfo; gClrCorRuntimeHost = clrCorRuntimeHost; gClrAppDomainInterface = clrAppDomainInterface; gClrAppDomain = clrAppDomain; gClrPowershellAssembly = clrPowershellAssembly; gClrPowershellType = clrPowershellType; return ERROR_SUCCESS; }
// 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; }
/// <summary> /// Binds to the CLR after determining the appropriate version. /// </summary> /// <param name="hSession">Handle to the installer session, /// used just for logging.</param> /// <param name="version">Specific version of the CLR to load. /// If null, then the config file and/or primary assembly are /// used to determine the version.</param> /// <param name="szConfigFile">XML .config file which may contain /// a startup section to direct which version of the CLR to use. /// May be NULL.</param> /// <param name="szPrimaryAssembly">Assembly to be used to determine /// the version of the CLR in the absence of other configuration. /// May be NULL.</param> /// <param name="ppHost">Returned runtime host interface.</param> /// <returns>True if the CLR was loaded successfully, false if /// there was some error.</returns> /// <remarks> /// If szPrimaryAssembly is NULL and szConfigFile is also NULL or /// does not contain any version configuration, the CLR will not be loaded. /// </remarks> bool LoadCLR(MSIHANDLE hSession, const wchar_t* szVersion, const wchar_t* szConfigFile, const wchar_t* szPrimaryAssembly, ICorRuntimeHost** ppHost) { typedef HRESULT (__stdcall *PGetRequestedRuntimeInfo)(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWSTR pConfigurationFile, DWORD startupFlags, DWORD runtimeInfoFlags, LPWSTR pDirectory, DWORD dwDirectory, DWORD *dwDirectoryLength, LPWSTR pVersion, DWORD cchBuffer, DWORD* dwlength); typedef HRESULT (__stdcall *PCorBindToRuntimeEx)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); HMODULE hmodMscoree = LoadLibrary(L"mscoree.dll"); if (hmodMscoree == NULL) { Log(hSession, L"Failed to load mscoree.dll (Error code %d). This custom action " L"requires the .NET Framework to be installed.", GetLastError()); return false; } PGetRequestedRuntimeInfo pGetRequestedRuntimeInfo = (PGetRequestedRuntimeInfo) GetProcAddress(hmodMscoree, "GetRequestedRuntimeInfo"); PCorBindToRuntimeEx pCorBindToRuntimeEx = (PCorBindToRuntimeEx) GetProcAddress(hmodMscoree, "CorBindToRuntimeEx"); if (pGetRequestedRuntimeInfo == NULL || pCorBindToRuntimeEx == NULL) { Log(hSession, L"Failed to locate functions in mscoree.dll (Error code %d). This custom action " L"requires the .NET Framework to be installed.", GetLastError()); FreeLibrary(hmodMscoree); return false; } wchar_t szClrVersion[20]; HRESULT hr; if (szVersion != NULL && szVersion[0] != L'\0') { wcsncpy_s(szClrVersion, 20, szVersion, 20); } else { wchar_t szVersionDir[MAX_PATH]; hr = pGetRequestedRuntimeInfo(szPrimaryAssembly, NULL, szConfigFile, 0, 0, szVersionDir, MAX_PATH, NULL, szClrVersion, 20, NULL); if (FAILED(hr)) { Log(hSession, L"Failed to get requested CLR info. Error code 0x%x", hr); Log(hSession, L"Ensure that the proper version of the .NET Framework is installed, or " L"that there is a matching supportedRuntime element in CustomAction.config. " L"If you are binding to .NET 4 or greater add " L"useLegacyV2RuntimeActivationPolicy=true to the <startup> element."); FreeLibrary(hmodMscoree); return false; } } Log(hSession, L"Binding to CLR version %s", szClrVersion); ICorRuntimeHost* pHost; hr = pCorBindToRuntimeEx(szClrVersion, NULL, STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (void**) &pHost); if (FAILED(hr)) { Log(hSession, L"Failed to bind to the CLR. Error code 0x%X", hr); FreeLibrary(hmodMscoree); return false; } hr = pHost->Start(); if (FAILED(hr)) { Log(hSession, L"Failed to start the CLR. Error code 0x%X", hr); pHost->Release(); FreeLibrary(hmodMscoree); return false; } *ppHost = pHost; FreeLibrary(hmodMscoree); return true; }
unsigned __stdcall ThreadProc(void *pArg) { RuntimeAndApp *pContext = (RuntimeAndApp *)pArg; HRESULT hr; #define IfFailGoMsg(MSG) \ if (FAILED(hr)) \ { \ printf("Runtime %d (%S): " MSG " (%x)\n", \ pContext->m_dwRuntimeNo, \ pContext->m_pwzRuntimeVer, \ hr); \ goto lExit; \ } ICLRRuntimeHost *pHost_V2 = NULL; ICorRuntimeHost *pHost = NULL; IUnknown *pUnk = NULL; mscorlib::_AppDomain *pAD = NULL; // Get ICorRuntimeHost to execute the app. hr = pContext->m_pRuntime->GetInterface( CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (LPVOID *)&pHost); IfFailGoMsg("Failed to load the runtime"); // Also try to get ICLRRuntimeHost which has a useful Stop method. (ICorRuntimeHost::Stop is empty.) if (SUCCEEDED(pContext->m_pRuntime->GetInterface( CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pHost_V2))) { hr = pHost_V2->Start(); IfFailGoMsg("Failed to start ICLRRuntimeHost"); } ReportSyncPoint(SyncPointRuntimeStart, pContext->m_dwRuntimeNo); hr = pHost->Start(); IfFailGoMsg("Failed to start ICorRuntimeHost"); if(g_options.m_bUseDefaultAppDomain) { hr = pHost->GetDefaultDomain(&pUnk); IfFailGoMsg("Failed to get default domain"); } else { hr = pHost->CreateDomain(L"AD2",NULL,&pUnk); IfFailGoMsg("Failed to create AppDomain"); } hr = pUnk->QueryInterface(__uuidof(mscorlib::_AppDomain), (LPVOID *)&pAD); IfFailGoMsg("Failed to QI for _AppDomain"); BSTR bstrPath = SysAllocString(pContext->m_pwzAppPath); SAFEARRAY *rgArgs = CreateArgList(pContext->m_pwzAppArgs); ReportSyncPoint(SyncPointApplicationStart, pContext->m_dwRuntimeNo); if (g_options.m_bUseLoadByName) { hr = ExecuteAssemblyByName(pAD, bstrPath, rgArgs, &pContext->m_dwRetCode); } else { hr = pAD->ExecuteAssembly_3(bstrPath, NULL, rgArgs, &pContext->m_dwRetCode); } if (hr == COR_E_NEWER_RUNTIME) { IfFailGoMsg("Failed to execute assembly\nWas it built by a compiler that is newer than this runtime?"); } else { // we don't know whether the error comes from the runtime (failed to execute assembly) or // the assembly actually ran and threw an unhandled exception that was converted to the HR IfFailGoMsg("ExecuteAssembly returned an error code"); } SysFreeString(bstrPath); SafeArrayDestroy(rgArgs); if(!g_options.m_bUseDefaultAppDomain) { ReportSyncPoint(SyncPointAppDomainUnload, pContext->m_dwRuntimeNo); hr = pHost->UnloadDomain(pAD); IfFailGoMsg("Failed to unload AppDomain"); } pAD->Release(); pAD = NULL; pUnk->Release(); pUnk = NULL; hr = pHost->Stop(); IfFailGoMsg("Failed to stop ICorRuntimeHost"); if (pHost_V2 != NULL) { hr = pHost_V2->Stop(); IfFailGoMsg("Failed to stop ICLRRuntimeHost"); pHost_V2 = NULL; } lExit: if (pHost_V2 != NULL) pHost_V2->Release(); if (pAD != NULL) pAD->Release(); if (pUnk != NULL) pUnk->Release(); if (pHost != NULL) pHost->Release(); if (g_options.m_bRunMultithreaded) { // make sure we don't deadlock the other thread // this is also needed if the value of g_options.m_dwADUnloadOrder is SameOrder or ReverseOrder // since one of the threads will be waiting for the other one to Unload the AppDomain. SetEvent(g_rhndEvents[pContext->m_dwRuntimeNo - 1]); _endthreadex(0); } return 0; #undef IfFailGoMsg }
int __stdcall invokeCLR( WCHAR* wszApplication){ //Initializes the COM library CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ICorRuntimeHost* pHost = NULL; IUnknown* pAppDomainThunk = NULL; _AppDomain* pAppDomain = NULL; long lReturn = 0; // Load CLR into the process HRESULT hr = CorBindToRuntimeEx(NULL,NULL,0,CLSID_CorRuntimeHost,IID_ICorRuntimeHost,(VOID**)&pHost); if(!FAILED(hr)) { // Start the CLR hr = pHost->Start(); if(!FAILED(hr)) { // Get the _AppDomain interface hr = pHost->GetDefaultDomain(&pAppDomainThunk); if(!FAILED(hr)) { hr = pAppDomainThunk->QueryInterface(__uuidof(_AppDomain), (void**)&pAppDomain); if(!FAILED(hr)) { // Execute assembly hr = pAppDomain->ExecuteAssembly_2(_bstr_t(wszApplication), &lReturn); if (FAILED(hr)) { printf("_AppDomain::ExecuteAssembly_2 failed with hr=0x%x.\n", hr); lReturn = -1; } }else{ printf("Can't get System::_AppDomain interface\n"); lReturn = -2; } }else{ printf("ICorRuntimeHost->GetDefaultDomain failed with hr=0x%x.\n", hr); lReturn = -3; } }else{ printf("ICorRuntimeHost->Start failed with hr=0x%x.\n", hr); lReturn = -4; } }else{ printf("CorBindToRuntimeHost failed with hr=0x%x.\n", hr); lReturn = -5; } // print the error message description if needed if(FAILED(hr)){ LPVOID lpMsgBuf = NULL; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); if(lpMsgBuf != NULL) printf("Message:%s\n",lpMsgBuf); else printf("No translation of 0x%x\n",hr); } // close COM library CoUninitialize(); return lReturn; }
int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr; ICLRMetaHost *pMetaHost = NULL; ICLRRuntimeInfo *pRuntimeInfo = NULL; ICorRuntimeHost *pCorRuntimeHost = NULL; IUnknownPtr spAppDomainThunk = NULL; _AppDomainPtr spDefaultAppDomain = NULL; // The .NET assembly to load. bstr_t bstrAssemblyName("PowerShellRunner"); _AssemblyPtr spAssembly = NULL; // The .NET class to instantiate. bstr_t bstrClassName("PowerShellRunner.PowerShellRunner"); _TypePtr spType = NULL; // Start the runtime hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)); if (FAILED(hr)) { wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr); goto Cleanup; } hr = pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo)); if (FAILED(hr)) { wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr); goto Cleanup; } // Check if the specified runtime can be loaded into the process. BOOL fLoadable; hr = pRuntimeInfo->IsLoadable(&fLoadable); if (FAILED(hr)) { wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr); goto Cleanup; } if (!fLoadable) { wprintf(L".NET runtime v2.0.50727 cannot be loaded\n"); goto Cleanup; } // Load the CLR into the current process and return a runtime interface hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&pCorRuntimeHost)); if (FAILED(hr)) { wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr); goto Cleanup; } // Start the CLR. hr = pCorRuntimeHost->Start(); if (FAILED(hr)) { wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr); goto Cleanup; } // Get a pointer to the default AppDomain in the CLR. hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk); if (FAILED(hr)) { wprintf(L"ICorRuntimeHost::GetDefaultDomain failed w/hr 0x%08lx\n", hr); goto Cleanup; } hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain)); if (FAILED(hr)) { wprintf(L"Failed to get default AppDomain w/hr 0x%08lx\n", hr); goto Cleanup; } // Load the .NET assembly. // (Option 1) Load it from disk - usefully when debugging the PowerShellRunner app (you'll have to copy the DLL into the same directory as the exe) //hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly); // (Option 2) Load the assembly from memory SAFEARRAYBOUND bounds[1]; bounds[0].cElements = PowerShellRunner_dll_len; bounds[0].lLbound = 0; SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds); SafeArrayLock(arr); memcpy(arr->pvData, PowerShellRunner_dll, PowerShellRunner_dll_len); SafeArrayUnlock(arr); hr = spDefaultAppDomain->Load_3(arr, &spAssembly); if (FAILED(hr)) { wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr); goto Cleanup; } // Get the Type of PowerShellRunner. hr = spAssembly->GetType_2(bstrClassName, &spType); if (FAILED(hr)) { wprintf(L"Failed to get the Type interface w/hr 0x%08lx\n", hr); goto Cleanup; } // Call the static method of the class wchar_t* argument = L"Get-Process\n\ #This is a PowerShell Comment\n\ Write-Host \"`n`n******* The next command is going to throw an exception. This is planned *********`n`n\"\n\ Read-Host\n"; InvokeMethod(spType, L"InvokePS", argument); Cleanup: if (pMetaHost) { pMetaHost->Release(); pMetaHost = NULL; } if (pRuntimeInfo) { pRuntimeInfo->Release(); pRuntimeInfo = NULL; } if (pCorRuntimeHost) { pCorRuntimeHost->Release(); pCorRuntimeHost = NULL; } return 0; }