Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1435 lines
32 KiB

/*++
Copyright (c) 1995-2001 Microsoft Corporation
Module Name:
debug.c
Abstract:
Domain Name System (DNS) Library
Debug routines.
Author:
Jim Gilroy (jamesg) January 31, 1995
Revision History:
--*/
#include "local.h"
#define DNSDBG_CONTEXT_SWITCH_LOGGING 1
#define DNSDBG_DEFAULT_WRAP_SIZE (2000000) // 2mb
//
// DCR: Temp hack while debugging print lock jam
// - cuts off lock printing to avoid recursive spin
//
extern PCRITICAL_SECTION pDnsAtomicPrintCs;
//
// Debug globals
//
DNS_DEBUG_INFO g_DnsDbgInfo = { 0 };
PDNS_DEBUG_INFO g_pDbgInfo = &g_DnsDbgInfo;
// Redirected
BOOL g_DbgRedirected = FALSE;
//
// Debug flag -- exposed as pointer in dnslib.h
//
// By default use DnsDebugFlag, but actual debug printing is
// switched by *pDnsDebugFlag, which caller may point at local
// flag if desired.
//
PDWORD pDnsDebugFlag = (PDWORD)&g_DnsDbgInfo;
//
// Note that in all functions below, we use the universal
// check IS_DNSDBG_ON(), which is defined for debug AND retail.
// Do NOT use any of the debug macros, as we want the code to
// work equally well in retail versions of dnsapi.dll, so that
// debug versions of calling modules can use these functions.
//
//
// Print buffer sizes
// - small default stack buffer
// - large buffer on heap to handle any print
//
// NOTE: MUST have stack buffer of sufficient size to
// handle any message we print on memory allocation
// failure; otherwise we get into the obvious loop
// of alloc failure causing print, which causes attempted
// alloc and another print
//
#define DNS_STACK_PRINT_BUFFER_LENGTH (0x300) // 768 covers 99%
#define DNS_HEAP_PRINT_BUFFER_LENGTH (0x4000) // 16K will cover anything
//
// Public debug routines
//
VOID
Dns_Assert(
IN LPSTR pszFile,
IN INT LineNo,
IN LPSTR pszExpr
)
{
DnsDbg_Printf(
"ASSERTION FAILED: %s\n"
" %s, line %d\n",
pszExpr,
pszFile,
LineNo );
DnsDbg_Flush();
// always print to debugger, even if debugger print flag not set
if ( ! IS_DNSDBG_ON( DEBUGGER ) )
{
DnsDbg_PrintfToDebugger(
"ASSERTION FAILED: %s\n"
" %s, line %d\n",
pszExpr,
pszFile,
LineNo );
}
if ( IS_DNSDBG_ON( BREAKPOINTS ) )
{
DebugBreak();
}
else
{
DnsDbg_Printf( "Skipping DNS_ASSERT, debug flag = %lx\n", *pDnsDebugFlag );
}
}
#if 0
typedef struct _DnsDebugInit
{
DWORD Flag;
PSTR pszFlagFile;
PDWORD pDebugFlag;
PSTR pszLogFile;
DWORD WrapSize;
BOOL fUseGlobalFile;
BOOL fUseGlobalFlag;
BOOL fSetGlobals;
}
DNS_DEBUG_INIT, *PDNS_DEBUG_INIT;
#endif
VOID
Dns_StartDebugEx(
IN DWORD DebugFlag,
IN PSTR pszFlagFile,
IN OUT PDWORD pDebugFlag,
IN PSTR pszLogFile,
IN DWORD WrapSize,
IN BOOL fUseGlobalFile,
IN BOOL fUseGlobalFlag,
IN BOOL fSetGlobals
)
/*++
Routine Description:
Initialize debugging.
Only current task is to read and set debug flags.
Arguments:
includes:
dwFlag -- debug flags
pszFlagFile -- name of file containing debug flags
pdwFlag -- ptr to DWORD to receive debug flags
pszLogFile -- log file name
dwWrapSize -- log file wrap size
fUseGlobalFile --
fUseGlobalFlag --
fSetGlobals --
Return Value:
None.
--*/
{
HANDLE hfile;
DWORD freadFlag = FALSE;
BOOL fretry = FALSE;
CHAR prevName[ MAX_PATH+10 ];
DWORD debugFlag;
PDNS_DEBUG_INFO pinfoGlobal = NULL;
//
// use external flag?
// - save ptr to it
//
// allow use of external flag so callers -- eg. DNS server --
// can easily manipulate flag during run time and still keep
// their checking macros simple
//
if ( pDebugFlag )
{
pDnsDebugFlag = pDebugFlag;
g_DnsDbgInfo.Flag = *pDnsDebugFlag;
}
//
// get piggyback info
//
if ( fUseGlobalFlag || fUseGlobalFile )
{
pinfoGlobal = DnsApiSetDebugGlobals( NULL );
}
//
// skip debug flag setup if piggybacking
// - use the existing flag value
// - but not safe to grab pointer which
// may go away on dll unload
//
// DCR: safe way to use existing flags?
// DCR: need to be able to get "last" debug flag set
// without blowing up
//
if ( fUseGlobalFlag &&
pinfoGlobal &&
pinfoGlobal->hFile )
{
goto Done;
}
//
// setup debug flag
//
debugFlag = DebugFlag;
if ( debugFlag )
{
freadFlag = TRUE;
}
else if ( pszFlagFile )
{
// read debug flag in file
hfile = CreateFile(
pszFlagFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL
);
if ( hfile == (HANDLE)INVALID_HANDLE_VALUE )
{
// if file specified and not found, then quit if explicit value
// not given
if ( debugFlag == 0 )
{
return;
}
}
else
{
DWORD bytesRead;
CHAR buffer[100];
RtlZeroMemory( buffer, sizeof(buffer) );
if ( ReadFile( hfile, buffer, 100, &bytesRead, NULL ) )
{
buffer[bytesRead] = '\0';
debugFlag = strtoul( buffer, NULL, 16 );
freadFlag = TRUE;
}
else
{
DnsDbg_Printf( "read file failed: %ld\n", GetLastError( ) );
if ( debugFlag == 0 )
{
CloseHandle( hfile );
return;
}
}
CloseHandle( hfile );
}
}
//
// save any flag read
// - reset global (internal or external) to it
//
if ( freadFlag )
{
g_DnsDbgInfo.Flag = debugFlag;
*pDnsDebugFlag = debugFlag;
}
//
// skip debug file open if piggybacking
//
// two levels
// - only using file
// - using file and debug flags
if ( fUseGlobalFile &&
pinfoGlobal &&
pinfoGlobal->hFile )
{
goto Done;
}
//
// open debug logfile
//
fretry = 0;
while ( pszLogFile )
{
PCHAR pnameBuf = g_DnsDbgInfo.FileName;
// heap may not be initialized, copy filename to static buffer
//
// note: if we fail on first pass we try again but open directly
// at file system root; given simply filename, applications
// run from system32 and services (resolver) will attempt open
// in system32 and some (resolver) do not by default have
// permissions to create files there
if ( fretry == 0 )
{
strncpy( pnameBuf, pszLogFile, MAX_PATH );
}
else
{
pnameBuf[0] = '\\';
strncpy( pnameBuf+1, pszLogFile, MAX_PATH-1 );
}
pnameBuf[MAX_PATH-1] = 0;
#if 0
// jeff changes -- don't have time to fix up now
// file wrapping should handle this sort of thing
//
// Save off the current copy as ".prev"
//
strncpy( prevName, DnsDebugFileName, MAX_PATH );
strcat( prevName, ".prev" );
MoveFileEx(
DnsDebugFileName,
prevName,
MOVEFILE_REPLACE_EXISTING );
DnsDebugFileHandle = CreateFile(
DnsDebugFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
0,
NULL
);
#endif
hfile = CreateFile(
pnameBuf,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
0,
NULL
);
// on failure, retry once
if ( hfile == NULL || hfile == (HANDLE)INVALID_HANDLE_VALUE )
{
if ( !fretry )
{
fretry++;
continue;
}
hfile = NULL;
}
g_DnsDbgInfo.hFile = hfile;
g_DnsDbgInfo.FileWrapSize = WrapSize;
break;
}
//
// initialize console
//
if ( IS_DNSDBG_ON( CONSOLE ) )
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
COORD coord;
AllocConsole();
GetConsoleScreenBufferInfo(
GetStdHandle(STD_OUTPUT_HANDLE),
&csbi
);
coord.X = (SHORT)(csbi.srWindow.Right - csbi.srWindow.Left + 1);
coord.Y = (SHORT)((csbi.srWindow.Bottom - csbi.srWindow.Top + 1) * 20);
SetConsoleScreenBufferSize(
GetStdHandle(STD_OUTPUT_HANDLE),
coord
);
g_DnsDbgInfo.fConsole = TRUE;
}
//
// set "global" debug file info
//
// dnsapi.dll serves as storage for common dns client
// debug file if that is desired; this lets applications
// push all dns debug output into a single file
//
// currently push both file and debug flag value
// note, we don't push debug file ptr as don't know
// whose memory becomes invalid first
//
if ( fSetGlobals && g_DnsDbgInfo.hFile )
{
DnsApiSetDebugGlobals(
&g_DnsDbgInfo // set our info as global
);
}
Done:
//
// use "global" (dnsapi.dll) debugging
// - copy in our info if no existing info
// - set to use global info blob
//
// two levels
// - only using file
// - using file and debug flags
if ( fUseGlobalFile &&
pinfoGlobal )
{
// copy in our new info if no global info exists
if ( !pinfoGlobal->hFile &&
g_DnsDbgInfo.hFile )
{
DnsApiSetDebugGlobals( &g_DnsDbgInfo );
}
// point at global info
g_pDbgInfo = pinfoGlobal;
g_DbgRedirected = TRUE;
if ( fUseGlobalFlag )
{
pDnsDebugFlag = (PDWORD) pinfoGlobal;
}
// avoid double cleanup
// - clear the handle in your modules blob
g_DnsDbgInfo.hFile = NULL;
}
//
// use print locking for debug locking
//
DnsPrint_InitLocking( NULL );
DNSDBG( ANY, (
"Initialized debugging:\n"
"\tpDbgInfo %p\n"
"\t&DnsDbgInfo %p\n"
"\tfile (param) %s\n"
"\thFile %p\n"
"\tpDbgInfo->Flag %08x\n"
"\tpDnsDebugFlag %p\n"
"\t*pDnsDebugFlag %08x\n"
"DnsLib compiled on %s at %s\n",
g_pDbgInfo,
&g_DnsDbgInfo,
pszLogFile,
g_pDbgInfo->hFile,
g_pDbgInfo->Flag,
pDnsDebugFlag,
*pDnsDebugFlag,
__DATE__,
__TIME__ ));
} // Dns_StartDebug
#if 0
VOID
Dns_StartDebugEx(
IN DWORD dwFlag,
IN PSTR pszFlagFile,
IN OUT PDWORD pdwFlag,
IN PSTR pszLogFile,
IN DWORD dwWrapSize,
IN BOOL fUseGlobalFile,
IN BOOL fUseGlobalFlag,
IN BOOL fSetGlobals
)
/*++
Routine Description:
Initialize debugging.
Only current task is to read and set debug flags.
Arguments:
dwFlag -- debug flags
pszFlagFile -- name of file containing debug flags
pdwFlag -- ptr to DWORD to receive debug flags
pszLogFile -- log file name
dwWrapSize -- log file wrap size
Return Value:
None.
--*/
{
DNS_DEBUG_INIT info;
RtlZeroMemory
&info,
sizeof(info) );
info.pszFlagFile = pszFlagFile;
info.DebugFlags = dwFlag;
info.pDebugFlags = pdwFlag;
info.pszLogFile = pszLogFile;
info.dwWrapSize = dwWrapSize;
info.fUseGlobalFile = fUseGlobalFile;
info.fUseGlobalFlag = fUseGlobalFlag;
info.fSetGlobals = fSetGlobals;
privateStartDebug( &info );
}
#endif
VOID
Dns_StartDebug(
IN DWORD dwFlag,
IN PSTR pszFlagFile,
IN OUT PDWORD pdwFlag,
IN PSTR pszLogFile,
IN DWORD dwWrapSize
)
/*++
Routine Description:
Initialize debugging.
Only current task is to read and set debug flags.
Arguments:
dwFlag -- debug flags
pszFlagFile -- name of file containing debug flags
pdwFlag -- ptr to DWORD to receive debug flags
pszLogFile -- log file name
dwWrapSize -- log file wrap size
Return Value:
None.
--*/
{
Dns_StartDebugEx(
dwFlag,
pszFlagFile,
pdwFlag,
pszLogFile,
dwWrapSize,
FALSE,
FALSE,
FALSE );
}
VOID
Dns_EndDebug(
VOID
)
/*++
Routine Description:
Terminate DNS debugging for shutdown.
Close debug file.
Arguments:
None.
Return Value:
None.
--*/
{
// close file
// - but only your dnslib instance
// - shared global file is closed by dnsapi
if ( g_DnsDbgInfo.hFile )
{
CloseHandle( g_DnsDbgInfo.hFile );
g_DnsDbgInfo.hFile = NULL;
}
}
PDNS_DEBUG_INFO
Dns_SetDebugGlobals(
IN OUT PDNS_DEBUG_INFO pInfo
)
/*++
Routine Description:
Exposure of debug globals.
The purpose of this is to allow dnsapi.dll to use it's globals
to allow common debug file. I'm using one routine for both
get and set to mimize the interfaces.
Note however, that this is NOT the routine that routines in
this module use to get cross-module debugging. They MUST call
the actual dnsapi.dll routine so that they are attaching
to the dnsapi's dnslib debugging globls not the ones with the
dnslib statically linked into their module.
Arguments:
pInfo -- local info to use as global info
Return Value:
Ptr to global info
--*/
{
//
// verify valid info coming in
// - must have file handle
//
//
// Implementation note:
//
// There are several issues to deal with when doing this
// - multiple redirection
// getting everyone to point at same blob
// solutions:
// - either double pointer (they read dnsapi.dll
// pointer
// - copy into dnsapi.dll the info
// - locking
// - broad scale print of structs
// - cleanup
// - no double close of handle
// - memory sections disappearing while some dll
// or exe still printing
//
// Approachs:
// 1) redirect blob pointer
// blob could expand to include actual print locks
// 2) copy info into single blob
// 3) expose debug routines
//
//
// Perhaps best approach might be to expose the dnsapi.dll
// printing
// - solves locking (at detail level), doesn't prevent breakup
// of high level printing unless it also redirected
// - can be done at the private level after parsing to va_arg
// - solves all the cleanup
// - they can be dumb stubs in non-debug binary, and dnslib
// routines can default to self if can't call dnsapi.dll
// routines
//
// Then redirection is simply
// - yes i use it -- redirection on each use
// - i want my file (and params) to BE used
//
#if 1
//
// copy over "i-want-to-be-global" callers context
//
// note: we're in dnsapi.dll here and should always be
// pointed at our own context -- we can change that
// later if desired
//
// note
// - lock during copy to be safe
// - don't leak existing handle
// - protect global handle from double close
//
if ( pInfo )
{
DnsPrint_Lock();
DNS_ASSERT( g_pDbgInfo == &g_DnsDbgInfo );
if ( pInfo->hFile )
{
HANDLE htemp = g_pDbgInfo->hFile;
RtlCopyMemory(
& g_DnsDbgInfo,
pInfo,
sizeof(*pInfo) );
g_pDbgInfo = &g_DnsDbgInfo;
pDnsDebugFlag = (PDWORD)&g_DnsDbgInfo;
CloseHandle( htemp );
}
DnsPrint_Unlock();
}
#else
//
// point dnsapi.dll debugging global at this context
// which becomes "global"
// note: essential this is last writer wins, but this
// should be fine for our purpuse (dnsup and resolver)
// as these processes init the debug after the
// dll loads
//
// problem with this approach is that folks redirected
// onto dnsapi.dll do not get new info when it is
// redirected (into dnsup)
if ( pInfo && pInfo->hFile )
{
g_pDbgInfo = pInfo;
pDnsDebugFlag = (PDWORD)pInfo;
}
#endif
return g_pDbgInfo;
}
#if 0
VOID
privateSyncGlobalDebug(
VOID
)
/*++
Routine Description:
Sync up with global debug.
Get dnslib debugging in line with "global" debugging if
that is desired for this dnslib instance.
Arguments:
None.
Return Value:
None
--*/
{
if ( !g_DbgRedirected )
{
return;
}
// sync with global values
}
#endif
VOID
DnsDbg_WrapLogFile(
VOID
)
/*++
Routine Description:
Wrap the log file.
Arguments:
None.
Return Value:
None.
--*/
{
CHAR backupName[ MAX_PATH+10 ];
HANDLE hfile;
//
// note, need to lock as file handle used in DnsDbg_Flush()
// outside print routine
//
DnsPrint_Lock();
hfile = g_pDbgInfo->hFile;
if ( hfile )
{
FlushFileBuffers( hfile );
CloseHandle( hfile );
}
strcpy( backupName, g_pDbgInfo->FileName );
if ( g_pDbgInfo->FileWrapCount == 0 )
{
strcat( backupName, ".first" );
}
else
{
strcat( backupName, ".last" );
}
MoveFileEx(
g_pDbgInfo->FileName,
backupName,
MOVEFILE_REPLACE_EXISTING
);
hfile = CreateFile(
g_pDbgInfo->FileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
0,
NULL
);
if ( hfile == (HANDLE)INVALID_HANDLE_VALUE )
{
hfile = NULL;
}
g_pDbgInfo->hFile = hfile;
g_pDbgInfo->FileWrapCount++;
g_pDbgInfo->FileCurrentSize = 0;
DnsPrint_Unlock();
}
VOID
privateDnsDebugPrint(
IN PBYTE pOutputBuffer,
IN BOOL fPrintContext
)
/*++
Routine Description:
Private DNS debug print that does actual print.
May print to any of
- debugger
- console window
- debug log file
Arguments:
pOutputBuffer -- bytes to print
fPrintContext
- TRUE to print thread context
- FALSE otherwise
Return Value:
None.
--*/
{
DWORD length;
BOOL ret;
//
// DCR: nice to automatically shut down console print when debugging
// it would be cool to be able to have all flags on, and detect
// when in ntsd, so that we don't get duplicated output
//
//
// lock print to keep atomic even during wrap
// - note use Print lock, which exists even in retail builds
// Dbg lock is defined away
//
DnsPrint_Lock();
//
// catch and timestamp thread context switches
//
if ( fPrintContext )
{
DWORD threadId = GetCurrentThreadId();
BOOL fcontextSwitch = (g_pDbgInfo->LastThreadId != threadId);
SYSTEMTIME st;
BOOL fdoPrint = FALSE;
// get time
// - if have context switch
// - or putting in debug timestamps
//
// DCR: maybe have global that set to put in timestamps and
// can set interval
//
// DCR: lock safe timestamps
// better would be "lock-safe" timestamps that are printed
// only when take the print lock -- then they would never
// interrupt the a multi-part print
// one way might be to test recursive depth of print CS
// otherwise must change to lock that includes this
// code
if ( fcontextSwitch
||
(pDnsDebugFlag && (*pDnsDebugFlag & DNS_DBG_TIMESTAMP)) )
{
GetLocalTime( &st );
if ( g_pDbgInfo->LastSecond != st.wSecond )
{
fdoPrint = TRUE;
}
}
if ( fcontextSwitch || fdoPrint )
{
CHAR printBuffer[ 200 ];
length = sprintf(
printBuffer,
fcontextSwitch ?
"\n%02d:%02d:%02d:%03d DBG switch from thread %X to thread %X\n" :
"%02d:%02d:%02d:%03d DBG tick\n",
st.wHour,
st.wMinute,
st.wSecond,
st.wMilliseconds,
g_pDbgInfo->LastThreadId,
threadId );
g_pDbgInfo->LastSecond = st.wSecond;
g_pDbgInfo->LastThreadId = threadId;
// print context
// - suppress context even through thread test
// would break recursion
privateDnsDebugPrint(
printBuffer,
FALSE // suppress context
);
}
}
//
// output -- to debugger, console, file
//
if ( IS_DNSDBG_ON( DEBUGGER ) )
{
OutputDebugString( pOutputBuffer );
}
if ( IS_DNSDBG_ON( CONSOLE ) )
{
if ( g_pDbgInfo->fConsole )
{
length = strlen( pOutputBuffer );
ret = WriteFile(
GetStdHandle(STD_OUTPUT_HANDLE),
(PVOID) pOutputBuffer,
length,
&length,
NULL
);
#if 0
if ( !ret )
{
DnsDbg_PrintfToDebugger(
"DnsDbg_Printf: console WriteFile failed: %ld\n",
GetLastError() );
}
#endif
}
}
//
// write to debug log
//
if ( IS_DNSDBG_ON( FILE ) )
{
if ( g_pDbgInfo->hFile )
{
length = strlen( pOutputBuffer );
ret = WriteFile(
g_pDbgInfo->hFile,
(PVOID) pOutputBuffer,
length,
&length,
NULL
);
if ( !ret )
{
DnsDbg_PrintfToDebugger(
"DnsDbg_Printf: file WriteFile failed: %ld\n",
GetLastError() );
}
//
// if wrapping debug log file
// - move current log to backup file
// <file>.first on first wrap
// <file>.last on subsequent wraps
// - reopen current file name
//
g_pDbgInfo->FileCurrentSize += length;
if ( g_pDbgInfo->FileWrapSize &&
g_pDbgInfo->FileWrapSize <= g_pDbgInfo->FileCurrentSize )
{
DnsDbg_WrapLogFile();
}
else if ( IS_DNSDBG_ON( FLUSH ) )
{
FlushFileBuffers( g_pDbgInfo->hFile );
}
}
}
DnsPrint_Unlock();
} // privateDnsDebugPrint
VOID
privateFormatAndPrintBuffer(
IN LPSTR Format,
IN va_list ArgList
)
/*++
Routine Description:
Arguments to formatted buffer print.
This helper routine exists to avoid duplicating buffer
overflow logic in DnsDbg_Printf() and DnsDbg_PrintRoutine()
The overflow logic is required because the default stack size
has been chopped down in whistler making is easy to generate
stack expansion exceptions under stress. And of course this
means the stress guys send me these B.S. stress failures.
Solution is to put a small buffer on the stack for perf, then
allocate a larger buffer if the print doesn't fit into the
stack buffer.
Arguments:
Format -- standard C format string
ArgList -- standard arg list
Return Value:
None.
--*/
{
CHAR stackBuffer[ DNS_STACK_PRINT_BUFFER_LENGTH ];
ULONG bufLength;
DWORD lastError;
INT count;
PCHAR pprintBuffer;
PCHAR pheapBuffer = NULL;
//
// save last error so any WriteFile() failures don't mess it up
//
lastError = GetLastError();
//
// write formatted print buffer
//
// - first try stack buffer
// - if fails, try heap buffer
// - use best, always NULL terminate
//
bufLength = DNS_STACK_PRINT_BUFFER_LENGTH;
pprintBuffer = stackBuffer;
do
{
#if 0
// code for debugging print lock problems
PBYTE ptemp = pprintBuffer;
if ( pDnsAtomicPrintCs )
{
ptemp += sprintf(
ptemp,
"(%d) ",
pDnsAtomicPrintCs->RecursionCount
);
}
count = _vsnprintf(
ptemp,
bufLength-1-(ptemp-pprintBuffer),
Format,
ArgList );
#else
count = _vsnprintf(
pprintBuffer,
bufLength-1,
Format,
ArgList );
#endif
pprintBuffer[ bufLength-1 ] = 0;
if ( count > 0 || pheapBuffer )
{
break;
}
// try again with heap buffer
pheapBuffer = ALLOCATE_HEAP( DNS_HEAP_PRINT_BUFFER_LENGTH );
if ( !pheapBuffer )
{
break;
}
pprintBuffer = pheapBuffer;
bufLength = DNS_HEAP_PRINT_BUFFER_LENGTH;
}
while( 1 );
va_end( ArgList );
// do the real print
privateDnsDebugPrint( pprintBuffer, TRUE );
if ( pheapBuffer )
{
FREE_HEAP( pheapBuffer );
}
// restore LastError() if changed
if ( lastError != GetLastError() )
{
SetLastError( lastError );
}
}
VOID
DnsDbg_Printf(
IN LPSTR Format,
...
)
/*++
Routine Description:
DNS debug print with printf semantics.
May print to any of
- debugger
- console window
- debug log file
Arguments:
pContext -- dummny context to match signature of PRINT_ROUTINE function
Format -- standard C format string
... -- standard arg list
Return Value:
None.
--*/
{
va_list arglist;
va_start( arglist, Format );
privateFormatAndPrintBuffer(
Format,
arglist );
}
VOID
DnsDbg_PrintRoutine(
IN OUT PPRINT_CONTEXT pContext,
IN LPSTR Format,
...
)
/*++
Routine Description:
DNS debug print with PRINT_ROUTINE semantics.
Arguments:
pContext -- dummny context to match signature of PRINT_ROUTINE function
Format -- standard C format string
... -- standard arg list
Return Value:
None.
--*/
{
va_list arglist;
va_start( arglist, Format );
privateFormatAndPrintBuffer(
Format,
arglist );
}
VOID
DnsDbg_Flush(
VOID
)
/*++
Routine Description:
Flushes DNS debug printing to disk.
Arguments:
None
Return Value:
None.
--*/
{
//
// need to lock to protect handle as this maybe called
// 1) directly as this is exposed in dnslib.h
// 2) from hard ASSERT()
// and a print which wraps may be ongoing
//
if ( g_pDbgInfo->hFile )
{
HANDLE hfile;
DnsPrint_Lock();
if ( hfile = g_pDbgInfo->hFile )
{
FlushFileBuffers( hfile );
}
DnsPrint_Unlock();
}
}
VOID
DnsDbg_PrintfToDebugger(
IN LPSTR Format,
...
)
/*++
Routine Description:
Print to debugger. Win95 has no DbgPrint().
Arguments:
Format -- standard C format string
... -- standard arg list
Return Value:
None.
--*/
{
va_list arglist;
CHAR outputBuffer[ DNS_STACK_PRINT_BUFFER_LENGTH+1 ];
ULONG length;
BOOL ret;
va_start( arglist, Format );
_vsnprintf( outputBuffer, DNS_STACK_PRINT_BUFFER_LENGTH, Format, arglist );
va_end( arglist );
outputBuffer[ DNS_STACK_PRINT_BUFFER_LENGTH ] = 0;
OutputDebugString( outputBuffer );
}
//
// Debug utilities
//
// Other debug routines are coded generically as print routines (print.c)
// and are macroed to debug routines by choosing DnsDbg_Printf() as the
// print function.
//
#if DBG
VOID
DnsDbg_CSEnter(
IN PCRITICAL_SECTION pLock,
IN LPSTR pszLockName,
IN LPSTR pszFile,
IN INT LineNo
)
{
DnsDbg_Printf(
"\nENTERING %s lock %p in %s, line %d.\n",
pszLockName,
pLock,
pszFile,
LineNo );
EnterCriticalSection( pLock );
DnsDbg_Printf(
"\nHOLDING %s lock %p in %s, line %d.\n",
pszLockName,
pLock,
pszFile,
LineNo );
}
VOID
DnsDbg_CSLeave(
IN PCRITICAL_SECTION pLock,
IN LPSTR pszLockName,
IN LPSTR pszFile,
IN INT LineNo
)
{
DnsDbg_Printf(
"\nRELEASING %s lock %p in %s, line %d.\n",
pszLockName,
pLock,
pszFile,
LineNo );
LeaveCriticalSection( pLock );
}
#endif
//
// End of debug.c
//