// static void CordbAssembly::DbgAssertAssemblyDeletedCallback(VMPTR_DomainAssembly vmDomainAssembly, void * pUserData) { CordbAssembly * pThis = reinterpret_cast<CordbAssembly * >(pUserData); INTERNAL_DAC_CALLBACK(pThis->GetProcess()); VMPTR_DomainAssembly vmAssemblyDeleted = pThis->m_vmDomainAssembly; CONSISTENCY_CHECK_MSGF((vmAssemblyDeleted != vmDomainAssembly), ("An Assembly Unload event was sent, but the assembly still shows up in the enumeration.\n vmAssemblyDeleted=%p\n", VmPtrToCookie(vmAssemblyDeleted))); }
// Constructor CorpubProcess::CorpubProcess(DWORD dwProcessId, bool fManaged, HANDLE hProcess, HANDLE hMutex, AppDomainEnumerationIPCBlock *pAD, #if !defined(FEATURE_DBGIPC_TRANSPORT_DI) IPCReaderInterface *pIPCReader, #endif // !FEATURE_DBGIPC_TRANSPORT_DI FPGetModuleFileNameEx * fpGetModuleFileNameEx) : CordbCommonBase(0, enumCorpubProcess), m_dwProcessId(dwProcessId), m_fIsManaged(fManaged), m_hProcess(hProcess), m_hMutex(hMutex), m_AppDomainCB(pAD), #if !defined(FEATURE_DBGIPC_TRANSPORT_DI) m_pIPCReader(pIPCReader), #endif // !FEATURE_DBGIPC_TRANSPORT_DI m_pNext(NULL) { { // First try to get the process name from the OS. That can't be spoofed by badly formed IPC block. // psapi!GetModuleFileNameExW can get that, but it's not available on all platforms so we // need to load it dynamically. if (fpGetModuleFileNameEx != NULL) { // MSDN is very confused about whether the lenght is in bytes (MSDN 2002) or chars (MSDN 2004). // We err on the safe side by having buffer that's twice as large, and ignoring // the units on the return value. WCHAR szName[MAX_LONGPATH * sizeof(WCHAR)]; DWORD lenInCharsOrBytes = MAX_LONGPATH*sizeof(WCHAR); // Pass NULL module handle to get "Main Module", which will give us the process name. DWORD ret = (*fpGetModuleFileNameEx) (hProcess, NULL, szName, lenInCharsOrBytes); if (ret > 0) { // Recompute string length because we don't know if 'ret' is in bytes or char. SIZE_T len = wcslen(szName) + 1; m_szProcessName = new (nothrow) WCHAR[len]; if (m_szProcessName != NULL) { wcscpy_s(m_szProcessName, len, szName); goto exit; } } } // This is a security feature on WinXp + above, so make sure it worked there. CONSISTENCY_CHECK_MSGF(FALSE, ("On XP/2k03 OSes + above, we should have been able to get\n" "the module name from psapi!GetModuleFileNameEx. fp=0x%p\n.", fpGetModuleFileNameEx)); } // We couldn't get it from the OS, so fallthrough to getting it from the IPC block. // Fetch the process name from the AppDomainIPCBlock _ASSERTE (pAD->m_szProcessName != NULL); if (pAD->m_szProcessName == NULL) m_szProcessName = NULL; else { SIZE_T nBytesRead; _ASSERTE(pAD->m_iProcessNameLengthInBytes > 0); // Note: this assumes we're reading the null terminator from // the IPC block. m_szProcessName = (WCHAR*) new (nothrow) char[pAD->m_iProcessNameLengthInBytes]; if (m_szProcessName == NULL) { LOG((LF_CORDB, LL_INFO1000, "CP::CP: Failed to allocate memory for ProcessName.\n")); goto exit; } BOOL bSucc = ReadProcessMemory(hProcess, pAD->m_szProcessName, m_szProcessName, pAD->m_iProcessNameLengthInBytes, &nBytesRead); if ((bSucc == 0) || (nBytesRead != (SIZE_T)pAD->m_iProcessNameLengthInBytes)) { // The EE may have done a rude exit LOG((LF_CORDB, LL_INFO1000, "CP::EAD: ReadProcessMemory (ProcessName) failed.\n")); } } exit: ; }