Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

584 lines
12 KiB

/*++
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