HRESULT GetInstalledClrRuntimes(ICLRMetaHost *clrMetaHost, std::vector<std::wstring>& clrRuntimeList) { HRESULT hr = S_OK; clrRuntimeList.clear(); IEnumUnknown* runtimeEnumerator = nullptr; hr = clrMetaHost->EnumerateInstalledRuntimes(&runtimeEnumerator); if (SUCCEEDED(hr)) { WCHAR currentRuntime[50]; DWORD bufferSize = ARRAYSIZE(currentRuntime); IUnknown* runtime = nullptr; while (runtimeEnumerator->Next(1, &runtime, NULL) == S_OK) { ICLRRuntimeInfo* runtimeInfo = nullptr; hr = runtime->QueryInterface(IID_PPV_ARGS(&runtimeInfo)); if (SUCCEEDED(hr)) { hr = runtimeInfo->GetVersionString(currentRuntime, &bufferSize); if (SUCCEEDED(hr)) { clrRuntimeList.push_back(std::wstring(currentRuntime)); } runtimeInfo->Release(); } runtime->Release(); } runtimeEnumerator->Release(); hr = S_OK; } return hr; }
BOOL CPipeServer::OpenOrAttachToProcess(void) { ICLRMetaHost *pMetaHost; IEnumUnknown *RuntimeEnum; HANDLE ths; MODULEENTRY32 m; HRESULT r; BOOL result=FALSE; CLR_DEBUGGING_VERSION v; v.wStructVersion=0; v.wMajor=4; v.wMinor=0; v.wRevision=30319; v.wBuild=65535; CLRDebugging=NULL; CorDebugProcess=NULL; CorDebugProcess5=NULL; libprovider=NULL; datacallback=NULL; HMODULE hMscoree = LoadLibraryA("mscoree.dll"); CLRCreateInstanceFnPtr CLRCreateInstance; if (hMscoree==NULL) return FALSE; CLRCreateInstance=(CLRCreateInstanceFnPtr)GetProcAddress(hMscoree, "CLRCreateInstance"); if (CLRCreateInstance==NULL) return FALSE; //only 4.0 is supported for now processhandle=OpenProcess(PROCESS_ALL_ACCESS , FALSE, processid); if (processhandle==0) return FALSE; if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost)!=S_OK) return FALSE; if (pMetaHost->EnumerateLoadedRuntimes(processhandle, &RuntimeEnum)==S_OK) { ICLRRuntimeInfo *info; ULONG count=0; RuntimeEnum->Next(1, (IUnknown **)&info, &count); if (count) { result=TRUE; libprovider=new CMyICLRDebuggingLibraryProvider(info); //todo: scan for 4.0 } RuntimeEnum->Release(); } pMetaHost->Release(); if (!result) return FALSE; //no runtimes if (CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (void **)&CLRDebugging)!=S_OK) return FALSE; ths=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processid); if (ths==INVALID_HANDLE_VALUE) return FALSE; ZeroMemory(&m, sizeof(m)); m.dwSize=sizeof(m); if (Module32First(ths, &m)) { datacallback=new CMyIcorDebugDataTarget(processhandle); do { CLR_DEBUGGING_PROCESS_FLAGS flags; r=CLRDebugging->OpenVirtualProcess((ULONG64)m.hModule, datacallback, libprovider, &v, IID_ICorDebugProcess, (IUnknown **)&CorDebugProcess, &v, &flags); if (r==S_OK) { CorDebugProcess->QueryInterface(IID_ICorDebugProcess5, (void **)&CorDebugProcess5); break; } } while (Module32Next(ths, &m)); } CloseHandle(ths); if (r!=S_OK) { #ifdef _DEBUG /* //todo for older (<4.0) c# versions: WCHAR Version[255]; DWORD vlength; ICorDebug *CorDebug; processhandle=OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid); r=GetVersionFromProcess(processhandle, Version, 255, &vlength); r=CreateDebuggingInterfaceFromVersion(CorDebugVersion_2_0, Version, (IUnknown **)&CorDebug); CorDebug->Initialize(); //Cor CMyICorDebugManagedCallback *MyICorDebugManagedCallback; MyICorDebugManagedCallback=new CMyICorDebugManagedCallback(); r=CorDebug->SetManagedHandler((ICorDebugManagedCallback *)MyICorDebugManagedCallback); r=CorDebug->DebugActiveProcess(processid, false, &CorDebugProcess); CorDebugProcess->QueryInterface(IID_ICorDebugProcess5, (void **)&CorDebugProcess5); CorDebug->Initialize(); while (MyICorDebugManagedCallback->attached==FALSE) Sleep(100); //r=CorDebug->GetProcess(processid, &CorDebugProcess); CorDebugProcess->Stop(FALSE); CorDebugProcess->Detach(); CorDebug->Release(); */ #endif if (r!=S_OK) return FALSE; } //still here return TRUE; }
BOOL CPipeServer::OpenOrAttachToProcess(void) { ICLRMetaHost *pMetaHost; IEnumUnknown *RuntimeEnum; HANDLE ths; MODULEENTRY32 m; HRESULT r; BOOL result=FALSE; CLR_DEBUGGING_VERSION v; v.wStructVersion=0; v.wMajor=4; v.wMinor=0; v.wRevision=30319; v.wBuild=65535; CLRDebugging=NULL; CorDebugProcess=NULL; CorDebugProcess5=NULL; libprovider=NULL; datacallback=NULL; HMODULE hMscoree = LoadLibraryA("mscoree.dll"); CLRCreateInstanceFnPtr CLRCreateInstance; if (hMscoree==NULL) return FALSE; CLRCreateInstance=(CLRCreateInstanceFnPtr)GetProcAddress(hMscoree, "CLRCreateInstance"); if (CLRCreateInstance==NULL) return FALSE; //only 4.0 is supported for now processhandle=OpenProcess(PROCESS_ALL_ACCESS , FALSE, processid); if (processhandle==0) return FALSE; if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost)!=S_OK) return FALSE; if (pMetaHost->EnumerateLoadedRuntimes(processhandle, &RuntimeEnum)==S_OK) { ICLRRuntimeInfo *info; ULONG count=0; RuntimeEnum->Next(1, (IUnknown **)&info, &count); if (count) { result=TRUE; libprovider=new CMyICLRDebuggingLibraryProvider(info); //todo: scan for 4.0 } RuntimeEnum->Release(); } pMetaHost->Release(); if (!result) return FALSE; //no runtimes if (CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (void **)&CLRDebugging)!=S_OK) return FALSE; ths=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processid); if (ths==INVALID_HANDLE_VALUE) return FALSE; ZeroMemory(&m, sizeof(m)); m.dwSize=sizeof(m); if (Module32First(ths, &m)) { datacallback=new CMyIcorDebugDataTarget(processhandle); do { CLR_DEBUGGING_PROCESS_FLAGS flags; r=CLRDebugging->OpenVirtualProcess((ULONG64)m.hModule, datacallback, libprovider, &v, IID_ICorDebugProcess, (IUnknown **)&CorDebugProcess, &v, &flags); if (r==S_OK) { CorDebugProcess->QueryInterface(IID_ICorDebugProcess5, (void **)&CorDebugProcess5); break; } } while (Module32Next(ths, &m)); } CloseHandle(ths); if (r!=S_OK) return FALSE; //still here return TRUE; }
void CFrame::UpdateLinks() { // start from scratch m_ChildFrames.clear(); // detect all child frames CComQIPtr<IOleContainer> spContainer = m_Document; if (!!spContainer) { // get an enumerator for the frames IEnumUnknown* pEnumerator; HRESULT hr = spContainer->EnumObjects(OLECONTF_EMBEDDINGS, &pEnumerator); if (SUCCEEDED(hr)) { IUnknown* pUnknown; ULONG uFetched; // enumerate all the frames for (UINT i = 0; S_OK == pEnumerator->Next(1, &pUnknown, &uFetched); i++) { CComQIPtr<IWebBrowser2> spChildBrowser = pUnknown; pUnknown->Release(); if (!!spChildBrowser) { // well done, store child frame CComPtr<IDispatch> spChildDispDoc; CHECK_COM(spChildBrowser->get_Document(&spChildDispDoc), FS(_T("Cannot retrieve document object from %08X"), spChildBrowser)); CComQIPtr<IHTMLDocument2> spChildDoc = spChildDispDoc; // sometimes IE can return NULL spChildDispDoc // // (observed on pages with file download blocking) // test for valid doc if (!!spChildDoc) { CComBSTR url2; CHECK_COM(spChildDoc->get_URL(&url2), FS(_T("Cannot retrieve location URL from %08X"), spChildDoc)); CString URL2 = url2; // it wouldn't be so easy to simply add child document into childs // but IE (maybe) does some reallocation of this document, so we need to do lookup via frameId TFrameId id = m_FrameTable.GetFrameId(spChildDoc, false); // wait for document to load, // there is RISK OF CALLS to other functions !!! //if (id==NULL_FRAME) id = m_FrameTable.GetFrameId(spChildDoc, true); // blocking call if (id==NULL_FRAME) { // TODO: tohle se muze nekdy stat, kdyz se frame jeste nestihne naloadovat pri F5, napriklad gmail.com to dela TRACE_W(FS(_T("Child doc not found for %s !!"), URL2)); } else { m_ChildFrames.push_back(id); } } } } } pEnumerator->Release(); } }
VOID StartAssembly(vector<wstring> const& params) { ICLRMetaHost *pMetaHost = NULL; HRESULT hr; hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); if (SUCCEEDED(hr)) { IEnumUnknown *peunkRuntimes; hr = pMetaHost->EnumerateInstalledRuntimes(&peunkRuntimes); if (SUCCEEDED(hr)) { // *** FINDING LATEST RUNTIME *** IUnknown *punkRuntime; ICLRRuntimeInfo *prtiLatest = NULL; WCHAR szLatestRuntimeVersion[MAX_PATH]; while (peunkRuntimes->Next(1, &punkRuntime, NULL) == S_OK) { ICLRRuntimeInfo *prtiCurrent; hr = punkRuntime->QueryInterface(IID_PPV_ARGS(&prtiCurrent)); if (SUCCEEDED(hr)) { if (!prtiLatest) { hr = prtiCurrent->QueryInterface(IID_PPV_ARGS(&prtiLatest)); if (SUCCEEDED(hr)) { DWORD cch = ARRAYSIZE(szLatestRuntimeVersion); hr = prtiLatest->GetVersionString(szLatestRuntimeVersion, &cch); } } else { WCHAR szCurrentRuntimeVersion[MAX_PATH]; DWORD cch = ARRAYSIZE(szCurrentRuntimeVersion); hr = prtiCurrent->GetVersionString(szCurrentRuntimeVersion, &cch); if (SUCCEEDED(hr)) { if (wcsncmp(szLatestRuntimeVersion, szCurrentRuntimeVersion, cch) < 0) { hr = prtiCurrent->GetVersionString(szLatestRuntimeVersion, &cch); if (SUCCEEDED(hr)) { prtiLatest->Release(); hr = prtiCurrent->QueryInterface(IID_PPV_ARGS(&prtiLatest)); } } } } prtiCurrent->Release(); } punkRuntime->Release(); } peunkRuntimes->Release(); // *** STARTING CLR *** if (SUCCEEDED(hr)) { ICLRRuntimeHost *prth; hr = prtiLatest->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&prth); if (SUCCEEDED(hr)) { hr = prth->Start(); if (SUCCEEDED(hr)) { DWORD dwRet = 0; hr = prth->ExecuteInDefaultAppDomain(params.at(0).c_str(), params.at(1).c_str(), params.at(2).c_str(), params.at(3).c_str(), &dwRet); // hr = 0x80131513 (System.MissingMethodException) if (SUCCEEDED(hr)) { // *** Success *** MessageBox(GetDesktopWindow(), L"Successfully called managed function.", L"Success", MB_OK); } hr = prth->Stop(); } prth->Release(); } } } pMetaHost->Release(); } }
DWORD InitRuntime( ) { DWORD dwRet = 0; HRESULT hr = S_OK; WCHAR ver[255] = {0}; IEnumUnknown *pRuntimes = nullptr; // MetaHost instance hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pClrHost); if(!SUCCEEDED(hr)) return 1; // Get available runtimes hr = pClrHost->EnumerateInstalledRuntimes(&pRuntimes); if(!SUCCEEDED(hr)) return 1; // Search for target runtime needed for managed dll to run while(pRuntimes->Next(1, (IUnknown**)&pRuntimeinfo, &dwRet) == S_OK && dwRet > 0) { dwRet = ARRAYSIZE(ver); hr = pRuntimeinfo->GetVersionString(ver, &dwRet); // ver - string "vA.B[.X]" if(ver[1] == TARGET_RUNTIME) break; pRuntimeinfo->Release(); pRuntimeinfo = nullptr; } // Found runtime if(pRuntimeinfo != nullptr) { BOOL started = FALSE; // Get CLR hosting interface hr = pRuntimeinfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pRuntimeHost); if(!SUCCEEDED(hr)) return 1; // Check if runtime is already running hr = pRuntimeinfo->IsStarted(&started, &dwRet); if(!SUCCEEDED(hr)) return 1; // Start .NET runtime if needed if(started == FALSE) { hr = pRuntimeHost->Start(); if(!SUCCEEDED(hr)) return 1; } } if(pRuntimes) pRuntimes->Release(); return 0; }
STDAPI AttachProfiler(int pid, LPCWSTR wszTargetVersion, LPCWSTR wszProfilerPath, ProfConfig * pProfConfig, BOOL fConsoleMode) { HMODULE hModule = NULL; LPVOID pvClientData = NULL; DWORD cbClientData = 0; HRESULT hr; ICLRMetaHost * pMetaHost = NULL; IEnumUnknown * pEnum = NULL; IUnknown * pUnk = NULL; ICLRRuntimeInfo * pRuntime = NULL; ICLRProfiling * pProfiling = NULL; g_fConsoleMode = fConsoleMode; DWORD dwProfileeProcessID = (DWORD) pid; CLSID clsidProfiler; CLSIDFromString(PROFILER_GUID_WCHAR, &clsidProfiler); DWORD dwMillisecondsMax = pProfConfig->dwDefaultTimeoutMs; bool fCLRFound = false; //--------------------------------------------------------------------------------------- // GET AND CALL API //--------------------------------------------------------------------------------------- hModule = LoadLibrary(L"mscoree.dll"); if (hModule == NULL) { Log(L"LoadLibrary mscoree.dll failed. hr=0x%x.\n", hr = HRESULT_FROM_WIN32(GetLastError())); goto Cleanup; } // Note: This is the ONLY C export we need out of mscoree.dll. This enables us to // get started with the metahost interfaces, and it's all COM from that point // forward. CLRCreateInstanceFnPtr pfnCreateInstance = (CLRCreateInstanceFnPtr)GetProcAddress(hModule, "CLRCreateInstance"); if (pfnCreateInstance == NULL) { Log(L"GetProcAddress on 'CLRCreateInstance' failed. hr=0x%x.\n", hr = HRESULT_FROM_WIN32(GetLastError())); goto Cleanup; } hr = (*pfnCreateInstance)(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID *)&pMetaHost); if (FAILED(hr)) { Log(L"CLRCreateInstance IID_ICLRMetaHost' failed. hr=0x%x.\n", hr); goto Cleanup; } // Cross-user attach requires the SE_DEBUG_NAME privilege, so attempt to enable it // now. Even if the privilege is not found, the CLRProfiler still continues to attach the target process. // We'll just fail later on if we do try to attach to a different-user target process. HRESULT hrEnableDebugPrivilege = EnableDebugPrivilege(); HANDLE hndProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProfileeProcessID); if (hndProcess == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); //If EnableDebugPrivilege is not successful, let the customer know running CLRProfiler as administrator may solve the problem. if (hrEnableDebugPrivilege == E_FAIL) { Log(L"CLRProfiler can not open the target process %d (error: 0x%x), probably because CLRProfiler could not enable the debug privilege (error: 0x%x). \n" L"Please run the CLRProfiler as administrator and try again.", dwProfileeProcessID, hr, hrEnableDebugPrivilege); } else { Log(L"OpenProcess failed. hr=0x%x.\n", hr); } goto Cleanup; } // One process may have multiple versions of the CLR loaded. Grab an enumerator to // get back all the versions currently loaded. hr = pMetaHost->EnumerateLoadedRuntimes(hndProcess, &pEnum); if (FAILED(hr)) { Log(L"EnumerateLoadedRuntimes' failed. hr=0x%x.\n", hr); goto Cleanup; } while (pEnum->Next(1, &pUnk, NULL) == S_OK) { hr = pUnk->QueryInterface(IID_ICLRRuntimeInfo, (LPVOID *) &pRuntime); if (FAILED(hr)) goto LoopCleanup; WCHAR wszVersion[30]; DWORD cchVersion = ARRAY_LEN(wszVersion); hr = pRuntime->GetVersionString(wszVersion, &cchVersion); if (SUCCEEDED(hr) && _wcsnicmp(wszVersion, wszTargetVersion, min(cchVersion, wcslen(wszTargetVersion))) == 0) { fCLRFound = true; hr = pRuntime->GetInterface(CLSID_CLRProfiling, IID_ICLRProfiling, (LPVOID *)&pProfiling); if (FAILED(hr)) { Log(L"Can not get the ICLRProfiling interface. Error: 0x%x.", hr); break; } // Here it is! Attach the profiler! // The profilee may not have access to the profler dll // Give it a try. hr = pProfiling->AttachProfiler(dwProfileeProcessID, dwMillisecondsMax, &clsidProfiler, wszProfilerPath, (LPVOID)pProfConfig, sizeof(*pProfConfig)); if(FAILED(hr)) { if (hr == ERROR_TIMEOUT)//ERROR_TIMEOUT { Log(L"CLRProfiler timed out to attach to the process.\nPlease check the event log to find out whether the attach succeeded or failed."); } else if (hr == COR_E_UNAUTHORIZEDACCESS)//0x80070005 { Log(L"CLRProfiler failed to attach to the process with error code 0x80070005(COR_E_UNAUTHORIZEDACCESS).\n" L"This may occur if the target process(%d) does not have access to ProfilerOBJ.dll or the directory in which ProfilerOBJ.dll is located.\n" L"Please check event log for more details.", pid); } else if (hr == CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE) { Log(L"Profiler initialization failed because the target process is running with concurrent GC enabled. Either\n" L" 1) turn off concurrent GC in the application's configuration file before launching the application, or\n" L" 2) simply start the application from CLRProfiler rather than trying to attach CLRProfiler after the application has already started."); } else { Log(L"Attach Profiler Failed 0x%x, please check the event log for more details.", hr); } } pProfiling->Release(); pProfiling = NULL; break; } LoopCleanup: if (pRuntime != NULL) { pRuntime->Release(); pRuntime = NULL; } if (pUnk != NULL) { pUnk->Release(); pUnk = NULL; } } if (fCLRFound == false) { Log(L"No CLR Version %s is loaded into the target process.", wszTargetVersion); hr = E_FAIL; } Cleanup: if (pRuntime != NULL) { pRuntime->Release(); pRuntime = NULL; } if (pUnk != NULL) { pUnk->Release(); pUnk = NULL; } if (pEnum != NULL) { pEnum->Release(); pEnum = NULL; } if (pMetaHost != NULL) { pMetaHost->Release(); pMetaHost = NULL; } if (hModule != NULL) { FreeLibrary(hModule); hModule = NULL; } return hr; }