/*++ Copyright (c) 2000 Microsoft Corporation Module Name: debug.c Abstract: Debugging routines exported by the STOR library. Author: Matthew D Hendel (math) 29-Apr-2000 Revision History: --*/ #include "precomp.h" //#include "ntrtl.h" #if DBG BOOLEAN StorQuiet = FALSE; ULONG StorComponentId = -1; PCSTR StorDebugPrefix = "STOR: "; // // NB: These should come from ntrtl.h // ULONG vDbgPrintExWithPrefix( IN PCH Prefix, IN ULONG ComponentId, IN ULONG Level, IN PCSTR Format, va_list arglist ); NTSYSAPI ULONG NTAPI DbgPrompt( PCH Prompt, PCH Response, ULONG MaximumResponseLength ); BOOLEAN StorAssertHelper( PCHAR Expression, PCHAR File, ULONG Line, PBOOLEAN Ignore ) { CHAR Response[2]; DebugPrint (("*** Assertion failed: %s\n", Expression)); DebugPrint (("*** Source File: %s, line %ld\n\n", File, Line)); if (*Ignore == TRUE) { DebugPrint (("Ignored\n")); return FALSE; } for (;;) { // // The following line will print the prefix, not just the space. // DebugPrint ((" ")); DbgPrompt( "(B)reak, (S)kip (I)gnore (bsi)? ", Response, sizeof (Response) ); switch (tolower (Response[0])) { case 'b': return TRUE; case 'i': *Ignore = TRUE; return FALSE; case 's': return FALSE; } } } VOID StorSetDebugPrefixAndId( IN PCSTR Prefix, IN ULONG ComponentId ) /*++ Routine Description: Set the default debug prefix to something other than "STOR: ". Arguments: Prefix - Supplies the prefix. The pointer to the prefix is saved preserved, so the prefix memory cannot be paged deallocated. Generally, using a static string here is best. ComponentId - Return Value: None. --*/ { StorDebugPrefix = Prefix; StorComponentId = ComponentId; } VOID vStorDebugPrintEx( IN ULONG Level, IN PCSTR Format, va_list arglist ) { if (Level == DPFLTR_ERROR_LEVEL || !StorQuiet) { vDbgPrintExWithPrefix ((PSTR)StorDebugPrefix, StorComponentId, Level, Format, arglist); } } VOID StorDebugPrintEx( IN ULONG Level, IN PCSTR Format, ... ) { va_list ap; va_start (ap, Format); vStorDebugPrintEx (Level, Format, ap); va_end (ap); } VOID StorDebugWarn( IN PCSTR Format, ... ) { va_list ap; va_start (ap, Format); vStorDebugPrintEx (DPFLTR_WARNING_LEVEL, Format, ap); va_end (ap); } VOID StorDebugTrace( IN PCSTR Format, ... ) { va_list ap; va_start (ap, Format); vStorDebugPrintEx (DPFLTR_TRACE_LEVEL, Format, ap); va_end (ap); } VOID StorDebugPrint( IN PCSTR Format, ... ) { va_list ap; va_start (ap, Format); vStorDebugPrintEx (DPFLTR_ERROR_LEVEL, Format, ap); va_end (ap); } #endif // DBG // // The following are support functions for compiler runtime checks. // #if defined (_RTC) || (DBG == 1) typedef struct _RTC_vardesc { int addr; int size; char *name; } _RTC_vardesc; typedef struct _RTC_framedesc { int varCount; _RTC_vardesc *variables; } _RTC_framedesc; VOID __cdecl _RTC_InitBase( VOID ) { } VOID __cdecl _RTC_Shutdown( VOID ) { } VOID #if defined (_X86_) __declspec(naked) #endif // _X86_ __cdecl _RTC_CheckEsp( ) { #if defined (_X86_) __asm { jne esperror ; ret esperror: ; function prolog push ebp mov ebp, esp sub esp, __LOCAL_SIZE push eax ; save the old return value push edx push ebx push esi push edi } DebugPrint (("*** Callstack Check failure at %p\n", _ReturnAddress())); KdBreakPoint(); __asm { ; function epilog pop edi pop esi pop ebx pop edx ; restore the old return value pop eax mov esp, ebp pop ebp ret } #endif } VOID FASTCALL _RTC_CheckStackVars( PVOID frame, _RTC_framedesc *v ) { int i; for (i = 0; i < v->varCount; i++) { int *head = (int *)(((char *)frame) + v->variables[i].addr + v->variables[i].size); int *tail = (int *)(((char *)frame) + v->variables[i].addr - sizeof(int)); if (*tail != 0xcccccccc || *head != 0xcccccccc) { DebugPrint(("*** RTC Failure %p: stack corruption near %p (%s)\n", _ReturnAddress(), v->variables[i].addr + (ULONG_PTR)frame, v->variables[i].name)); KdBreakPoint(); } } } VOID __cdecl _RTC_UninitUse( IN PCSTR varname ) { DebugPrint(("\n*** RTC Failure %p: uninitialized variable %s.\n", _ReturnAddress(), varname)); KdBreakPoint(); } #endif // _RTC || DBG