316 lines
9 KiB
C
316 lines
9 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Debug.h
|
|
|
|
Abstract:
|
|
|
|
New debug services for spooler.
|
|
|
|
Author:
|
|
|
|
Albert Ting (AlbertT) 15-Jan-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _DBGLOG_H
|
|
#define _DBGLOG_H
|
|
|
|
/********************************************************************
|
|
|
|
Setting up the debug support:
|
|
=============================
|
|
|
|
Define a MODULE prefix string. Since this will be printed as
|
|
a prefix to all debug output, it should be concise and unique.
|
|
|
|
In your global header file:
|
|
|
|
#define MODULE "prtlib:"
|
|
|
|
Define a MODULE_DEBUG variable. This is the actual symbol
|
|
that the library will use to indicate debugging level.
|
|
This DWORD is broken into two bitfield WORDs: the low word
|
|
indicates which levels to print to the debugger; the high word
|
|
breaks into the debugger. The library takes the DebugLevel from
|
|
a debug message, then ANDs it with the debug level. If the bit
|
|
is on, the corresponding action (print or break) is taken.
|
|
|
|
In your global header file:
|
|
|
|
#define MODULE_DEBUG PrtlibDebug
|
|
|
|
Finally, the actual debug variable must be defined and initialized
|
|
to a default debug level. This must be done in exactly one
|
|
*.c translation unit:
|
|
|
|
In one of your source files:
|
|
|
|
MODULE_DEBUG_INIT ( {LevelsToPrint}, {LevelsToBreak} );
|
|
|
|
Adding logging to source code:
|
|
==============================
|
|
|
|
The general format for debug message is:
|
|
|
|
DBGMSG( {DebugLevel}, ( {args to printf} ));
|
|
|
|
The DebugLevel dictates whether the level should print, break
|
|
into the debugger, or just log to memory (logging always done).
|
|
|
|
The args to printf must be placed in an extra set of parens,
|
|
and should assume everything is ANSI. To print LPTSTRs, use
|
|
the TSTR macro:
|
|
|
|
DBGMSG( DBG_WARN,
|
|
( "LPTSTR "TSTR", LPSTR %s, LPWSTR %ws\n",
|
|
TEXT("hello"), "hello", L"hello" ));
|
|
|
|
Viewing DBGMSGs:
|
|
================
|
|
|
|
Messages will print to the debugger (usermode, or kernel debugger
|
|
if no usermode debugger is available) for all printable levels.
|
|
To change the level, you can edit the MODULE_DEBUG variable
|
|
(PrtlibDebug in the above example).
|
|
|
|
By default, DBG_ERROR and DBG_WARNING messages a logged to the
|
|
error log (stored at gpbterrlog). All others are stored in the
|
|
trace log (gpbttracelog). These currently log to memory in
|
|
a circular buffer. Use the splx.dll extension to dump these
|
|
logs.
|
|
|
|
At compile time, you can switch these logs to go to file rather
|
|
than memory. They will be stored as the PID + index number in
|
|
the default directory of the process.
|
|
|
|
********************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
//
|
|
// These values are strictly debug, but must be defined in the free
|
|
// build because the TStatus error checking uses them as the first ctr
|
|
// parameter. (During inlining they are discarded.)
|
|
//
|
|
|
|
#define DBG_NONE 0x0000
|
|
#define DBG_INFO 0x0001
|
|
#define DBG_WARN 0x0002
|
|
#define DBG_WARNING 0x0002
|
|
#define DBG_ERROR 0x0004
|
|
#define DBG_TRACE 0x0008
|
|
#define DBG_SECURITY 0x0010
|
|
#define DBG_EXEC 0x0020
|
|
#define DBG_PORT 0x0040
|
|
#define DBG_NOTIFY 0x0080
|
|
#define DBG_PAUSE 0x0100
|
|
|
|
#define DBG_THREADM 0x0400
|
|
#define DBG_MIN 0x0800
|
|
#define DBG_TIME 0x1000
|
|
#define DBG_FOLDER 0x2000
|
|
#define DBG_NOHEAD 0x8000
|
|
|
|
#if DBG
|
|
|
|
extern DWORD MODULE_DEBUG;
|
|
|
|
//
|
|
// This should be used exactly once in a C file. It defines
|
|
// the Debug variable, and also the DbgMsg function.
|
|
//
|
|
// If we are statically linking with SplLib (SplLib is a library, not
|
|
// a Dll), then we will get the definition from SplLib, so don't define
|
|
// it here.
|
|
//
|
|
#ifdef LINK_SPLLIB
|
|
#define MODULE_DEBUG_INIT( print, break ) \
|
|
DWORD MODULE_DEBUG = (DBG_PRINT( print ) | DBG_BREAK( break ))
|
|
#else
|
|
#define MODULE_DEBUG_INIT( print, break ) \
|
|
VOID \
|
|
DbgMsg( \
|
|
LPCSTR pszMsgFormat, \
|
|
... \
|
|
) \
|
|
{ \
|
|
CHAR szMsgText[1024]; \
|
|
va_list vargs; \
|
|
\
|
|
va_start( vargs, pszMsgFormat ); \
|
|
wvsprintfA( szMsgText, pszMsgFormat, vargs ); \
|
|
va_end( vargs ); \
|
|
\
|
|
if( szMsgText[0] && szMsgText[0] != ' ' ){ \
|
|
OutputDebugStringA( MODULE ); \
|
|
} \
|
|
OutputDebugStringA( szMsgText ); \
|
|
} \
|
|
DWORD MODULE_DEBUG = (DBG_PRINT( print ) | DBG_BREAK( break ))
|
|
#endif
|
|
|
|
#define DBGSTR( str ) \
|
|
((str) ? (str) : TEXT("(NULL)"))
|
|
|
|
#ifdef UNICODE
|
|
#define TSTR "%ws"
|
|
#else
|
|
#define TSTR "%s"
|
|
#endif
|
|
|
|
#define DBG_PRINT_MASK 0xffff
|
|
#define DBG_BREAK_SHIFT 16
|
|
|
|
#define DBG_PRINT(x) (x)
|
|
#define DBG_BREAK(x) (((x) << DBG_BREAK_SHIFT)|(x))
|
|
|
|
#define SPLASSERT(expr) \
|
|
if (!(expr)) { \
|
|
DbgMsg( "Failed: %s\nLine %d, %s\n", \
|
|
#expr, \
|
|
__LINE__, \
|
|
__FILE__ ); \
|
|
DebugBreak(); \
|
|
}
|
|
|
|
VOID
|
|
vDbgSingleThreadReset(
|
|
PDWORD pdwThreadId
|
|
);
|
|
|
|
VOID
|
|
vDbgSingleThread(
|
|
PDWORD pdwThreadId
|
|
);
|
|
|
|
VOID
|
|
vDbgSingleThreadNot(
|
|
PDWORD pdwThreadId
|
|
);
|
|
|
|
VOID
|
|
DbgMsg(
|
|
LPCSTR pszMsgFormat,
|
|
...
|
|
);
|
|
|
|
#ifdef DBGLOG
|
|
|
|
#define DBGMSG( uDbgLevel, argsPrint ) \
|
|
vDbgLogError( MODULE_DEBUG, \
|
|
uDbgLevel, \
|
|
__LINE__, \
|
|
__FILE__, \
|
|
MODULE, \
|
|
pszDbgAllocMsgA argsPrint )
|
|
|
|
LPSTR
|
|
pszDbgAllocMsgA(
|
|
LPCSTR pszMsgFormatA,
|
|
...
|
|
);
|
|
|
|
VOID
|
|
vDbgLogError(
|
|
UINT uDbg,
|
|
UINT uDbgLevel,
|
|
UINT uLine,
|
|
LPCSTR pszFileA,
|
|
LPCSTR pszModuleA,
|
|
LPCSTR pszMsgA
|
|
);
|
|
#else
|
|
|
|
VOID
|
|
DbgBreakPoint(
|
|
VOID
|
|
);
|
|
|
|
#define DBGMSG( Level, MsgAndArgs ) \
|
|
{ \
|
|
if( ( (Level) & 0xFFFF ) & MODULE_DEBUG ){ \
|
|
DbgMsg MsgAndArgs; \
|
|
} \
|
|
if( ( (Level) << 16 ) & MODULE_DEBUG ) \
|
|
DbgBreakPoint(); \
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#define SINGLETHREAD_VAR(var) \
|
|
DWORD dwSingleThread_##var
|
|
|
|
#define SINGLETHREAD(var) \
|
|
vDbgSingleThread(&dwSingleThread_##var)
|
|
|
|
#define SINGLETHREADNOT(var) \
|
|
vDbgSingleThreadNot(&dwSingleThread_##var)
|
|
|
|
#define SINGLETHREADRESET(var) \
|
|
vDbgSingleThreadReset(&dwSingleThread_##var)
|
|
|
|
#else
|
|
#define MODULE_DEBUG_INIT( print, break )
|
|
#define DBGMSG( uDbgLevel, argsPrint )
|
|
#define SPLASSERT(exp)
|
|
#define SINGLETHREAD_VAR(var)
|
|
#define SINGLETHREAD(var)
|
|
#define SINGLETHREADNOT(var)
|
|
#define SINGLETHREADRESET(var)
|
|
#endif
|
|
|
|
|
|
//
|
|
// Automatic checking if an object is valid.
|
|
//
|
|
#if DBG
|
|
|
|
VOID
|
|
vWarnInvalid(
|
|
PVOID pvObject,
|
|
UINT uDbg,
|
|
UINT uLine,
|
|
LPCSTR pszFileA,
|
|
LPCSTR pszModuleA
|
|
);
|
|
|
|
#define VALID_PTR(x) \
|
|
((( x ) && (( x )->bValid( ))) ? \
|
|
TRUE : \
|
|
( vWarnInvalid( (PVOID)(x), MODULE_DEBUG, __LINE__, __FILE__, MODULE ), FALSE ))
|
|
|
|
#define VALID_OBJ(x) \
|
|
((( x ).bValid( )) ? \
|
|
TRUE : \
|
|
( vWarnInvalid( (PVOID)&(x), MODULE_DEBUG, __LINE__, __FILE__, MODULE ), FALSE ))
|
|
|
|
#define VALID_BASE(x) \
|
|
(( x::bValid( )) ? \
|
|
TRUE : \
|
|
( vWarnInvalid( (PVOID)this, MODULE_DEBUG, __LINE__, __FILE__, MODULE ), FALSE ))
|
|
|
|
#else
|
|
#define VALID_PTR(x) \
|
|
(( x ) && (( x )->bValid()))
|
|
#define VALID_OBJ(x) \
|
|
(( x ).bValid())
|
|
#define VALID_BASE(x) \
|
|
( x::bValid( ))
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // _DBGLOG_H
|