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.
 
 
 
 
 
 

505 lines
14 KiB

/*
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
(C) Copyright 1998
All rights reserved.
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
Portions of this software are:
(C) Copyright 1994 TriplePoint, Inc. -- http://www.TriplePoint.com
License to use this software is granted under the same terms
outlined in the Microsoft Windows Device Driver Development Kit.
(C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
License to use this software is granted under the terms outlined in
the Microsoft Windows Device Driver Development Kit.
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@doc INTERNAL TpiDebug TpiDebug_c
@module TpiDebug.c |
This module, along with <f TpiDebug\.h>, implements code and macros to
support NDIS driver debugging. This file must be linked with the driver
to support debug dumps and logging.
@comm
The code and macros defined by these modules is only generated during
development debugging when the C pre-processor macro flag (DBG == 1).
If (DBG == 0) no code will be generated, and all debug strings will be
removed from the image.
This is a device independent module which can be re-used, without
change, by any driver or application.
@head3 Contents |
@index class,mfunc,func,msg,mdata,struct,enum | TpiDebug_c
@end
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
*/
#if defined(_EXE_) || defined(_DLL_)
typedef char CHAR, *PCHAR;
typedef unsigned char UCHAR, *PUCHAR;
typedef unsigned short USHORT, *PUSHORT;
typedef unsigned long ULONG, *PULONG;
typedef unsigned int *PUINT;
# include <windows.h>
#elif defined(_VXD_)
# include <basedef.h>
# include <vmm.h>
# pragma VxD_LOCKED_CODE_SEG
# pragma VxD_LOCKED_DATA_SEG
#else
# include <windef.h>
#endif
#include "TpiDebug.h"
#if DBG
/*
// Sometimes the debug output seriously impacts the run-time performance,
// so it is necessary to turn off the debug output. In this case, you can
// capture some debug trace information into the DbgLogBuffer, and it can
// be examined later without impacting the run-time performance.
*/
#define DBG_LOG_ENTRIES 100 // Maximum number of FIFO log entries.
#define DBG_LOG_SIZE 128 // Maximum number of bytes per entry.
#if defined(_VXD_)
DBG_SETTINGS DbgSettings = { DBG_DEFAULTS, {'V','X','D',0 } };
#elif defined(_EXE_)
DBG_SETTINGS DbgSettings = { DBG_DEFAULTS, {'E','X','E',0 } };
#elif defined(_DLL_)
DBG_SETTINGS DbgSettings = { DBG_DEFAULTS, {'D','L','L',0 } };
#elif defined(_SYS_)
DBG_SETTINGS DbgSettings = { DBG_DEFAULTS, {'S','Y','S',0 } };
#else
DBG_SETTINGS DbgSettings = { DBG_DEFAULTS, {'T','P','I',0 } };
#endif
PDBG_SETTINGS DbgInfo = &DbgSettings;
UINT DbgLogIndex = 0;
UCHAR DbgLogBuffer[DBG_LOG_ENTRIES][DBG_LOG_SIZE] = { { 0 } };
/* @doc INTERNAL TpiDebug TpiDebug_c DbgPrintData
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DbgPrintData> outputs data to the debug display formatted in HEX and
ASCII for easy viewing.
<f Note>: This routine is used for debug output only.
It is not compiled into the retail version.
@ex <tab> |
DbgPrintData(ReceiveBuffer, 14, 0); // Packet header
DbgPrintData(ReceiveBuffer+14, BytesReceived-14, 14); // Packet data
0000: ff ff ff ff ff ff 0a 22 23 01 02 03 00 10 ......."#.....
000E: 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 40 ABCDEFGHIJKMNOPQ
*/
VOID DbgPrintData(
IN PUCHAR Data, // @parm
// Pointer to first byte of data to be displayed.
IN UINT NumBytes, // @parm
// Number of bytes to be displayed.
IN ULONG Offset // @parm
// Value to be added to the offset counter displayed at the start of each
// line. This is useful for viewing data whose base offset is relative to
// another, non-zero starting address.
)
{
UINT LineStart;
UINT LineIndex;
/*
// Display the caller's buffer with up to 16 bytes per line.
*/
for (LineStart = 0; LineStart < NumBytes; LineStart += 16)
{
/*
// Display the starting offset of the line.
*/
DbgPrint("%04lx: ", LineStart + Offset);
/*
// Display a line of HEX byte values.
*/
for (LineIndex = LineStart; LineIndex < (LineStart+16); LineIndex++)
{
if (LineIndex < NumBytes)
{
DbgPrint("%02x ",(UINT)((UCHAR)*(Data+LineIndex)));
}
else
{
DbgPrint(" ");
}
}
DbgPrint(" "); // A little white space between HEX and ASCII.
/*
// Display the corresponding ASCII byte values if they are printable.
// (i.e. 0x20 <= N <= 0x7F).
*/
for (LineIndex = LineStart; LineIndex < (LineStart+16); LineIndex++)
{
if (LineIndex < NumBytes)
{
char c = *(Data+LineIndex);
if (c < ' ' || c > 'z')
{
c = '.';
}
DbgPrint("%c", (UINT)c);
}
else
{
DbgPrint(" ");
}
}
DbgPrint("\n"); // End of line.
}
}
/* @doc INTERNAL TpiDebug TpiDebug_c DbgQueueData
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DbgQueueData> saves data to the DbgLogBuffer so it can be viewed later
with the debugger.
<f Note>: This routine is used for debug output only.
It is not compiled into the retail version.
*/
VOID DbgQueueData(
IN PUCHAR Data, // @parm
// Pointer to first byte of data to be displayed.
IN UINT NumBytes, // @parm
// Number of bytes to be displayed.
IN UINT Flags // @parm
// A flag descriptor to help identify the log entry.
)
{
/*
// Point to the next available entry in the DbgLogBuffer.
*/
PUCHAR LogEntry = &DbgLogBuffer[DbgLogIndex++][0];
/*
// Wrap around on the next entry if needed.
*/
if (DbgLogIndex >= DBG_LOG_ENTRIES)
{
DbgLogIndex = 0;
}
/*
// Save the flags parameter in the first WORD of the log buffer.
*/
*((PUSHORT) LogEntry) = (USHORT) Flags;
LogEntry += sizeof(PUSHORT);
/*
// Save the NumBytes parameter in the second WORD of the log buffer.
*/
*((PUSHORT) LogEntry) = (USHORT) NumBytes;
LogEntry += sizeof(NumBytes);
/*
// Don't try to save more than we have room for.
*/
if (NumBytes > DBG_LOG_SIZE - sizeof(USHORT) * 2)
{
NumBytes = DBG_LOG_SIZE - sizeof(USHORT) * 2;
}
/*
// Save the rest of the data in the remaining portion of the log buffer.
*/
while (NumBytes--)
{
*LogEntry++ = *Data++;
}
}
/* @doc INTERNAL TpiDebug TpiDebug_c DbgBreakPoint
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func VOID | DbgBreakPoint |
<f DbgBreakPoint> is defined in the NT kernel for SYS drivers, but we
override it here so we can support for SYS's, EXE's, VXD's, and DLL's.
*/
#if defined(_MSC_VER) && (_MSC_VER <= 800)
// Must be building with 16-bit compiler
VOID __cdecl DbgBreakPoint(VOID)
#else
// Must be building with 32-bit compiler
VOID __stdcall DbgBreakPoint(VOID)
#endif
{
#if !defined(_WIN64)
__asm int 3;
#endif
}
/* @doc INTERNAL TpiDebug TpiDebug_c DbgPrint
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func ULONG __cdecl | DbgPrint |
<f DbgPrint> is defined in the kernel for SYS drivers, otherwise it is
supported here for EXE's, VXD's, and DLL's.
@parm PCHAR | Format |
printf style format string.
@parm OPTIONAL | Params |
Zero or more optional parameters as needed by the format string.
*/
#if defined(_VXD_)
#if !defined(NDIS_DOS)
ULONG __cdecl DbgPrint(PCHAR Format, ...)
{
ULONG result = 0;
__asm lea eax, (Format + 4)
__asm push eax
__asm push Format
VMMCall(_Debug_Printf_Service)
__asm add esp, 4*2
__asm mov result, eax
return (result);
}
#endif
#elif defined(_EXE_) || defined(_DLL_)
UCHAR DbgString[1024];
ULONG __cdecl DbgPrint(PCHAR Format, ...)
{
ULONG result;
result = wvsprintf(DbgString, Format, ((PCHAR) &Format) + sizeof(PCHAR));
OutputDebugString(DbgString);
if (result >= sizeof(DbgString))
{
// We just blew the stack!
// Since we can't return, we have to generate a stack-fault interrupt
__asm int 1;
__asm int 3;
__asm int 12;
}
return (result);
}
#endif // DbgPrint
/*
* If DBG_SILENT is set, all TERSE debug goes here. An assertion
* will dump the block.
*/
#define DBG_QUEUE_LEN 4096
UINT DbgIndex=0;
UINT DbgLen=0;
UCHAR DbgQueue[DBG_QUEUE_LEN] = {0};
UCHAR DbgLock=0;
/* @doc INTERNAL TpiDebug TpiDebug_c DbgDumpSilentQueue
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DbgDumpSilentQueue> dumps the contents of the silent debug queue to
the monitor.
*/
void DbgDumpSilentQueue(
void
)
{
if (DbgLen >= DBG_QUEUE_LEN)
{
DbgPrintData(
&DbgQueue[DbgIndex],
DBG_QUEUE_LEN-DbgIndex,
0);
if (DbgIndex)
{
DbgPrint("\n");
DbgPrintData(
DbgQueue,
DbgIndex-1,
0);
}
DbgPrint("\n");
}
else if (DbgLen)
{
DbgPrintData(
DbgQueue,
DbgIndex-1,
0);
DbgPrint("\n");
}
}
#if NDIS_NT
/* @doc INTERNAL TpiDebug TpiDebug_c _assert
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f _assert> overrides the assertion function provided by the operating
system. Dumps the contents of debug queue, prints the assertion, and
then traps to the debugger. Used for debugging only.
*/
void _CRTAPI1 _assert(
void * exp, // @parm
// ASCIIZ pointer to the expression causing the fault.
void * file, // @parm
// ASCIIZ pointer to the name of the file.
unsigned line // @parm
// Line offset within the file where the assertion is defined.
)
{
DbgDumpSilentQueue();
DbgPrint("Assertion Failed: %s at %s:%d\n",exp,file,line);
DbgBreakPoint();
}
#endif
/* @doc INTERNAL TpiDebug TpiDebug_c DbgSilentQueue
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DbgSilentQueue> logs a string to the debug queue which can be
displayed later using <f DbgDumpSilentQueue>. Used for debugging only.
*/
void DbgSilentQueue(
PUCHAR str // @parm
// Pointer to string to be placed in DbgQueue.
)
{
/*
// If the debug queue is busy, just
// bail out.
*/
if ((++DbgLock) > 1)
{
goto exit;
}
while (str && *str)
{
DbgQueue[DbgIndex] = *str++;
DbgLen++;
if ((++DbgIndex) >= DBG_QUEUE_LEN)
{
DbgIndex = 0;
}
}
exit:
DbgLock--;
}
/* @doc INTERNAL TpiDebug TpiDebug_c DbgPrintFieldTable
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DbgPrintFieldTable> displays the contents of a C data structure in
a formatted output to the debugger. This can be used when symbolic
debugging is not available on the target platform.
*/
void DbgPrintFieldTable(
IN PDBG_FIELD_TABLE pFields, // @parm
// A pointer to an array of field records <t DBG_FIELD_TABLE>.
IN PUCHAR pBaseContext, // @parm
// References the base of the structure where the values will be displayed
// from. This should be a pointer to the first byte of the structure.
IN PUCHAR pBaseName // @parm
// Pointer to C string containing the name of the structure being displayed.
)
{
DbgPrint("STRUCTURE: @0x%08X %s\n", pBaseContext, pBaseName);
while (pFields->FieldName)
{
switch (pFields->FieldType)
{
case sizeof(ULONG):
DbgPrint("\t%04X: %-32s=0x%08X\n", pFields->FieldOffset,
pFields->FieldName,
*(PULONG)(pBaseContext+pFields->FieldOffset));
break;
case sizeof(USHORT):
DbgPrint("\t%04X: %-32s=0x%04X\n", pFields->FieldOffset,
pFields->FieldName,
*(PUSHORT)(pBaseContext+pFields->FieldOffset));
break;
case sizeof(UCHAR):
DbgPrint("\t%04X: %-32s=0x%02X\n", pFields->FieldOffset,
pFields->FieldName,
*(PUCHAR)(pBaseContext+pFields->FieldOffset));
break;
default:
ASSERT(0);
break;
}
pFields++;
}
}
#endif // DBG