// For coresys we need to look for an API in some apiset dll on win8 if we can't find it // in the traditional dll. HINSTANCE LoadDllForAPI(WCHAR* dllTraditional, WCHAR* dllApiSet) { HINSTANCE hinst = WszLoadLibrary(dllTraditional); if (!hinst) { if(RunningOnWin8()) hinst = WszLoadLibrary(dllApiSet); } return hinst; }
// Detach HRESULT WindowsNativePipeline::DebugActiveProcessStop(DWORD processId) { #if !defined(FEATURE_CORESYSTEM) // Late-bind to DebugActiveProcessStop since it's WinXP and above only HModuleHolder hKernel32; hKernel32 = WszLoadLibrary(W("kernel32")); if (hKernel32 == NULL) return HRESULT_FROM_GetLastError(); typedef BOOL (*DebugActiveProcessStopSig) (DWORD); DebugActiveProcessStopSig pDebugActiveProcessStop = reinterpret_cast<DebugActiveProcessStopSig>(GetProcAddress(hKernel32, "DebugActiveProcessStop")); // Win2K will fail here - can't find DebugActiveProcessStop if (pDebugActiveProcessStop == NULL) return HRESULT_FROM_GetLastError(); // Ok, the API exists, call it if (!pDebugActiveProcessStop(processId)) { // Detach itself failed return HRESULT_FROM_GetLastError(); } #else // The API exists, call it if (!::DebugActiveProcessStop(processId)) { // Detach itself failed return HRESULT_FROM_GetLastError(); } #endif return S_OK; }
// Determine (if possible) whether a debugger is attached to the target process HRESULT WindowsNativePipeline::IsRemoteDebuggerPresent(DWORD processId, BOOL* pfDebuggerPresent) { #if !defined(FEATURE_CORESYSTEM) // Get a process handle for the process ID. HandleHolder hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); if (hProc == NULL) return HRESULT_FROM_GetLastError(); // Delay-bind to CheckRemoteDebuggerPresent - WinXP SP1 and above only HModuleHolder hKernel32; hKernel32 = WszLoadLibrary(W("kernel32")); if (hKernel32 == NULL) return HRESULT_FROM_GetLastError(); typedef BOOL (*CheckRemoteDebuggerPresentSig) (HANDLE, PBOOL); CheckRemoteDebuggerPresentSig pCheckRemoteDebuggerPresent = reinterpret_cast<CheckRemoteDebuggerPresentSig>(GetProcAddress(hKernel32, "CheckRemoteDebuggerPresent")); if (pCheckRemoteDebuggerPresent == NULL) return HRESULT_FROM_GetLastError(); // API exists - call it if (!pCheckRemoteDebuggerPresent(hProc, pfDebuggerPresent)) return HRESULT_FROM_GetLastError(); return S_OK; #else //CoreSystem doesn't have this API return E_FAIL; #endif }
// Enforces the bit set in code:WindowsNativePipeline::DebugSetProcessKillOnExit void WindowsNativePipeline::UpdateDebugSetProcessKillOnExit() { #if !defined(FEATURE_CORESYSTEM) // Late bind to DebugSetProcessKillOnExit - WinXP and above only HModuleHolder hKernel32; hKernel32 = WszLoadLibrary(W("kernel32")); SIMPLIFYING_ASSUMPTION(hKernel32 != NULL); if (hKernel32 == NULL) return; typedef BOOL (*DebugSetProcessKillOnExitSig) (BOOL); DebugSetProcessKillOnExitSig pDebugSetProcessKillOnExit = reinterpret_cast<DebugSetProcessKillOnExitSig>(GetProcAddress(hKernel32, "DebugSetProcessKillOnExit")); // If the API doesn't exist (eg. Win2k) - there isn't anything we can do, just // silently ignore the request. if (pDebugSetProcessKillOnExit == NULL) return; BOOL ret = pDebugSetProcessKillOnExit(m_fKillOnExit); // Not a good failure path here. // 1) This shouldn't fail. // 2) Even if it does, this is likely called after the debuggee // has already been created, and if this API fails, most scenarios will // be unaffected, so we don't want to fail the overall debugging session. SIMPLIFYING_ASSUMPTION(ret); #else // The API doesn't exit on CoreSystem, just return return; #endif }
CorpubPublish::CorpubPublish() : CordbCommonBase(0), m_fpGetModuleFileNameEx(NULL) { // Try to get psapi!GetModuleFileNameExW once, and then every process object can use it. // If we can't get it, then we'll fallback to getting information from the IPC block. #if !defined(FEATURE_CORESYSTEM) m_hPSAPIdll = WszLoadLibrary(W("psapi.dll")); #else m_hPSAPIdll = WszLoadLibrary(W("api-ms-win-obsolete-psapi-l1-1-0.dll")); #endif if (m_hPSAPIdll != NULL) { m_fpGetModuleFileNameEx = (FPGetModuleFileNameEx*) GetProcAddress(m_hPSAPIdll, "GetModuleFileNameExW"); } CordbCommonBase::InitializeCommon(); }
CoreClrCallbacks *GetCoreClrCallbacks() { static CoreClrCallbacks coreClrCallbacks = { 0 }; if (coreClrCallbacks.m_hmodCoreCLR == NULL) { // Run against the desktop CLR coreClrCallbacks.m_hmodCoreCLR = WszLoadLibrary(W("mscoree.dll")); coreClrCallbacks.m_pfnIEE = SnIEE; coreClrCallbacks.m_pfnGetCORSystemDirectory = SnGetCorSystemDirectory; coreClrCallbacks.m_pfnGetCLRFunction = NULL; } return &coreClrCallbacks; }
void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { pfnGetSystemTimeAsFileTime func = NULL; #ifndef FEATURE_PAL HMODULE hKernel32 = WszLoadLibrary(W("kernel32.dll")); if (hKernel32 != NULL) { func = (pfnGetSystemTimeAsFileTime)GetProcAddress(hKernel32, "GetSystemTimePreciseAsFileTime"); if (func != NULL) { // GetSystemTimePreciseAsFileTime exists and we'd like to use it. However, on // misconfigured systems, it's possible for the "precise" time to be inaccurate: // https://github.com/dotnet/coreclr/issues/14187 // If it's inaccurate, though, we expect it to be wildly inaccurate, so as a // workaround/heuristic, we get both the "normal" and "precise" times, and as // long as they're close, we use the precise one. This workaround can be removed // when we better understand what's causing the drift and the issue is no longer // a problem or can be better worked around on all targeted OSes. FILETIME systemTimeResult; ::GetSystemTimeAsFileTime(&systemTimeResult); FILETIME preciseSystemTimeResult; func(&preciseSystemTimeResult); LONG64 systemTimeLong100ns = (LONG64)((((ULONG64)systemTimeResult.dwHighDateTime) << 32) | (ULONG64)systemTimeResult.dwLowDateTime); LONG64 preciseSystemTimeLong100ns = (LONG64)((((ULONG64)preciseSystemTimeResult.dwHighDateTime) << 32) | (ULONG64)preciseSystemTimeResult.dwLowDateTime); const INT32 THRESHOLD_100NS = 1000000; // 100ms if (abs(preciseSystemTimeLong100ns - systemTimeLong100ns) > THRESHOLD_100NS) { // Too much difference. Don't use GetSystemTimePreciseAsFileTime. func = NULL; } } } if (func == NULL) #endif { func = &::GetSystemTimeAsFileTime; } g_pfnGetSystemTimeAsFileTime = func; func(lpSystemTimeAsFileTime); }
void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { pfnGetSystemTimeAsFileTime func = NULL; #ifndef FEATURE_PAL HMODULE hKernel32 = WszLoadLibrary(W("kernel32.dll")); if (hKernel32 != NULL) { func = (pfnGetSystemTimeAsFileTime)GetProcAddress(hKernel32, "GetSystemTimePreciseAsFileTime"); } if (func == NULL) #endif { func = &::GetSystemTimeAsFileTime; } g_pfnGetSystemTimeAsFileTime = func; func(lpSystemTimeAsFileTime); }
static size_t GetRestrictedPhysicalMemoryLimit() { LIMITED_METHOD_CONTRACT; // The limit was cached already if (g_RestrictedPhysicalMemoryLimit != (size_t)MAX_PTR) return g_RestrictedPhysicalMemoryLimit; size_t job_physical_memory_limit = (size_t)MAX_PTR; BOOL in_job_p = FALSE; #ifdef FEATURE_CORECLR HINSTANCE hinstApiSetPsapiOrKernel32 = 0; // these 2 modules will need to be freed no matter what as we only use them locally in this method. HINSTANCE hinstApiSetJob1OrKernel32 = 0; HINSTANCE hinstApiSetJob2OrKernel32 = 0; #else HINSTANCE hinstPsapi = 0; #endif PIS_PROCESS_IN_JOB GCIsProcessInJob = 0; PQUERY_INFORMATION_JOB_OBJECT GCQueryInformationJobObject = 0; #ifdef FEATURE_CORECLR hinstApiSetJob1OrKernel32 = LoadDllForAPI(L"kernel32.dll", L"api-ms-win-core-job-l1-1-0.dll"); if (!hinstApiSetJob1OrKernel32) goto exit; GCIsProcessInJob = (PIS_PROCESS_IN_JOB)GetProcAddress(hinstApiSetJob1OrKernel32, "IsProcessInJob"); if (!GCIsProcessInJob) goto exit; #else GCIsProcessInJob = &(::IsProcessInJob); #endif if (!GCIsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) goto exit; if (in_job_p) { #ifdef FEATURE_CORECLR hinstApiSetPsapiOrKernel32 = LoadDllForAPI(L"kernel32.dll", L"api-ms-win-core-psapi-l1-1-0"); if (!hinstApiSetPsapiOrKernel32) goto exit; GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstApiSetPsapiOrKernel32, "K32GetProcessMemoryInfo"); #else // We need a way to get the working set in a job object and GetProcessMemoryInfo // is the way to get that. According to MSDN, we should use GetProcessMemoryInfo In order to // compensate for the incompatibility that psapi.dll introduced we are getting this dynamically. hinstPsapi = WszLoadLibrary(L"psapi.dll"); if (!hinstPsapi) return 0; GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstPsapi, "GetProcessMemoryInfo"); #endif if (!GCGetProcessMemoryInfo) goto exit; #ifdef FEATURE_CORECLR hinstApiSetJob2OrKernel32 = LoadDllForAPI(L"kernel32.dll", L"api-ms-win-core-job-l2-1-0"); if (!hinstApiSetJob2OrKernel32) goto exit; GCQueryInformationJobObject = (PQUERY_INFORMATION_JOB_OBJECT)GetProcAddress(hinstApiSetJob2OrKernel32, "QueryInformationJobObject"); #else GCQueryInformationJobObject = &(::QueryInformationJobObject); #endif if (!GCQueryInformationJobObject) goto exit; JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info; if (GCQueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info), NULL)) { size_t job_memory_limit = (size_t)MAX_PTR; size_t job_process_memory_limit = (size_t)MAX_PTR; size_t job_workingset_limit = (size_t)MAX_PTR; // Notes on the NT job object: // // You can specific a bigger process commit or working set limit than // job limit which is pointless so we use the smallest of all 3 as // to calculate our "physical memory load" or "available physical memory" // when running inside a job object, ie, we treat this as the amount of physical memory // our process is allowed to use. // // The commit limit is already reflected by default when you run in a // job but the physical memory load is not. // if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_MEMORY) != 0) job_memory_limit = limit_info.JobMemoryLimit; if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) != 0) job_process_memory_limit = limit_info.ProcessMemoryLimit; if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET) != 0) job_workingset_limit = limit_info.BasicLimitInformation.MaximumWorkingSetSize; job_physical_memory_limit = min (job_memory_limit, job_process_memory_limit); job_physical_memory_limit = min (job_physical_memory_limit, job_workingset_limit); MEMORYSTATUSEX ms; ::GetProcessMemoryLoad(&ms); // A sanity check in case someone set a larger limit than there is actual physical memory. job_physical_memory_limit = (size_t) min (job_physical_memory_limit, ms.ullTotalPhys); } } exit: #ifdef FEATURE_CORECLR if (hinstApiSetJob1OrKernel32) FreeLibrary(hinstApiSetJob1OrKernel32); if (hinstApiSetJob2OrKernel32) FreeLibrary(hinstApiSetJob2OrKernel32); #endif if (job_physical_memory_limit == (size_t)MAX_PTR) { job_physical_memory_limit = 0; #ifdef FEATURE_CORECLR FreeLibrary(hinstApiSetPsapiOrKernel32); #else FreeLibrary(hinstPsapi); #endif } VolatileStore(&g_RestrictedPhysicalMemoryLimit, job_physical_memory_limit); return g_RestrictedPhysicalMemoryLimit; }
// This function enumerates all the process in the system and returns // their PIDs BOOL GetAllProcessesInSystem(DWORD *ProcessId, DWORD dwArraySize, DWORD *pdwNumEntries) { HandleHolder hSnapshotHolder; #if !defined(FEATURE_CORESYSTEM) // Load the dll "kernel32.dll". HModuleHolder hDll = WszLoadLibrary(W("kernel32")); _ASSERTE(hDll != NULL); if (hDll == NULL) { LOG((LF_CORDB, LL_INFO1000, "Unable to load the dll for enumerating processes. " "LoadLibrary (kernel32.dll) failed.\n")); return FALSE; } #else // Load the dll "api-ms-win-obsolete-kernel32-l1-1-0.dll". HModuleHolder hDll = WszLoadLibrary(W("api-ms-win-obsolete-kernel32-l1-1-0.dll")); _ASSERTE(hDll != NULL); if (hDll == NULL) { LOG((LF_CORDB, LL_INFO1000, "Unable to load the dll for enumerating processes. " "LoadLibrary (api-ms-win-obsolete-kernel32-l1-1-0.dll) failed.\n")); return FALSE; } #endif // Create the Process' Snapshot // Get the pointer to the requested function FARPROC pProcAddr = GetProcAddress(hDll, "CreateToolhelp32Snapshot"); // If the proc address was not found, return error if (pProcAddr == NULL) { LOG((LF_CORDB, LL_INFO1000, "Unable to enumerate processes in the system. " "GetProcAddr (CreateToolhelp32Snapshot) failed.\n")); return FALSE; } // Handle from CreateToolHelp32Snapshot must be freed via CloseHandle(). typedef HANDLE CREATETOOLHELP32SNAPSHOT(DWORD, DWORD); HANDLE hSnapshot = ((CREATETOOLHELP32SNAPSHOT *)pProcAddr)(TH32CS_SNAPPROCESS, NULL); if (hSnapshot == INVALID_HANDLE_VALUE) { LOG((LF_CORDB, LL_INFO1000, "Unable to create snapshot of processes in the system. " "CreateToolhelp32Snapshot() failed.\n")); return FALSE; } // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. hSnapshotHolder.Assign(hSnapshot); // Get the first process in the process list // Get the pointer to the requested function pProcAddr = GetProcAddress(hDll, "Process32First"); // If the proc address was not found, return error if (pProcAddr == NULL) { LOG((LF_CORDB, LL_INFO1000, "Unable to enumerate processes in the system. " "GetProcAddr (Process32First) failed.\n")); return FALSE; } PROCESSENTRY32 PE32; // need to initialize the dwSize field before calling Process32First PE32.dwSize = sizeof (PROCESSENTRY32); typedef BOOL PROCESS32FIRST(HANDLE, LPPROCESSENTRY32); BOOL succ = ((PROCESS32FIRST *)pProcAddr)(hSnapshot, &PE32); if (succ != TRUE) { LOG((LF_CORDB, LL_INFO1000, "Unable to create snapshot of processes in the system. " "Process32First() returned FALSE.\n")); return FALSE; } // Loop over and get all the remaining processes // Get the pointer to the requested function pProcAddr = GetProcAddress(hDll, "Process32Next"); // If the proc address was not found, return error if (pProcAddr == NULL) { LOG((LF_CORDB, LL_INFO1000, "Unable to enumerate processes in the system. " "GetProcAddr (Process32Next) failed.\n")); return FALSE; } typedef BOOL PROCESS32NEXT(HANDLE, LPPROCESSENTRY32); int iIndex = 0; do { ProcessId [iIndex++] = PE32.th32ProcessID; succ = ((PROCESS32NEXT *)pProcAddr)(hSnapshot, &PE32); } while ((succ == TRUE) && (iIndex < (int)dwArraySize)); // I would like to know if we're running more than 512 processes on Win95!! _ASSERTE (iIndex < (int)dwArraySize); *pdwNumEntries = iIndex; // If we made it this far, we succeeded return TRUE; }
static size_t GetRestrictedPhysicalMemoryLimit() { LIMITED_METHOD_CONTRACT; // The limit was cached already if (g_RestrictedPhysicalMemoryLimit != (size_t)MAX_PTR) return g_RestrictedPhysicalMemoryLimit; size_t job_physical_memory_limit = (size_t)MAX_PTR; BOOL in_job_p = FALSE; HINSTANCE hinstKernel32 = 0; PIS_PROCESS_IN_JOB GCIsProcessInJob = 0; PQUERY_INFORMATION_JOB_OBJECT GCQueryInformationJobObject = 0; GCIsProcessInJob = &(::IsProcessInJob); if (!GCIsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) goto exit; if (in_job_p) { hinstKernel32 = WszLoadLibrary(L"kernel32.dll"); if (!hinstKernel32) goto exit; GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstKernel32, "K32GetProcessMemoryInfo"); if (!GCGetProcessMemoryInfo) goto exit; GCQueryInformationJobObject = &(::QueryInformationJobObject); if (!GCQueryInformationJobObject) goto exit; JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info; if (GCQueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info), NULL)) { size_t job_memory_limit = (size_t)MAX_PTR; size_t job_process_memory_limit = (size_t)MAX_PTR; size_t job_workingset_limit = (size_t)MAX_PTR; // Notes on the NT job object: // // You can specific a bigger process commit or working set limit than // job limit which is pointless so we use the smallest of all 3 as // to calculate our "physical memory load" or "available physical memory" // when running inside a job object, ie, we treat this as the amount of physical memory // our process is allowed to use. // // The commit limit is already reflected by default when you run in a // job but the physical memory load is not. // if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_MEMORY) != 0) job_memory_limit = limit_info.JobMemoryLimit; if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) != 0) job_process_memory_limit = limit_info.ProcessMemoryLimit; if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET) != 0) job_workingset_limit = limit_info.BasicLimitInformation.MaximumWorkingSetSize; job_physical_memory_limit = min (job_memory_limit, job_process_memory_limit); job_physical_memory_limit = min (job_physical_memory_limit, job_workingset_limit); MEMORYSTATUSEX ms; ::GetProcessMemoryLoad(&ms); // A sanity check in case someone set a larger limit than there is actual physical memory. job_physical_memory_limit = (size_t) min (job_physical_memory_limit, ms.ullTotalPhys); } } exit: if (job_physical_memory_limit == (size_t)MAX_PTR) { job_physical_memory_limit = 0; FreeLibrary(hinstKernel32); } VolatileStore(&g_RestrictedPhysicalMemoryLimit, job_physical_memory_limit); return g_RestrictedPhysicalMemoryLimit; }
//----------------------------------------------------------------------------- // Receieves the call. This should be in a different process than the source //----------------------------------------------------------------------------- HRESULT IPCFuncCallHandler::InitFCHandler(HANDLER_CALLBACK pfnCallback) { m_pfnCallback = pfnCallback; HRESULT hr = NOERROR; DWORD dwThreadId; DWORD dwErr = 0; SetLastError(0); SECURITY_ATTRIBUTES *pSA = NULL; // Grab the SA DWORD dwPid = GetCurrentProcessId(); hr = IPCShared::CreateWinNTDescriptor(dwPid, &pSA); if (FAILED(hr)) goto errExit;; // Create the StartEnum Event m_hStartEnum = WszCreateEvent(pSA, FALSE, FALSE, FixupName(StartEnumEventName)); if (m_hStartEnum == NULL) { dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create the EndEnumEvent m_hDoneEnum = WszCreateEvent(pSA, FALSE, FALSE, FixupName(DoneEnumEventName)); if (m_hDoneEnum == NULL) { dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create the ShutdownThread Event m_hShutdownThread = WszCreateEvent(pSA, TRUE, /* Manual Reset */ FALSE, /* Initial state not signalled */ NULL); dwErr = GetLastError(); if (m_hShutdownThread == NULL) { hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create the AuxThreadShutdown Event m_hAuxThreadShutdown = WszCreateEvent(pSA, TRUE, /* Manual Reset */ FALSE, NULL); dwErr = GetLastError(); if (m_hAuxThreadShutdown == NULL) { hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // The thread that we are about to create should always // find the code in memory. So we take a ref on the DLL. // and do a free library at the end of the thread's start function m_hCallbackModule = WszLoadLibrary (L"CorPerfmonExt.dll"); dwErr = GetLastError(); if (m_hCallbackModule == NULL) { hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create thread m_hAuxThread = CreateThread( NULL, 0, HandlerAuxThreadProc, this, 0, &dwThreadId); dwErr = GetLastError(); if (m_hAuxThread == NULL) { hr = HRESULT_FROM_WIN32(dwErr); // In case of an error free this library here otherwise // the thread's exit would take care of it. if (m_hCallbackModule) FreeLibrary (m_hCallbackModule); goto errExit; } errExit: if (!SUCCEEDED(hr)) { TerminateFCHandler(); } return hr; }
//***************************************************************************** // This function will handle ignore codes and tell the user what is happening. //***************************************************************************** int _DbgBreakCheck( LPCSTR szFile, int iLine, LPCSTR szExpr) { TCHAR rcBuff[1024+_MAX_PATH]; TCHAR rcPath[_MAX_PATH]; TCHAR rcTitle[64]; _DBGIGNOREDATA *psData; long i; if (DebugBreakOnAssert()) { DebugBreak(); } DBGIGNORE* pDBGIFNORE = GetDBGIGNORE(); // Check for ignore all. for (i=0, psData = pDBGIFNORE->Ptr(); i<pDBGIFNORE->Count(); i++, psData++) { if (psData->iLine == iLine && _stricmp(psData->rcFile, szFile) == 0 && psData->bIgnore == true) return (false); } // Give assert in output for easy access. WszGetModuleFileName(0, rcPath, NumItems(rcPath)); swprintf(rcBuff, L"Assert failure(PID %d [0x%08x], Thread: %d [0x%x]): %hs\n" L" File: %hs, Line: %d Image:\n%s\n", GetCurrentProcessId(), GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId(), szExpr, szFile, iLine, rcPath); WszOutputDebugString(rcBuff); // Write out the error to the console printf("%S\n", rcBuff); LogAssert(szFile, iLine, szExpr); FlushLogging(); // make certain we get the last part of the log fflush(stdout); if (NoGuiOnAssert()) { TerminateOnAssert(); } if (DebugBreakOnAssert()) { return(true); // like a retry } // Change format for message box. The extra spaces in the title // are there to get around format truncation. swprintf(rcBuff, L"%hs\n\n%hs, Line: %d\n\nAbort - Kill program\nRetry - Debug\nIgnore - Keep running\n" L"\n\nImage:\n%s\n", szExpr, szFile, iLine, rcPath); swprintf(rcTitle, L"Assert Failure (PID %d, Thread %d/%x) ", GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId()); // Tell user there was an error. _DbgBreakCount++; int ret = WszMessageBoxInternal(NULL, rcBuff, rcTitle, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | COMPLUS_MB_SERVICE_NOTIFICATION); --_DbgBreakCount; HMODULE hKrnl32; switch(ret) { // For abort, just quit the app. case IDABORT: TerminateProcess(GetCurrentProcess(), 1); // WszFatalAppExit(0, L"Shutting down"); break; // Tell caller to break at the correct loction. case IDRETRY: hKrnl32 = WszLoadLibrary(L"kernel32.dll"); _ASSERTE(hKrnl32 != NULL); if(hKrnl32) { typedef BOOL (WINAPI *t_pDbgPres)(); t_pDbgPres pFcn = (t_pDbgPres) GetProcAddress(hKrnl32, "IsDebuggerPresent"); // If this function is available, use it. if (pFcn) { if (pFcn()) { SetErrorMode(0); } else LaunchJITDebugger(); } FreeLibrary(hKrnl32); } return (true); // If we want to ignore the assert, find out if this is forever. case IDIGNORE: swprintf(rcBuff, L"Ignore the assert for the rest of this run?\nYes - Assert will never fire again.\nNo - Assert will continue to fire.\n\n%hs\nLine: %d\n", szFile, iLine); if (WszMessageBoxInternal(NULL, rcBuff, L"Ignore Assert Forever?", MB_ICONQUESTION | MB_YESNO | COMPLUS_MB_SERVICE_NOTIFICATION) != IDYES) break; if ((psData = pDBGIFNORE->Append()) == 0) return (false); psData->bIgnore = true; psData->iLine = iLine; strcpy(psData->rcFile, szFile); break; } return (false); }
HRESULT LoadDataAccessDll(HINSTANCE mscorModule, REFIID ifaceId, ICLRDataTarget* target, HMODULE* dllHandle, void** iface) { HRESULT status; WCHAR accessDllPath[MAX_PATH]; HMODULE accessDll; // // Load the access DLL from the same directory // as the runtime DLL. // if (!WszGetModuleFileName(mscorModule, accessDllPath, NumItems(accessDllPath))) { return HRESULT_FROM_GetLastError(); } PWSTR pathTail = wcsrchr(accessDllPath, '\\'); if (!pathTail) { return E_INVALIDARG; } pathTail++; PWSTR eeFlavor = L"wks"; if (_snwprintf_s(pathTail, _countof(accessDllPath) + (accessDllPath - pathTail), NumItems(accessDllPath) - (pathTail - accessDllPath), MAKEDLLNAME_W(L"mscordac%s"), eeFlavor) <= 0) { return E_INVALIDARG; } accessDll = WszLoadLibrary(accessDllPath); if (!accessDll) { return HRESULT_FROM_GetLastError(); } // // Get the access interface and have it // enumerate the interesting memory in the target process. // void* ifacePtr; PFN_CLRDataCreateInstance entry = (PFN_CLRDataCreateInstance) GetProcAddress(accessDll, "CLRDataCreateInstance"); if (!entry) { status = HRESULT_FROM_GetLastError(); FreeLibrary(accessDll); } else if ((status = entry(ifaceId, target, &ifacePtr)) != S_OK) { FreeLibrary(accessDll); } else { *dllHandle = accessDll; *iface = ifacePtr; } return status; }