370 lines
8.4 KiB
C
370 lines
8.4 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
debug.c
|
||
|
||
Abstract:
|
||
|
||
This component of netbios runs in the user process and can ( when
|
||
built in a debug kernel) will log to either the console or through the
|
||
kernel debugger.
|
||
|
||
Author:
|
||
|
||
Colin Watson (ColinW) 24-Jun-91
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#if DBG
|
||
|
||
#include <netb.h>
|
||
#include <stdarg.h>
|
||
#include <stdio.h>
|
||
|
||
ULONG NbDllDebug = 0x0;
|
||
#define NB_DLL_DEBUG_NCB 0x00000001 // print all NCB's submitted
|
||
#define NB_DLL_DEBUG_NCB_BUFF 0x00000002 // print buffers for NCB's submitted
|
||
|
||
BOOL UseConsole = FALSE;
|
||
BOOL UseLogFile = TRUE;
|
||
HANDLE LogFile = INVALID_HANDLE_VALUE;
|
||
#define LOGNAME (LPTSTR) TEXT("netbios.log")
|
||
|
||
LONG NbMaxDump = 128;
|
||
|
||
// Macro used in DisplayNcb
|
||
#define DISPLAY_COMMAND( cmd ) \
|
||
case cmd: NbPrintf(( #cmd )); break;
|
||
|
||
VOID
|
||
FormattedDump(
|
||
PCHAR far_p,
|
||
LONG len
|
||
);
|
||
|
||
VOID
|
||
HexDumpLine(
|
||
PCHAR pch,
|
||
ULONG len,
|
||
PCHAR s,
|
||
PCHAR t
|
||
);
|
||
|
||
VOID
|
||
DisplayNcb(
|
||
IN PNCBI pncbi
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays on the standard output stream the contents
|
||
of the Ncb.
|
||
|
||
Arguments:
|
||
|
||
IN PNCBI - Supplies the NCB to be displayed.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
if ( (NbDllDebug & NB_DLL_DEBUG_NCB) == 0 ) {
|
||
return;
|
||
}
|
||
|
||
NbPrintf(( "PNCB %#010lx\n", pncbi));
|
||
|
||
NbPrintf(( "ncb_command %#04x ", pncbi->ncb_command));
|
||
switch ( pncbi->ncb_command & ~ASYNCH ) {
|
||
DISPLAY_COMMAND( NCBCALL );
|
||
DISPLAY_COMMAND( NCBLISTEN );
|
||
DISPLAY_COMMAND( NCBHANGUP );
|
||
DISPLAY_COMMAND( NCBSEND );
|
||
DISPLAY_COMMAND( NCBRECV );
|
||
DISPLAY_COMMAND( NCBRECVANY );
|
||
DISPLAY_COMMAND( NCBCHAINSEND );
|
||
DISPLAY_COMMAND( NCBDGSEND );
|
||
DISPLAY_COMMAND( NCBDGRECV );
|
||
DISPLAY_COMMAND( NCBDGSENDBC );
|
||
DISPLAY_COMMAND( NCBDGRECVBC );
|
||
DISPLAY_COMMAND( NCBADDNAME );
|
||
DISPLAY_COMMAND( NCBDELNAME );
|
||
DISPLAY_COMMAND( NCBRESET );
|
||
DISPLAY_COMMAND( NCBASTAT );
|
||
DISPLAY_COMMAND( NCBSSTAT );
|
||
DISPLAY_COMMAND( NCBCANCEL );
|
||
DISPLAY_COMMAND( NCBADDGRNAME );
|
||
DISPLAY_COMMAND( NCBENUM );
|
||
DISPLAY_COMMAND( NCBUNLINK );
|
||
DISPLAY_COMMAND( NCBSENDNA );
|
||
DISPLAY_COMMAND( NCBCHAINSENDNA );
|
||
DISPLAY_COMMAND( NCBLANSTALERT );
|
||
DISPLAY_COMMAND( NCBFINDNAME );
|
||
|
||
// Extensions
|
||
DISPLAY_COMMAND( NCALLNIU );
|
||
DISPLAY_COMMAND( NCBQUICKADDNAME );
|
||
DISPLAY_COMMAND( NCBQUICKADDGRNAME );
|
||
DISPLAY_COMMAND( NCBACTION );
|
||
|
||
default: NbPrintf(( " Unknown type")); break;
|
||
}
|
||
if ( pncbi->ncb_command & ASYNCH ) {
|
||
NbPrintf(( " | ASYNCH"));
|
||
}
|
||
|
||
|
||
NbPrintf(( "\nncb_retcode %#04x\n", pncbi->ncb_retcode));
|
||
NbPrintf(( "ncb_lsn %#04x\n", pncbi->ncb_lsn));
|
||
NbPrintf(( "ncb_num %#04x\n", pncbi->ncb_num));
|
||
|
||
NbPrintf(( "ncb_buffer %#010lx\n",pncbi->ncb_buffer));
|
||
NbPrintf(( "ncb_length %#06x\n", pncbi->ncb_length));
|
||
|
||
NbPrintf(( "\nncb_callname and ncb->name\n"));
|
||
FormattedDump( pncbi->cu.ncb_callname, NCBNAMSZ );
|
||
FormattedDump( pncbi->ncb_name, NCBNAMSZ );
|
||
|
||
if (((pncbi->ncb_command & ~ASYNCH) == NCBCHAINSEND) ||
|
||
((pncbi->ncb_command & ~ASYNCH) == NCBCHAINSENDNA)) {
|
||
NbPrintf(( "ncb_length2 %#06x\n", pncbi->cu.ncb_chain.ncb_length2));
|
||
NbPrintf(( "ncb_buffer2 %#010lx\n",pncbi->cu.ncb_chain.ncb_buffer2));
|
||
}
|
||
|
||
NbPrintf(( "ncb_rto %#04x\n", pncbi->ncb_rto));
|
||
NbPrintf(( "ncb_sto %#04x\n", pncbi->ncb_sto));
|
||
NbPrintf(( "ncb_post %lx\n", pncbi->ncb_post));
|
||
NbPrintf(( "ncb_lana_num %#04x\n", pncbi->ncb_lana_num));
|
||
NbPrintf(( "ncb_cmd_cplt %#04x\n", pncbi->ncb_cmd_cplt));
|
||
|
||
NbPrintf(( "ncb_reserve\n"));
|
||
FormattedDump( ((PNCB)pncbi)->ncb_reserve, 14 );
|
||
|
||
NbPrintf(( "ncb_next\n"));
|
||
FormattedDump( (PCHAR)&pncbi->u.ncb_next, sizeof( LIST_ENTRY) );
|
||
NbPrintf(( "ncb_iosb\n"));
|
||
FormattedDump( (PCHAR)&pncbi->u.ncb_iosb, sizeof( IO_STATUS_BLOCK ) );
|
||
NbPrintf(( "ncb_event %#04x\n", pncbi->ncb_event));
|
||
|
||
if ( (NbDllDebug & NB_DLL_DEBUG_NCB_BUFF) == 0 ) {
|
||
NbPrintf(( "\n\n" ));
|
||
return;
|
||
}
|
||
|
||
switch ( pncbi->ncb_command & ~ASYNCH ) {
|
||
case NCBSEND:
|
||
case NCBCHAINSEND:
|
||
case NCBDGSEND:
|
||
case NCBSENDNA:
|
||
case NCBCHAINSENDNA:
|
||
if ( pncbi->ncb_retcode == NRC_PENDING ) {
|
||
|
||
//
|
||
// If pending then presumably we have not displayed the ncb
|
||
// before. After its been sent there isn't much point in displaying
|
||
// the buffer again.
|
||
//
|
||
|
||
NbPrintf(( "ncb_buffer contents:\n"));
|
||
FormattedDump( pncbi->ncb_buffer, pncbi->ncb_length );
|
||
}
|
||
break;
|
||
|
||
case NCBRECV:
|
||
case NCBRECVANY:
|
||
case NCBDGRECV:
|
||
case NCBDGSENDBC:
|
||
case NCBDGRECVBC:
|
||
case NCBENUM:
|
||
case NCBASTAT:
|
||
case NCBSSTAT:
|
||
case NCBFINDNAME:
|
||
if ( pncbi->ncb_retcode != NRC_PENDING ) {
|
||
// Buffer has been loaded with data
|
||
NbPrintf(( "ncb_buffer contents:\n"));
|
||
FormattedDump( pncbi->ncb_buffer, pncbi->ncb_length );
|
||
}
|
||
break;
|
||
|
||
case NCBCANCEL:
|
||
// Buffer has been loaded with the NCB to be cancelled
|
||
NbPrintf(( "ncb_buffer contents:\n"));
|
||
FormattedDump( pncbi->ncb_buffer, sizeof(NCB));
|
||
break;
|
||
}
|
||
NbPrintf(( "\n\n" ));
|
||
}
|
||
|
||
VOID
|
||
NbPrint(
|
||
char *Format,
|
||
...
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is equivalent to printf with the output being directed to
|
||
stdout.
|
||
|
||
Arguments:
|
||
|
||
IN char *Format - Supplies string to be output and describes following
|
||
(optional) parameters.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
va_list arglist;
|
||
char OutputBuffer[1024];
|
||
ULONG length;
|
||
|
||
if ( NbDllDebug == 0 ) {
|
||
return;
|
||
}
|
||
|
||
|
||
va_start( arglist, Format );
|
||
|
||
vsprintf( OutputBuffer, Format, arglist );
|
||
|
||
va_end( arglist );
|
||
|
||
if ( UseConsole ) {
|
||
DbgPrint( "%s", OutputBuffer );
|
||
} else {
|
||
length = strlen( OutputBuffer );
|
||
if ( LogFile == INVALID_HANDLE_VALUE ) {
|
||
if ( UseLogFile ) {
|
||
LogFile = CreateFile( LOGNAME,
|
||
GENERIC_WRITE,
|
||
FILE_SHARE_WRITE,
|
||
NULL,
|
||
OPEN_ALWAYS,
|
||
FILE_ATTRIBUTE_NORMAL,
|
||
NULL );
|
||
if ( LogFile == INVALID_HANDLE_VALUE ) {
|
||
// Could not access logfile so use stdout instead
|
||
UseLogFile = FALSE;
|
||
LogFile = GetStdHandle(STD_OUTPUT_HANDLE);
|
||
}
|
||
} else {
|
||
// Use the applications stdout file.
|
||
LogFile = GetStdHandle(STD_OUTPUT_HANDLE);
|
||
}
|
||
}
|
||
|
||
WriteFile( LogFile , (LPVOID )OutputBuffer, length, &length, NULL );
|
||
}
|
||
|
||
} // NbPrint
|
||
|
||
void
|
||
FormattedDump(
|
||
PCHAR far_p,
|
||
LONG len
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine outputs a buffer in lines of text containing hex and
|
||
printable characters.
|
||
|
||
Arguments:
|
||
|
||
IN far_p - Supplies buffer to be displayed.
|
||
IN len - Supplies the length of the buffer in bytes.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
ULONG l;
|
||
char s[80], t[80];
|
||
|
||
if ( len > NbMaxDump ) {
|
||
len = NbMaxDump;
|
||
}
|
||
|
||
while (len) {
|
||
l = len < 16 ? len : 16;
|
||
|
||
NbPrintf (("%lx ", far_p));
|
||
HexDumpLine (far_p, l, s, t);
|
||
NbPrintf (("%s%.*s%s\n", s, 1 + ((16 - l) * 3), "", t));
|
||
|
||
len -= l;
|
||
far_p += l;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
HexDumpLine(
|
||
PCHAR pch,
|
||
ULONG len,
|
||
PCHAR s,
|
||
PCHAR t
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine builds a line of text containing hex and printable characters.
|
||
|
||
Arguments:
|
||
|
||
IN pch - Supplies buffer to be displayed.
|
||
IN len - Supplies the length of the buffer in bytes.
|
||
IN s - Supplies the start of the buffer to be loaded with the string
|
||
of hex characters.
|
||
IN t - Supplies the start of the buffer to be loaded with the string
|
||
of printable ascii characters.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
static UCHAR rghex[] = "0123456789ABCDEF";
|
||
|
||
UCHAR c;
|
||
UCHAR *hex, *asc;
|
||
|
||
|
||
hex = s;
|
||
asc = t;
|
||
|
||
*(asc++) = '*';
|
||
while (len--) {
|
||
c = *(pch++);
|
||
*(hex++) = rghex [c >> 4] ;
|
||
*(hex++) = rghex [c & 0x0F];
|
||
*(hex++) = ' ';
|
||
*(asc++) = (c < ' ' || c > '~') ? (CHAR )'.' : c;
|
||
}
|
||
*(asc++) = '*';
|
||
*asc = 0;
|
||
*hex = 0;
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
|