WindowsXP-SP1/admin/burnslib/core/assert.cpp
2020-09-30 16:53:49 +02:00

179 lines
3.8 KiB
C++

// 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;
memset(ansiSymbol, 0, Burnslib::StackTrace::SYMBOL_NAME_MAX);
memset(ansiModule, 0, Burnslib::StackTrace::MODULE_NAME_MAX);
memset(ansiSource, 0, MAX_PATH);
Burnslib::StackTrace::LookupAddress(
traceAddress,
ansiModule,
0,
ansiSymbol,
&displacement,
&line,
ansiSource);
return
_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 = 2048;
char details[MAX_MSG];
DWORD tid = ::GetCurrentThreadId();
DWORD pid = ::GetCurrentProcessId();
int used =
_snprintf(
details,
MAX_MSG,
" 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)
{
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
| MB_TASKMODAL
| MB_ICONERROR
| 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;
}