|
|
/*++
Copyright (c) 1991-3 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:
--*/
#include "procs.h"
#if NWDBG
//
// Set DebugControl to 1 to open the logfile on the first NW call and close it
// on process exit.
//
int DebugCtrl = 0;
BOOL UseConsole = FALSE; BOOL UseLogFile = FALSE; BOOL Verbose = FALSE;
HANDLE LogFile = INVALID_HANDLE_VALUE; #define LOGNAME (LPTSTR) TEXT("c:\\nwapi16.log")
LONG NwMaxDump = SERVERNAME_LENGTH * MC; //128;
#define ERR_BUF_SIZE 260
#define NAME_BUF_SIZE 260
extern UCHAR CpuInProtectMode;
LPSTR ConvertFlagsToString( IN WORD FlagsRegister, OUT LPSTR Buffer );
WORD GetFlags( VOID );
VOID HexDumpLine( PCHAR pch, ULONG len, PCHAR s, PCHAR t );
VOID DebugControl( int Command ) /*++
Routine Description:
This routine controls what we output as debug information and where.
Arguments:
IN int Command
Return Value:
none.
--*/ {
switch (Command) { case 0: UseLogFile = TRUE; break;
case 1: UseConsole = TRUE; break;
case 2: if (LogFile != INVALID_HANDLE_VALUE) { CloseHandle(LogFile); LogFile = INVALID_HANDLE_VALUE; } UseLogFile = FALSE; UseConsole = FALSE; break;
case 8: Verbose = TRUE; // Same as 4 only chatty
DebugCtrl = 4;
case 4: UseLogFile = TRUE; break;
} NwPrint(("DebugControl %x\n", Command )); }
VOID NwPrintf( 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[200]; int length;
if (( UseConsole == FALSE ) && ( UseLogFile == FALSE )) { return; }
va_start( arglist, Format );
length = _vsnprintf( OutputBuffer, sizeof(OutputBuffer)-1, Format, arglist ); if (length < 0) { return; }
OutputBuffer[sizeof(OutputBuffer)-1] = '\0'; // in-case length= 199;
va_end( arglist );
if ( UseConsole ) { DbgPrint( "%s", OutputBuffer ); } else {
if ( LogFile == INVALID_HANDLE_VALUE ) { if ( UseLogFile ) { LogFile = CreateFile( LOGNAME, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (LogFile == INVALID_HANDLE_VALUE) { LogFile = CreateFile( LOGNAME, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); }
if ( LogFile == INVALID_HANDLE_VALUE ) { UseLogFile = FALSE; return; } } }
WriteFile( LogFile , (LPVOID )OutputBuffer, length, &length, NULL ); }
} // NwPrintf
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 (( UseConsole == FALSE ) && ( UseLogFile == FALSE )) { return; }
if (( len > NwMaxDump ) || ( len < 0 )) { len = NwMaxDump; }
while (len) { l = len < 16 ? len : 16;
NwPrint(("%lx ", far_p)); HexDumpLine (far_p, l, s, t); NwPrint(("%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;
}
VOID DisplayExtendedError(VOID) { TCHAR errorBuf[ERR_BUF_SIZE]; TCHAR nameBuf[NAME_BUF_SIZE]; DWORD errorCode; DWORD status;
status = WNetGetLastError( &errorCode, errorBuf, ERR_BUF_SIZE, nameBuf, NAME_BUF_SIZE);
if(status != WN_SUCCESS) { NwPrint(("nwapi32: WNetGetLastError failed %d\n",status)); return; } NwPrint(("nwapi32: EXTENDED ERROR INFORMATION: (from GetLastError)\n")); NwPrint(("nwapi32: Code: %d\n",errorCode)); NwPrint(("nwapi32: Description: "FORMAT_LPSTR"\n",errorBuf)); NwPrint(("nwapi32: Provider: "FORMAT_LPSTR"\n\n",nameBuf)); return; }
VOID VrDumpRealMode16BitRegisters( IN BOOL DebugStyle )
/*++
Routine Description:
Displays dump of 16-bit real-mode 80286 registers - gp registers (8), segment registers (4), flags register (1) instruction pointer register (1)
Arguments:
DebugStyle - determines look of output:
DebugStyle == TRUE:
ax=1111 bx=2222 cx=3333 dx=4444 sp=5555 bp=6666 si=7777 di=8888 ds=aaaa es=bbbb ss=cccc cs=dddd ip=iiii fl fl fl fl fl fl fl fl
DebugStyle == FALSE:
cs:ip=cccc:iiii ss:sp=ssss:pppp bp=bbbb ax=1111 bx=2222 cx=3333 dx=4444 ds:si=dddd:ssss es:di=eeee:dddd flags[ODIxSZxAxPxC]=fl fl fl fl fl fl fl fl
Return Value:
None.
--*/
{ char flags_string[25];
if (( UseConsole == FALSE ) && ( UseLogFile == FALSE )) { return; }
if (CpuInProtectMode) { NwPrint(( "Protect Mode:\n")); }
if (DebugStyle) { NwPrint(( "ax=%04x bx=%04x cx=%04x dx=%04x sp=%04x bp=%04x si=%04x di=%04x\n" "ds=%04x es=%04x ss=%04x cs=%04x ip=%04x %s\n\n",
pNwDosTable->SavedAx, //getAX(),
getBX(), getCX(), getDX(), getSP(), getBP(), getSI(), getDI(), getDS(), getES(), getSS(), getCS(), getIP(), ConvertFlagsToString(GetFlags(), flags_string) )); } else { NwPrint(( "cs:ip=%04x:%04x ss:sp=%04x:%04x bp=%04x ax=%04x bx=%04x cx=%04x dx=%04x\n" "ds:si=%04x:%04x es:di=%04x:%04x flags[ODITSZxAxPxC]=%s\n\n", getCS(), getIP(), getSS(), getSP(), getBP(), pNwDosTable->SavedAx, //getAX(),
getBX(), getCX(), getDX(), getDS(), getSI(), getES(), getDI(), ConvertFlagsToString(GetFlags(), flags_string) )); } }
LPSTR ConvertFlagsToString( IN WORD FlagsRegister, OUT LPSTR Buffer )
/*++
Routine Description:
Given a 16-bit word, interpret bit positions as for x86 Flags register and produce descriptive string of flags state (as per debug) eg:
NV UP DI PL NZ NA PO NC ODItSZxAxPxC = 000000000000b OV DN EI NG ZR AC PE CY ODItSZxAxPxC = 111111111111b
Trap Flag (t) is not dumped since this has no interest for programs which are not debuggers or don't examine program execution (ie virtually none)
Arguments:
FlagsRegister - 16-bit flags Buffer - place to store string. Requires 25 bytes inc \0
Return Value:
Address of <Buffer>
--*/
{ static char* flags_states[16][2] = { //0 1
"NC", "CY", // CF (0x0001) - Carry
"", "", // x (0x0002)
"PO", "PE", // PF (0x0004) - Parity
"", "", // x (0x0008)
"NA", "AC", // AF (0x0010) - Aux (half) carry
"", "", // x (0x0020)
"NZ", "ZR", // ZF (0x0040) - Zero
"PL", "NG", // SF (0x0080) - Sign
"", "", // TF (0x0100) - Trap (not dumped)
"DI", "EI", // IF (0x0200) - Interrupt
"UP", "DN", // DF (0x0400) - Direction
"NV", "OV", // OF (0x0800) - Overflow
"", "", // x (0x1000) - (I/O Privilege Level) (not dumped)
"", "", // x (0x2000) - (I/O Privilege Level) (not dumped)
"", "", // x (0x4000) - (Nested Task) (not dumped)
"", "" // x (0x8000)
}; int i; WORD bit; BOOL on;
*Buffer = 0; for (bit=0x0800, i=11; bit; bit >>= 1, --i) { on = (BOOL)((FlagsRegister & bit) == bit); if (flags_states[i][on][0]) { strcat(Buffer, flags_states[i][on]); strcat(Buffer, " "); } } return Buffer; }
WORD GetFlags( VOID )
/*++
Routine Description:
Supplies the missing softpc function
Arguments:
None.
Return Value:
Conglomerates softpc flags into x86 flags word
--*/
{ WORD flags;
flags = (WORD)getCF(); flags |= (WORD)getPF() << 2; flags |= (WORD)getAF() << 4; flags |= (WORD)getZF() << 6; flags |= (WORD)getSF() << 7; flags |= (WORD)getIF() << 9; flags |= (WORD)getDF() << 10; flags |= (WORD)getOF() << 11;
return flags; }
VOID VrDumpNwData( VOID )
/*++
Routine Description:
Dumps out the state of the 16 bit datastructures.
Arguments:
none.
Return Value:
None.
--*/
{ int index; int Drive;
if (Verbose == FALSE) { return; }
NwPrint(( "Preferred = %x, Primary = %x\n", pNwDosTable->PreferredServer, pNwDosTable->PrimaryServer));
for (index = 0; index < MC; index++) {
if ((PUCHAR)pNwDosTable->ServerNameTable[index][0] != 0 ) {
if (pNwDosTable->ConnectionIdTable[index].ci_InUse != IN_USE) { NwPrint(("Warning Connection not in use %x: %x\n", index, pNwDosTable->ConnectionIdTable[index].ci_InUse)); }
NwPrint((" Server %d = %s, Connection = %d\n", index, (PUCHAR)pNwDosTable-> ServerNameTable[index], (((pNwDosTable->ConnectionIdTable[index]).ci_ConnectionHi * 256) + ( pNwDosTable-> ConnectionIdTable[index]).ci_ConnectionLo ))); } else { if (pNwDosTable->ConnectionIdTable[index].ci_InUse != FREE) { NwPrint(("Warning Connection in use but name is null %x: %x\n", index, pNwDosTable->ConnectionIdTable[index])); } } }
for (Drive = 0; Drive < MD; Drive++ ) {
if (pNwDosTable->DriveFlagTable[Drive] & 3) { NwPrint(("%c=%x on server %d,",'A' + Drive, pNwDosTable->DriveFlagTable[Drive], pNwDosTable->DriveIdTable[ Drive ] )); }
} NwPrint(("\n")); } #endif
|