// Copyright (c) 2000 Microsoft Corporation // // ASSERT macro // // 3 Mar 2000 sburns #include "headers.hxx" int AddStackTraceLine( DWORD64 traceAddress, char* buffer, size_t bufferMax) { if (!buffer || ! traceAddress || !bufferMax) { return 0; } char ansiSymbol[Burnslib::StackTrace::SYMBOL_NAME_MAX]; char ansiModule[Burnslib::StackTrace::MODULE_NAME_MAX]; char ansiSource[MAX_PATH]; DWORD64 displacement = 0; DWORD line = 0; // REVIEWED-2002/03/05-sburns correct byte counts passed. ::ZeroMemory(ansiSymbol, Burnslib::StackTrace::SYMBOL_NAME_MAX); ::ZeroMemory(ansiModule, Burnslib::StackTrace::MODULE_NAME_MAX); ::ZeroMemory(ansiSource, MAX_PATH); Burnslib::StackTrace::LookupAddress( traceAddress, ansiModule, 0, ansiSymbol, &displacement, &line, ansiSource); return // ISSUE-2002/03/05-sburns consider strsafe.h replacement _snprintf( buffer, bufferMax, " %016I64X %s%!%s+0x%I64X %s (%d)\n", traceAddress, ansiModule, ansiSymbol, displacement, ansiSource, line); } bool Burnslib::FireAssertionFailure(const char* file, int line, const char* expr) { // // DON'T CALL ASSERT() IN THIS FUNCTION! // // also don't call new, or any other code that could call ASSERT. bool result = false; char processName[128]; char* pProcessName = processName; if (!::GetModuleFileNameA(0, processName, 128)) { pProcessName = "Unknown"; } static const int MAX_MSG = 2047; // NTRAID#NTBUG9-541418-2002/03/28-sburns char details[MAX_MSG + 1]; // REVIEWED-2002/03/05-sburns correct byte count passed. ::ZeroMemory(details, MAX_MSG + 1); DWORD tid = ::GetCurrentThreadId(); DWORD pid = ::GetCurrentProcessId(); int used = // ISSUE-2002/03/05-sburns consider strsafe.h replacement _snprintf( details, // reserve space so that we can guarantee null-termination MAX_MSG - 1, " Expression: %s \n" "\n" " File \t : %s \n" " Line \t : %d \n" // " Module \t : %s \n" " Process\t : 0x%X (%d) %s\n" " Thread \t : 0x%X (%d)\n" "\n" " Click Retry to debug.\n" "\n", expr, file, line, // pModuleName, pid, pid, pProcessName, tid, tid); if (used < 0) { // ISSUE-2002/03/05-sburns consider strsafe.h replacement, use 'n' // variant strcpy(details, "details too detailed.\n"); } else { // grab a stack trace static const size_t TRACE_MAX = 10; DWORD64 stackTrace[TRACE_MAX]; Burnslib::StackTrace::Trace(stackTrace, TRACE_MAX); // build a stack trace dump // skip the first entry, which corresponds to this function, so that // the dump reflects the call stack at the point of assertion failure. // so there will be at most TRACE_MAX - 1 lines output. for (int i = 1; stackTrace[i] && i < TRACE_MAX; ++i) { int used2 = AddStackTraceLine( stackTrace[i], details + used, MAX_MSG - used); if (used2 < 0) { break; } used += used2; } } static const char* TITLE = "Assertion Failed!"; ::OutputDebugStringA(TITLE); ::OutputDebugStringA("\n"); ::OutputDebugStringA(details); switch ( ::MessageBoxA( 0, details, TITLE, MB_SETFOREGROUND // ICONHAND + SYSTEMMODAL gets us the special low-memory // message box. // NTRAID#NTBUG9-556530-2002/03/28-sburns | MB_ICONHAND | MB_SYSTEMMODAL | MB_ABORTRETRYIGNORE)) { case IDABORT: { _exit(3); } case IDRETRY: { // user wants to drop into the debugger. result = true; break; } case IDIGNORE: case IDCANCEL: default: { // do nothing break; } } return result; }