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.
 
 
 
 
 
 

2228 lines
64 KiB

/*++
NwRdr Kernel Debugger Extensions
Copyright (c) 1995 Microsoft Corporation
Abstract:
NW Redirector Kernel Debugger extensions.
This module contains a set of useful kernel debugger
extensions for the NT nw redirector.
Author:
Cory West <corywest>, 09-Jan-1994
--*/
#include "procs.h"
#include "nodetype.h"
#include <string.h>
#include <stdlib.h>
//
// Function prototypes.
//
VOID
DumpScbNp(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis,
BOOL first
);
VOID
DumpFcbNp(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis,
BOOL first
);
//
// Define some macros for simplicity.
//
#define GET_DWORD( pDest, addr ) \
(lpExtensionApis->lpReadVirtualMemRoutine)((LPVOID)(addr), pDest, 4, NULL)
#define GET_WORD( pDest, addr ) \
(lpExtensionApis->lpReadVirtualMemRoutine)((LPVOID)(addr), pDest, 2, NULL)
#define GET_STRING( pDest, string ) \
(lpExtensionApis->lpReadVirtualMemRoutine)(string.Buffer, pDest, \
string.Length, NULL); pDest[ string.Length/2 ] = L'\0'
#define printf lpExtensionApis->lpOutputRoutine
#define getmem lpExtensionApis->lpReadVirtualMemRoutine
#define getexpr lpExtensionApis->lpGetExpressionRoutine
#ifdef WINDBG
#define getsymaddr( string ) ((lpExtensionApis->lpGetExpressionRoutine))( "&"##string )
#else
#define getsymaddr lpExtensionApis->lpGetExpressionRoutine
#endif
VOID
help(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function prints out usage for the nw debugger extensions.
--*/
{
printf( "---------------------------------------------------------------------------\n");
printf( "NwRdr Debugger Extensions:\n\n");
printf( "Top Level Functions:\n\n");
printf( "serverlist(void) - List the servers that the redirector knows.\n");
printf( "logonlist(void) - List the users that are logged on.\n");
printf( "trace(void) - Display the trace buffer.\n");
printf( "nwdump(virtual addr) - Display the object at the given virtual address.\n");
printf( " (This function knows how to dump all NwRdr data\n");
printf( " structures.)\n");
printf( "help(void) - Display this message.\n\n");
printf( "List Management Functions:\n\n");
printf( "vcblist(scb*, npscb*) - Given a pointer to any of the specified objects,\n");
printf( " this function dumps the VCB list for that server.\n");
printf( "irplist(scb*, npscb*) - Given a pointer to any of the specified objects,\n");
printf( " this function dumps the IRP list for that server.\n");
printf( "fcblist(vcb*) - Given a pointer to a VCB, this function dumps\n");
printf( " the FCB/DCB list for that VCB.\n");
printf( "icblist(scb*, npscb*,\n");
printf( " fcb*, dcb*,\n");
printf( " npfcb*) - Given a pointer to any of the specified objects,\n");
printf( " function dumps the ICB list for that object.\n");
printf( "---------------------------------------------------------------------------\n");
}
VOID
traceflags(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function prints out the trace flag values.
--*/
{
printf( "DEBUG_TRACE_CLEANUP (0x00000001)\n");
printf( "DEBUG_TRACE_CLOSE (0x00000002)\n");
printf( "DEBUG_TRACE_CLEANUP (0x00000001)\n");
printf( "DEBUG_TRACE_CLOSE (0x00000002)\n");
printf( "DEBUG_TRACE_CREATE (0x00000004)\n");
printf( "DEBUG_TRACE_FSCTRL (0x00000008)\n");
printf( "DEBUG_TRACE_IPX (0x00000010)\n");
printf( "DEBUG_TRACE_LOAD (0x00000020)\n");
printf( "DEBUG_TRACE_EXCHANGE (0x00000040)\n");
printf( "DEBUG_TRACE_FILOBSUP (0x00000080)\n");
printf( "DEBUG_TRACE_STRUCSUP (0x00000100)\n");
printf( "DEBUG_TRACE_FSP_DISPATCHER (0x00000200)\n");
printf( "DEBUG_TRACE_FSP_DUMP (0x00000400)\n");
printf( "DEBUG_TRACE_WORKQUE (0x00000800)\n");
printf( "DEBUG_TRACE_UNWIND (0x00001000)\n");
printf( "DEBUG_TRACE_CATCH_EXCEPTIONS (0x00002000)\n");
printf( "DEBUG_TRACE_FILEINFO (0x00008000)\n");
printf( "DEBUG_TRACE_DIRCTRL (0x00010000)\n");
printf( "DEBUG_TRACE_CONVERT (0x00020000)\n");
printf( "DEBUG_TRACE_WRITE (0x00040000)\n");
printf( "DEBUG_TRACE_READ (0x00080000)\n");
printf( "DEBUG_TRACE_VOLINFO (0x00100000)\n");
printf( "DEBUG_TRACE_LOCKCTRL (0x00200000)\n");
printf( "DEBUG_TRACE_USERNCP (0x00400000)\n");
printf( "DEBUG_TRACE_SECURITY (0x00800000)\n");
printf( "DEBUG_TRACE_CACHE (0x01000000)\n");
printf( "DEBUG_TRACE_LIP (0x02000000)\n");
printf( "DEBUG_TRACE_MDL (0x04000000)\n");
printf( "DEBUG_TRACE_NDS (0x10000000)\n");
printf( "DEBUG_TRACE_SCAVENGER (0x40000000)\n");
printf( "DEBUG_TRACE_TIMER (0x80000000)\n");
}
//
// Internal helper routines to convert numerical data into symbolic data.
//
NODE_TYPE_CODE
GetNodeType(
DWORD objAddr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
Given the address of an object, this function will
attempt to get the node type code for that object.
--*/
{
NODE_TYPE_CODE ntc;
GET_WORD( &ntc, objAddr );
return ntc;
}
LPSTR
RcbStateToString(
DWORD State
)
/*++
Routine Description:
This helper function converts the RCB state from a
DWORD to a readable text string.
Arguments:
DWORD State - The DWORD RCB state.
Return Value:
LPSTR containing the readable text string.
--*/
{
switch ( State ) {
case RCB_STATE_STOPPED:
return("RCB_STATE_STOPPED");
case RCB_STATE_STARTING:
return("RCB_STATE_STARTING");
case RCB_STATE_NEED_BIND:
return("RCB_STATE_NEED_BIND");
case RCB_STATE_RUNNING:
return("RCB_STATE_RUNNING");
case RCB_STATE_SHUTDOWN:
return("RCB_STATE_SHUTDOWN");
default:
return("(state unknown)" );
}
}
LPSTR
ScbStateToString(
DWORD State
)
/*++
Routine Description:
This helper function converts the SCB state from a
DWORD to a readable text string.
Arguments:
DWORD State - The DWORD SCB state.
Return Value:
LPSTR containing the readable text string.
--*/
{
switch ( State ) {
case SCB_STATE_ATTACHING:
return("SCB_STATE_ATTACHING" );
case SCB_STATE_IN_USE:
return("SCB_STATE_IN_USE" );
case SCB_STATE_DISCONNECTING:
return("SCB_STATE_DISCONNECTING" );
case SCB_STATE_FLAG_SHUTDOWN:
return("SCB_STATE_FLAG_SHUTDOWN" );
case SCB_STATE_RECONNECT_REQUIRED:
return("SCB_STATE_RECONNECT_REQD" );
case SCB_STATE_LOGIN_REQUIRED:
return("SCB_STATE_LOGIN_REQUIRED" );
case SCB_STATE_TREE_SCB:
return("SCB_STATE_TREE_SCB" );
default:
return("(state unknown)" );
}
}
LPSTR
IcbStateToString(
DWORD State
)
/*++
Routine Description:
This helper function converts the ICB state from a
DWORD to a readable text string.
--*/
{
switch ( State ) {
case ICB_STATE_OPEN_PENDING:
return("ICB_STATE_OPEN_PENDING" );
case ICB_STATE_OPENED:
return("ICB_STATE_OPENED" );
case ICB_STATE_CLEANED_UP:
return("ICB_STATE_CLEANED_UP" );
case ICB_STATE_CLOSE_PENDING:
return("ICB_STATE_CLOSE_PENDING" );
default:
return("(state unknown)" );
}
}
VOID
PrintIrpContextFlags(
ULONG Flags,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
Print out the flags that are set in the IRP_CONTEXT flags.
--*/
{
if ( Flags & IRP_FLAG_IN_FSD )
printf( "\tIRP_FLAG_IN_FSD\n" );
if ( Flags & IRP_FLAG_ON_SCB_QUEUE )
printf( "\tIRP_FLAG_ON_SCB_QUEUE\n" );
if ( Flags & IRP_FLAG_SEQUENCE_NO_REQUIRED )
printf( "\tIRP_FLAG_SEQUENCE_NO_REQUIRED\n" );
if ( Flags & IRP_FLAG_SIGNAL_EVENT )
printf( "\tIRP_FLAG_SIGNAL_EVENT\n" );
if ( Flags & IRP_FLAG_RETRY_SEND )
printf( "\tIRP_FLAG_RETRY_SEND\n" );
if ( Flags & IRP_FLAG_RECONNECTABLE )
printf( "\tIRP_FLAG_RECONNECTABLE\n" );
if ( Flags & IRP_FLAG_RECONNECT_ATTEMPT )
printf( "\tIRP_FLAG_RECONNECT_ATTEMPT\n" );
if ( Flags & IRP_FLAG_BURST_REQUEST )
printf( "\tIRP_FLAG_BURST_REQUEST\n" );
if ( Flags & IRP_FLAG_BURST_PACKET )\
printf( "\tIRP_FLAG_BURST_PACKET\n" );
if ( Flags & IRP_FLAG_NOT_OK_TO_RECEIVE )
printf( "\tIRP_FLAG_NOT_OK_TO_RECEIVE\n" );
if ( Flags & IRP_FLAG_REROUTE_ATTEMPTED )
printf( "\tIRP_FLAG_REROUTE_ATTEMPTED\n" );
if ( Flags & IRP_FLAG_BURST_WRITE )
printf( "\tIRP_FLAG_BURST_WRITE\n" );
if ( Flags & IRP_FLAG_SEND_ALWAYS )
printf( "\tIRP_FLAG_SEND_ALWAYS\n" );
if ( Flags & IRP_FLAG_FREE_RECEIVE_MDL )
printf( "\tIRP_FLAG_FREE_RECEIVE_MDL\n" );
if ( Flags & IRP_FLAG_NOT_SYSTEM_PACKET )
printf( "\tIRP_FLAG_NOT_SYSTEM_PACKET\n" );
if ( Flags & IRP_FLAG_NOCONNECT )
printf( "\tIRP_FLAG_NOCONNECT\n" );
if ( Flags & IRP_FLAG_HAS_CREDENTIAL_LOCK )
printf( "\tIRP_FLAG_HAS_CREDENTIAL_LOCK\n" );
}
VOID
PrintNpFcbFlags(
ULONG Flags,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
Print out the flags that are set in the IRP_CONTEXT flags.
--*/
{
if ( Flags & FCB_FLAGS_DELETE_ON_CLOSE )
printf( "\tFCB_FLAGS_DELETE_ON_CLOSE\n" );
if ( Flags & FCB_FLAGS_TRUNCATE_ON_CLOSE )
printf( "\tFCB_FLAGS_TRUNCATE_ON_CLOSE\n" );
if ( Flags & FCB_FLAGS_PAGING_FILE )
printf( "\tFCB_FLAGS_PAGING_FILE\n" );
if ( Flags & FCB_FLAGS_PREFIX_INSERTED )
printf( "\tFCB_FLAGS_PREFIX_INSERTED\n" );
if ( Flags & FCB_FLAGS_FORCE_MISS_IN_PROGRESS )
printf( "\tFCB_FLAGS_FORCE_MISS_IN_PROGRESS\n" );
if ( Flags & FCB_FLAGS_ATTRIBUTES_ARE_VALID )
printf( "\tFCB_FLAGS_ATTRIBUTES_ARE_VALID\n" );
if ( Flags & FCB_FLAGS_LONG_NAME )
printf( "\tFCB_FLAGS_LONG_NAME\n" );
}
LPSTR
PacketToString(
UINT pt
)
/*++
Routine Description:
This helper function converts a PACKET_TYPE to
a readable text string.
--*/
{
switch ( pt ) {
case SAP_BROADCAST:
return "SAP_BROADCAST";
case NCP_CONNECT:
return "NCP_CONNECT";
case NCP_FUNCTION:
return "NCP_FUNCTION";
case NCP_SUBFUNCTION:
return "NCP_SUBFUNCTION";
case NCP_DISCONNECT:
return "NCP_DISCONNECT";
case NCP_BURST:
return "NCP_BURST";
case NCP_ECHO:
return "NCP_ECHO";
default:
return "(packet type unknown)";
}
}
//
// The internal object functions for the nwdump() routine.
// These functions must receive good pointers; they are
// neither smart, nor exported.
//
VOID
DumpScb(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis,
BOOL first
)
/*++
This function takes the address of the pageable portion
of an SCB and a pointer to a debugger extension interface
block. It prints out the information in the SCB and
the corresponding non-pageable SCB.
--*/
{
WCHAR Buffer[64];
BOOL b;
SCB Scb;
// Read it.
b = getmem((PVOID)addr, &Scb, sizeof( Scb ), NULL);
if ( b == 0 ) {
printf("<could not read the pageable scb>\n");
return;
}
printf( "-----------------------------SCB at %08lx-------------------------------\n", addr );
printf( "NodeTypeCode : NW_NTC_SCB\n" );
printf( "NodeByteSize : %d\n", Scb.NodeByteSize );
printf( "pNpScb Addr : %08lx\n", Scb.pNpScb );
printf( "Version : %d\\%d\n", Scb.MajorVersion, Scb.MinorVersion );
printf( "VcbList : %08lx (LIST_ENTRY, VCB)\n", addr + FIELD_OFFSET( SCB, ScbSpecificVcbQueue ));
printf( "VcbCount : %d\n", Scb.VcbCount );
printf( "IcbList : %08lx (LIST_ENTRY, ICB)\n", addr + FIELD_OFFSET( SCB, IcbList ));
printf( "IcbCount : %d\n", Scb.IcbCount );
printf( "OpenNdsStreams : %d\n", Scb.OpenNdsStreams );
printf( "UserUid : %08lx %08lx\n", Scb.UserUid.HighPart, Scb.UserUid.LowPart );
printf( "OpenFileCount : %d\n", Scb.OpenFileCount );
b = GET_STRING( Buffer, Scb.UidServerName );
if ( b ) {
printf( "UidServerName : %ws\n", Buffer );
} else {
printf( "UidServerName : (unreadable)\n");
}
b = GET_STRING( Buffer, Scb.NdsTreeName );
if ( b ) {
printf( "NDS Tree Name : %ws\n", Buffer );
} else {
printf( "Nds Tree Name : (none)\n");
}
b = GET_STRING( Buffer, Scb.UnicodeUid );
if ( b ) {
printf( "UnicodeUid : %ws\n", Buffer );
} else {
printf( "UnicodeUid : (unreadable)\n");
}
b = GET_STRING( Buffer, Scb.UserName );
if ( b ) {
printf( "User name : %ws\n", Buffer );
} else {
printf( "User name : (unreadable)\n" );
}
b = GET_STRING( Buffer, Scb.Password );
if ( b ) {
printf( "Password : %ws\n", Buffer );
} else {
printf( "Password : (unreadable)\n" );
}
printf( "PreferredServer : %s\n", Scb.PreferredServer ? "TRUE" : "FALSE" );
printf( "MessageWaiting : %s\n", Scb.MessageWaiting ? "TRUE" : "FALSE" );
printf( "AttachCount : %d\n", Scb.AttachCount);
// What about the drive map?
// Dump both parts.
if ( first )
DumpScbNp( (DWORD)Scb.pNpScb, lpExtensionApis, FALSE );
else
printf( "---------------------------------------------------------------------------\n");
return;
}
VOID
DumpScbNp(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis,
BOOL first
)
/*++
This function takes the address of the nonpageable
portion of an SCB and a pointer to a debugger extension
interface block. It prints out the information in the
nonpageable SCB and the corresponding pageable SCB.
--*/
{
WCHAR Buffer[64];
BOOL b;
NONPAGED_SCB NpScb;
// Read it.
b = getmem( (PVOID)addr, &NpScb, sizeof( NpScb ), NULL );
if ( b == 0 ) {
printf("<could not read the nonpageable scb>\n");
return;
}
printf( "------------------------Non-Pageable SCB at %08lx-----------------------\n", addr);
printf( "NodeTypeCode : NW_NTC_SCBNP\n" );
printf( "NodeByteSize : %d\n", NpScb.NodeByteSize );
b = GET_STRING( Buffer, NpScb.ServerName );
if ( b ) {
printf( "ServerName : %ws\n", Buffer );
} else {
printf( "ServerName : (unreadable)\n" );
}
printf( "pScb Addr : %08lx\n", NpScb.pScb );
printf( "Reference Count : %08lx\n", NpScb.Reference );
printf( "State : %s\n", ScbStateToString( NpScb.State ));
printf( "Last Used Time : %08lx %08lx\n", NpScb.LastUsedTime.HighPart, NpScb.LastUsedTime.LowPart );
printf( "Sending : %s\n", NpScb.Sending ? "TRUE" : "FALSE" );
printf( "Receiving : %s\n", NpScb.Receiving ? "TRUE" : "FALSE" );
printf( "Ok To Receive : %s\n", NpScb.OkToReceive ? "TRUE" : "FALSE" );
printf( "PageAlign : %s\n", NpScb.PageAlign ? "TRUE" : "FALSE" );
printf( "Scblinks : %08lx (LIST_ENTRY, NPSCB)\n", addr + FIELD_OFFSET( NONPAGED_SCB, ScbLinks ));
printf( "Requests : %08lx (LIST_ENTRY, NPSCB)\n", addr + FIELD_OFFSET( NONPAGED_SCB, Requests ));
printf( "------------------------------Transport Info-------------------------------\n" );
printf( "TickCount : %d\n", NpScb.TickCount );
printf( "RetryCount : %d\n", NpScb.RetryCount );
printf( "Timeout : %d\n", NpScb.TimeOut );
printf( "SequenceNo : %d\n", NpScb.SequenceNo );
printf( "ConnectionNo : %d\n", NpScb.ConnectionNo );
printf( "ConnectionNoHi : %d\n", NpScb.ConnectionNoHigh );
printf( "ConnectionStat : %d\n", NpScb.ConnectionStatus );
printf( "MaxTimeOut : %d\n", NpScb.MaxTimeOut );
printf( "BufferSize : %d\n", NpScb.BufferSize );
printf( "TaskNo : %d\n", NpScb.TaskNo );
printf( "Spin lock : %s\n", NpScb.NpScbSpinLock == 0 ? "Released" : "Acquired " );
printf( "LIP Data Speed : %d\n", NpScb.LipDataSpeed );
printf( "---------------------------Burst Mode Parameters---------------------------\n");
printf( "SourceConnId : %08lx\n", NpScb.SourceConnectionId );
printf( "DestConnId : %08lx\n", NpScb.DestinationConnectionId );
printf( "MaxPacketSize : %d\n", NpScb.MaxPacketSize );
printf( "MaxSendSize : %ld\n", NpScb.MaxSendSize );
printf( "MaxReceiveSize : %ld\n", NpScb.MaxReceiveSize );
printf( "SendBMEnable : %s\n", NpScb.SendBurstModeEnabled ? "TRUE" : "FALSE" );
printf( "ReceiveBMEnable : %s\n", NpScb.ReceiveBurstModeEnabled ? "TRUE" : "FALSE" );
printf( "BurstSequenceNo : %d\n", NpScb.BurstSequenceNo );
printf( "BurstRequestNo : %d\n", NpScb.BurstRequestNo );
printf( "BurstSendDelay : Good %d,\tCurrent %d,\tBad %d\n", NpScb.NwGoodSendDelay, NpScb.NwSendDelay, NpScb.NwBadSendDelay );
printf( "BurstReceiveDelay : Good %d,\tCurrent %d,\tBad %d\n", NpScb.NwGoodReceiveDelay, NpScb.NwReceiveDelay, NpScb.NwBadReceiveDelay );
printf( "BurstSuccessCount : Send %d, Receive %d\n", NpScb.SendBurstSuccessCount, NpScb.ReceiveBurstSuccessCount );
printf( "--------------------------Send Delays and Timeouts-------------------------\n" );
printf( "SendTimeout : %d\n", NpScb.SendTimeout );
printf( "TotalWaitTime : %d\n", NpScb.TotalWaitTime );
printf( "NwLoopTime : %d\n", NpScb.NwLoopTime );
printf( "NwSingleBurst : %d\n", NpScb.NwSingleBurstPacketTime );
printf( "NwMaxSendDelay : %d\n", NpScb.NwMaxSendDelay );
printf( "NwGoodSendDelay : %d\n", NpScb.NwGoodSendDelay );
printf( "NwBadSendDelay : %d\n", NpScb.NwBadSendDelay );
printf( "BurstDataWritten : %d\n", NpScb.BurstDataWritten );
printf( "NwMaxReceiveDelay : %d\n", NpScb.NwMaxReceiveDelay );
printf( "NwReceiveDelay : %d\n", NpScb.NwReceiveDelay );
printf( "NwGoodReceiveDelay : %d\n", NpScb.NwGoodReceiveDelay );
printf( "NwBadReceiveDelay : %d\n", NpScb.NwBadReceiveDelay );
printf( "CurrentBurstDelay : %d\n", NpScb.CurrentBurstDelay );
printf( "NtSendDelay : %08lx %08lx\n", NpScb.NtSendDelay.HighPart, NpScb.NtSendDelay.LowPart );
printf( "NwNextEventTime : %08lx %08lx\n", NpScb.NwNextEventTime.HighPart, NpScb.NwNextEventTime.LowPart );
// Spin locks? Transport and TDI info?
// Dump Both Parts.
if ( first )
DumpScb( (DWORD)NpScb.pScb, lpExtensionApis, FALSE );
else
printf( "---------------------------------------------------------------------------\n" );
return;
}
VOID
DumpFcb(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis,
BOOL first
)
/*++
This function takes the address of an FCB or DCB and a pointer
to a debugger extension interface block. It prints out
the information in the FCB or DCB.
--*/
{
WCHAR Buffer[64];
BOOL b;
FCB Fcb;
b = getmem( (PVOID)addr, &Fcb, sizeof( Fcb ), NULL );
if ( b == 0 ) {
printf("<could not read the fcb or dcb>\n");
return;
}
if (Fcb.NodeTypeCode == NW_NTC_FCB) {
printf( "----------------------------FCB at %08lx--------------------------------\n", addr );
printf( "NodeTypeCode : NW_NTC_FCB\n" );
} else {
printf( "----------------------------DCB at %08lx--------------------------------\n", addr );
printf( "NodeTypeCode : NW_NTC_DCB\n" );
}
b = GET_STRING( Buffer, Fcb.FullFileName );
if ( b ) {
printf( "FullFileName : %ws\n", Buffer );
} else {
printf( "FullFileName : (unreadable)\n" );
}
b = GET_STRING( Buffer, Fcb.RelativeFileName );
if ( b ) {
printf( "RelativeFileName : %ws\n", Buffer );
} else {
printf( "RelativeFileName : (unreadable)\n" );
}
printf( "VCB Addr : %08lx\n", Fcb.Vcb );
printf( "SCB Addr : %08lx\n", Fcb.Scb );
printf( "NpFcb Addr : %08lx\n", Fcb.NonPagedFcb );
printf( "LastModifiedDate : %d\n", Fcb.LastModifiedDate );
printf( "LastModifiedTime : %d\n", Fcb.LastModifiedTime );
printf( "CreationDate : %d\n", Fcb.CreationDate );
printf( "CreationTime : %d\n", Fcb.CreationTime );
printf( "LastAccessDate : %d\n", Fcb.LastAccessDate );
printf( "State : %d\n", Fcb.State );
printf( "Flags : %d\n", Fcb.Flags );
// SHARE_ACCESS?
printf( "FcbListEntry : %08lx (LIST_ENTRY, FCB)\n", addr + FIELD_OFFSET( FCB, FcbListEntry ));
printf( "IcbListEntry : %08lx (LIST_ENTRY, ICB)\n", addr + FIELD_OFFSET( FCB, IcbList ));
printf( "IcbCount : %d\n", Fcb.IcbCount );
printf( "LastReadOffset : %d\n", Fcb.LastReadOffset );
printf( "LastReadSize : %d\n", Fcb.LastReadSize );
// Dump both parts.
if ( first )
DumpFcbNp( (DWORD)Fcb.NonPagedFcb, lpExtensionApis, FALSE );
else
printf( "---------------------------------------------------------------------------\n" );
}
VOID
DumpVcb(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of a VCB and a pointer
to a debugger extension interface block. It prints out
the information in the VCB.
--*/
{
WCHAR Buffer[64];
BOOL b;
VCB Vcb;
// Read it.
b = getmem( (PVOID)addr, &Vcb, sizeof( Vcb ), NULL);
if ( b == 0 ) {
printf("<could not read the vcb>\n");
return;
}
printf( "------------------------------VCB at %08lx------------------------------\n", addr);
printf( "NodeTypeCode : NW_NTC_VCB\n" );
printf( "NodeByteSize : %d\n", Vcb.NodeByteSize );
printf( "Reference Count : %08lx\n", Vcb.Reference );
printf( "Last Used Time : %08lx %08lx\n", Vcb.LastUsedTime.HighPart, Vcb.LastUsedTime.LowPart );
printf( "GlobalVcbListEntry : %08lx (LIST_ENTRY, VCB)\n", addr + FIELD_OFFSET( VCB, GlobalVcbListEntry) );
printf( "SequenceNumber : %d\n", Vcb.SequenceNumber );
b = GET_STRING( Buffer, Vcb.Name );
if ( b ) {
printf( "VolumeName : %ws\n", Buffer );
} else {
printf( "VolumeName : (unreadable)\n" );
}
b = GET_STRING( Buffer, Vcb.ConnectName );
if ( b ) {
printf( "ConnectName : %ws\n", Buffer );
} else {
printf( "ConnectName : (unreadable)\n" );
}
b = GET_STRING( Buffer, Vcb.ShareName );
if ( b ) {
printf( "NW ShareName : %ws\n", Buffer );
} else {
printf( "NW ShareName : (unreadable)\n" );
}
if ( !Vcb.Flags & VCB_FLAG_PRINT_QUEUE ) {
printf( "VolumeNumber : %d\n", Vcb.Specific.Disk.VolumeNumber );
printf( "LongNameSpace : %d\n", Vcb.Specific.Disk.LongNameSpace );
printf( "Handle : %d\n", Vcb.Specific.Disk.Handle );
} else {
printf( "QueueId : %d\n", Vcb.Specific.Print.QueueId );
}
if ( Vcb.DriveLetter != 0) {
printf( "Drive letter : %wc:\n", Vcb.DriveLetter );
} else {
printf( "Drive letter : UNC\n" );
}
printf( "Scb Addr : %08lx\n", Vcb.Scb );
printf( "VcbListEntry : %08lx (LIST_ENTRY, VCB)\n", addr + FIELD_OFFSET( VCB, VcbListEntry) );
printf( "FcbListEntry : %08lx (LIST_ENTRY, FCB)\n", addr + FIELD_OFFSET(VCB, FcbList) );
printf( "OpenFileCount : %d\n", Vcb.OpenFileCount );
printf( "Flags : %08lx\n", Vcb.Flags );
printf( "---------------------------------------------------------------------------\n");
}
VOID
DumpIcb(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of an ICB and a pointer
to a debugger extension interface block. It prints out
the information in the ICB.
--*/
{
WCHAR Buffer[64];
BOOL b, icbscb;
ICB Icb;
UINT hb;
b = getmem( (PVOID)addr, &Icb, sizeof( Icb ), NULL);
if ( b == 0 ) {
printf("<could not read the icb>\n");
return;
}
icbscb = (Icb.NodeTypeCode == NW_NTC_ICB_SCB);
if ( icbscb ) {
printf( "---------------------------ICB_SCB at %08lx-----------------------------\n", addr );
printf( "NodeTypeCode : NW_NTC_ICB_SCB\n" );
} else {
printf( "-----------------------------ICB at %08lx-------------------------------\n", addr );
printf( "NodeTypeCode : NW_NTC_ICB\n" );
}
printf( "NodeByteSize : %d\n", Icb.NodeByteSize );
printf( "ListEntry : %08lx\n", Icb.ListEntry );
if (icbscb ) {
printf( "SuperType Addr : %08lx (SCB)\n", Icb.SuperType.Scb );
} else {
printf( "SuperType Addr : %08lx (FCB)\n", Icb.SuperType.Fcb );
printf( "NpFcb Addr : %08lx\n", Icb.NpFcb );
}
printf( "State : %s\n", IcbStateToString(Icb.State) );
printf( "HasRemoteHandle : %s\n", Icb.HasRemoteHandle ? "TRUE" : "FALSE" );
if ( Icb.HasRemoteHandle ) {
printf( "Handle : " );
for ( hb = 0; hb < 6; hb++ ) {
printf( "%c ", (Icb.Handle)[hb]);
}
printf( "\n");
}
// What abou the PFILE_OBJECT?
b = GET_STRING( Buffer, Icb.NwQueryTemplate );
if ( b ) {
printf( "NwQueryTemplate : %s\n", Buffer );
} else {
printf( "NWQueryTemplate : (unreadable)\n" );
}
b = GET_STRING( Buffer, Icb.UQueryTemplate );
if ( b ) {
printf( "UQueryTemplate : %ws\n", Buffer );
} else {
printf( "UQueryTemplate : (unreadable)\n" );
}
printf( "IndexLastIcbRtr : %d\n", Icb.IndexOfLastIcbReturned );
printf( "Pid : %d\n", Icb.Pid );
printf( "DotReturned : %s\n", Icb.DotReturned ? "TRUE" : "FALSE" );
printf( "DotDotReturned : %s\n", Icb.DotDotReturned ? "TRUE" : "FALSE" );
printf( "ReturnedSmthng : %s\n", Icb.ReturnedSomething ? "TRUE" : "FALSE" );
printf( "ShortNameSearch : %s\n", Icb.ShortNameSearch ? "TRUE" : "FALSE" );
printf( "SearchHandle : %d\n", Icb.SearchHandle );
printf( "SearchVolume : %d\n", Icb.SearchVolume );
printf( "SearchAttribts : %d\n", Icb.SearchAttributes );
printf( "SearchIndexHigh : %d\n", Icb.SearchIndexHigh );
printf( "SearchIndexLow : %d\n", Icb.SearchIndexLow );
printf( "IsPrintJob : %s\n", Icb.IsPrintJob ? "TRUE" : "FALSE" );
printf( "JobId : %d\n", Icb.JobId );
printf( "ActuallyPrinted : %s\n", Icb.ActuallyPrinted ? "TRUE" : "FALSE" );
printf( "USetLastAccessTime : %s\n", Icb.UserSetLastAccessTime ? "TRUE" : "FALSE" );
printf( "File Position : %d\n", Icb.FilePosition );
printf( "File Size : %d\n", Icb.FileSize );
printf( "IsTreeHanle : %s\n", Icb.IsTreeHandle ? "TRUE" : "FALSE" );
// This needs to be cleaned up!
printf( "---------------------------------------------------------------------------\n" );
}
VOID
DumpIrpContext(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
{
BOOL b;
IRP_CONTEXT IrpContext;
b = getmem( (PVOID)addr, &IrpContext, sizeof( IrpContext ), NULL );
if ( b == 0 ) {
printf( "<could not read the irpcontext>\n" );
return;
}
printf( "--------------------------IRP CONTEXT at %08lx--------------------------\n", addr );
printf( "NodeTypeCode : NW_NTC_IRP_CONTEXT\n" );
// WORK_QUEUE_ITEM?
printf( "PacketType : %s\n", PacketToString(IrpContext.PacketType));
printf( "NpScb Addr : %08lx\n", IrpContext.pNpScb );
printf( "Scb Addr : %08lx\n", IrpContext.pScb );
printf( "TdiStruct : %08lx\n", IrpContext.pTdiStruct );
// NextRequest?
printf( "Event : %08lx\n", addr + FIELD_OFFSET( IRP_CONTEXT, Event ) );
printf( "Original IRP : %08lx\n", IrpContext.pOriginalIrp );
printf( "Original SB : %08lx\n", IrpContext.pOriginalSystemBuffer );
printf( "Original UB : %08lx\n", IrpContext.pOriginalUserBuffer );
printf( "Original MDL : %08lx\n", IrpContext.pOriginalMdlAddress );
printf( "Receive IRP : %08lx\n", IrpContext.ReceiveIrp );
printf( "TxMdl : %08lx\n", IrpContext.TxMdl );
printf( "RxMdl : %08lx\n", IrpContext.RxMdl );
printf( "RunRoutine : %08lx\n", IrpContext.RunRoutine );
printf( "pEx : %08lx\n", IrpContext.pEx );
printf( "PostProcessRtn : %08lx\n", IrpContext.PostProcessRoutine );
printf( "TimeoutRtn : %08lx\n", IrpContext.TimeoutRoutine );
printf( "ComplSendRtn : %08lx\n", IrpContext.CompletionSendRoutine );
printf( "pWorkItem : %08lx\n", IrpContext.pWorkItem );
printf( "Req Data Addr : %08lx\n", addr + FIELD_OFFSET( IRP_CONTEXT, req ) );
printf( "ResponseLength : %08lx\n", IrpContext.ResponseLength );
printf( "Rsp Data Addr : %08lx\n", addr + FIELD_OFFSET( IRP_CONTEXT, rsp ) );
printf( "Icb Addr : %08lx\n", IrpContext.Icb );
printf( "Specific Data Addr : %08lx\n", addr + FIELD_OFFSET( IRP_CONTEXT, Specific.Create.FullPathName ) );
printf( "------------------------------IRP Context Flags----------------------------\n");
PrintIrpContextFlags(IrpContext.Flags, lpExtensionApis);
printf( "---------------------------------------------------------------------------\n" );
return;
}
VOID
DumpFcbNp(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis,
BOOL first
)
{
WCHAR Buffer[64];
BOOL b;
NONPAGED_FCB NpFcb;
b = getmem( (PVOID)addr, &NpFcb, sizeof( NONPAGED_FCB ), NULL);
if ( !b ) {
printf( "<could not read the non-pageable fcb>\n" );
return;
}
printf( "--------------------Common NP FCB Header at %08lx-----------------------\n");
printf( "NodeTypeCode : NW_NTC_NONPAGED_FCB\n" );
printf( "NodeByteSize : %d\n", NpFcb.Header.NodeByteSize );
printf( "IsFastIoPossible : %d\n", NpFcb.Header.IsFastIoPossible );
// Resource? PagingIoResource?
printf( "AllocationSize : %08lx %08lx\n", NpFcb.Header.AllocationSize.HighPart, NpFcb.Header.AllocationSize.LowPart );
printf( "FileSize : %08lx %08lx\n", NpFcb.Header.FileSize.HighPart, NpFcb.Header.FileSize.LowPart );
printf( "ValidDataLength : %08lx %08lx\n", NpFcb.Header.ValidDataLength.HighPart, NpFcb.Header.ValidDataLength.LowPart );
printf( "pFcb Addr : %08lx\n", NpFcb.Fcb );
// SegmentObject?
printf( "FileLockList : %08lx\n", addr + FIELD_OFFSET( NONPAGED_FCB, FileLockList) );
printf( "PendLockList : %08lx\n", addr + FIELD_OFFSET( NONPAGED_FCB, PendingLockList) );
printf( "Resource : %08lx\n", addr + FIELD_OFFSET( NONPAGED_FCB, Resource ) );
printf( "Attributes : %d\n", NpFcb.Attributes );
printf( "CacheType : %d\n", NpFcb.CacheType );
printf( "CacheBuffer : %08lx\n", NpFcb.CacheBuffer );
printf( "CacheMdl : %08lx\n", NpFcb.CacheMdl );
printf( "CacheSize : %d\n", NpFcb.CacheSize );
printf( "CacheFileOffset : %d\n", NpFcb.CacheFileOffset );
printf( "CacheDataSize : %d\n", NpFcb.CacheDataSize );
printf( "----------------------------------FCB Flags--------------------------------\n" );
PrintNpFcbFlags( NpFcb.Header.Flags, lpExtensionApis );
// Dump both parts.
if ( first )
DumpFcb( (DWORD)NpFcb.Fcb, lpExtensionApis, FALSE );
else
printf( "---------------------------------------------------------------------------\n" );
}
VOID
DumpRcb(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of an ICB and a pointer
to a debugger extension interface block. It prints out
the information in the ICB.
--*/
{
BOOL b;
RCB Rcb;
b = getmem( (PVOID)addr, &Rcb, sizeof( RCB ), NULL);
if ( b == 0 ) {
printf("<could not read the rcb>\n");
return;
}
printf( "------------------------------------------------------------\n");
printf( "NodeTypeCode : NW_NTC_RCB\n");
printf( "State : %s\n", RcbStateToString(Rcb.State));
printf( "OpenCount : %ul\n", Rcb.OpenCount);
printf( "ResourceAddr : %08lx\n", addr + FIELD_OFFSET( RCB, Resource ));
printf( "ServerListAddr : %08lx\n", addr + FIELD_OFFSET( RCB,
ServerNameTable ));
printf( "VolumeListAddr : %08lx\n", addr + FIELD_OFFSET( RCB,
VolumeNameTable ));
printf( "FileListAddr : %08lx\n", addr + FIELD_OFFSET( RCB,
FileNameTable ));
printf( "------------------------------------------------------------\n");
}
VOID
DumpPid(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of a PID and a pointer
to a debugger extension interface block. It prints out
the information in the PID.
--*/
{
printf( "------------------------------------------------------------\n");
printf( "NodeTypeCode : NW_NTC_PID\n" );
printf( "...Not yet implemented...");
printf( "------------------------------------------------------------\n");
}
VOID
DumpFileLock(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of a file lock and a pointer
to a debugger extension interface block. It prints out
the information in the file lock.
--*/
{
printf( "------------------------------------------------------------\n" );
printf( "NodeTypeCode : NW_NTC_FILE_LOCK\n" );
printf( "Not yet implemented...\n" );
printf( "------------------------------------------------------------\n" );
}
VOID
DumpLogon(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of a logon and a pointer
to a debugger extension interface block. It prints out
the information in the logon.
--*/
{
BOOL b;
LOGON Logon;
WCHAR Buffer[64];
b = getmem( (PVOID)addr, &Logon, sizeof(LOGON), NULL );
if (!b ) {
printf( "<unable to read logon>" );
return;
}
printf( "------------------------------------------------------------\n");
printf( "NodeTypeCode : NW_NTC_LOGON\n" );
printf( "NodeByteSize : %d\n", Logon.NodeByteSize );
printf( "NextLogon : %08lx (LOGON LIST_ENTRY)\n", addr +
FIELD_OFFSET( LOGON, Next ));
b = GET_STRING( Buffer, Logon.UserName );
if ( b ) {
printf( "UserName : %ws\n", Buffer );
} else {
printf( "UserName : <unreadable>\n" );
}
b = GET_STRING( Buffer, Logon.PassWord );
if ( b ) {
printf( "Password : %ws\n", Buffer );
} else {
printf( "Password : <unreadable>\n" );
}
b = GET_STRING( Buffer, Logon.ServerName );
if ( b ) {
printf( "Pref Server : %ws\n", Buffer );
} else {
printf( "Pref Server : <unreadable>\n" );
}
printf( "UserUid : %08lx %08lx\n", Logon.UserUid.HighPart,
Logon.UserUid.LowPart);
printf( "CredListResource: %08lx\n", addr +
FIELD_OFFSET( LOGON, CredentialListResource ));
printf( "CredentialList : %08lx (CREDENTIAL LIST_ENTRY)\n", addr +
FIELD_OFFSET( LOGON, NdsCredentialList ));
printf( "------------------------------------------------------------\n");
}
VOID
DumpCredential(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of an nds credential and a
pointer to a debugger extension interface block. It prints
out the information in the logon.
--*/
{
BOOL b;
NDS_SECURITY_CONTEXT Context;
NDS_CREDENTIAL Credential;
NDS_SIGNATURE Signature;
WCHAR Buffer[512];
CHAR PackBuffer[2048];
BYTE *packed;
ULONG packedlen;
b = getmem( (PVOID)addr, &Context, sizeof(NDS_SECURITY_CONTEXT), NULL );
if (!b ) {
printf( "<unable to read context>\n" );
return;
}
printf( "-------- NDS Security Context at 0x%08lx ----------------\n", addr);
printf( "NodeTypeCode : NW_NTC_NDS_CREDENTIAL\n" );
printf( "NodeByteSize : %d\n", Context.nts );
printf( "Next : %08lx (NDS_SECURITY_CONTEXT LIST_ENTRY)\n", addr +
FIELD_OFFSET( NDS_SECURITY_CONTEXT, Next ));
b = GET_STRING( Buffer, Context.NdsTreeName );
if ( b ) {
printf( "Nds Tree Name : %ws\n", Buffer );
} else {
printf( "Nds Tree Name : <unreadable>\n" );
}
b = GET_STRING( Buffer, Context.CurrentContext );
if ( b ) {
printf( "Current Context : %ws\n", Buffer );
} else {
printf( "Current Context :<unreadable>\n" );
}
printf( "Owning Logon : %08lx\n", Context.pOwningLogon );
printf( "Handle Count : %d\n", Context.SupplementalHandleCount );
if ( Context.Credential != NULL ) {
printf( "--------------------- Credential Data ----------------------\n");
b = getmem( (PVOID)Context.Credential, &Credential, sizeof(NDS_CREDENTIAL), NULL );
if (!b ) {
printf( "<unable to read credential>\n" );
goto DO_SIGNATURE;
}
printf( "Start validity : 0x%08lx\n", Credential.validityBegin );
printf( "End validity : 0x%08lx\n", Credential.validityEnd );
printf( "Random : 0x%08lx\n", Credential.random );
printf( "Opt data Len : %d\n", Credential.optDataSize );
printf( "UserName Len : %d\n", Credential.userNameLength );
//
// Optional data is the first packed data after the struct.
//
packedlen = Credential.optDataSize + Credential.userNameLength;
packed = ((BYTE *)Context.Credential) + sizeof( NDS_CREDENTIAL );
if ( Credential.optDataSize ) {
printf( "Opt data addr : %08lx\n", packed );
}
packed += Credential.optDataSize;
b = getmem( (PVOID)packed, Buffer, Credential.userNameLength, NULL );
if ( !b ) {
printf( "<unable to read user name>\n" );
goto DO_SIGNATURE;
}
printf( "Username : %ws\n", Buffer );
} else {
printf( "-------------------- No Credential Data --------------------\n");
}
DO_SIGNATURE:
if ( Context.Signature != NULL ) {
printf( "---------------------- Signature Data ----------------------\n");
b = getmem( (PVOID)Context.Signature, &Signature, sizeof(NDS_SIGNATURE), NULL );
if (!b ) {
printf( "<unable to read signature>\n" );
goto DO_END;
}
printf( "Signature Len : %d\n", Signature.signDataLength );
packedlen = Signature.signDataLength;
packed = ((BYTE *)Context.Signature) + sizeof( NDS_SIGNATURE );
printf( "Signature addr : %08lx\n", packed );
} else {
printf( "-------------------- No Signature Data ---------------------\n");
}
DO_END:
if ( Context.PublicNdsKey != NULL ) {
printf( "------------------------------------------------------------\n");
printf( "Public Key Len : %d\n", Context.PublicKeyLen );
printf( "Public Key : %08lx\n", Context.PublicNdsKey );
printf( "------------------------------------------------------------\n");
} else {
printf( "-------------------- No Public Key Data --------------------\n");
}
}
VOID
DumpMiniIrpContext(
DWORD addr,
PNTKD_EXTENSION_APIS lpExtensionApis
)
/*++
This function takes the address of a mini irp context
and a pointer to a debugger extension interface block.
It prints out the information in the mini irp context.
--*/
{
BOOL b;
MINI_IRP_CONTEXT mini;
b = getmem( (PVOID)addr, &mini, sizeof(MINI_IRP_CONTEXT), NULL );
if (!b ) {
printf( "<unable to read mini irp context>\n");
return;
}
printf( "------------------------------------------------------------\n");
printf( "NodeTypeCode : NW_NTC_MINI_IRP_CONTEXT\n" );
printf( "NodeByteSize : %d\n", mini.NodeByteSize );
printf( "ListEntry : %08lx\n", addr + FIELD_OFFSET( MINI_IRP_CONTEXT,
Next ));
printf( "IrpContext : %08lx\n", mini.IrpContext );
printf( "Irp : %08lx\n", mini.Irp );
printf( "Buffer : %08lx\n", mini.Buffer );
printf( "Mdl1 : %08lx\n", mini.Mdl1 );
printf( "Mdl2 : %08lx\n", mini.Mdl2 );
printf( "------------------------------------------------------------\n");
}
VOID
nwdump(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
Routine Description:
This function takes the pointer to a structure,
figures out what the structure is, and calls the
appropriate dump routine.
Arguments:
CurrentPc - Supplies the current pc at the time
the extension is called.
lpExtensionApis - Supplies the address of the
functions callable by this extension.
lpArgumentString - Supplies the address of the structure.
Return Value:
None.
---*/
{
DWORD addr;
//
// Determine the node type and dispatch.
//
addr = getexpr( lpArgumentString );
switch ( GetNodeType( addr, lpExtensionApis ) ) {
case NW_NTC_SCB:
DumpScb(addr, lpExtensionApis, TRUE);
break;
case NW_NTC_SCBNP:
DumpScbNp(addr, lpExtensionApis, TRUE);
break;
case NW_NTC_FCB:
case NW_NTC_DCB:
DumpFcb(addr, lpExtensionApis, TRUE);
break;
case NW_NTC_VCB:
DumpVcb(addr, lpExtensionApis);
break;
case NW_NTC_ICB:
case NW_NTC_ICB_SCB:
DumpIcb(addr, lpExtensionApis);
break;
case NW_NTC_IRP_CONTEXT:
DumpIrpContext(addr, lpExtensionApis);
break;
case NW_NTC_NONPAGED_FCB:
DumpFcbNp(addr, lpExtensionApis, TRUE);
break;
case NW_NTC_RCB:
DumpRcb(addr, lpExtensionApis);
break;
case NW_NTC_PID:
DumpPid(addr, lpExtensionApis);
break;
case NW_NTC_FILE_LOCK:
DumpFileLock(addr, lpExtensionApis);
break;
case NW_NTC_LOGON:
DumpLogon(addr, lpExtensionApis);
break;
case NW_NTC_MINI_IRP_CONTEXT:
DumpMiniIrpContext(addr, lpExtensionApis);
break;
case NW_NTC_NDS_CREDENTIAL:
DumpCredential(addr, lpExtensionApis);
break;
default:
printf("(this object does not have a vaid node type)\n");
break;
}
}
//
// Other debugger routines.
//
VOID
serverlist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
Routine Description:
This function displays a list of servers that the redirector
is maintaining connections to. The information is read from
the SCB queue, not from the server list in the RCB. The
argument to this function is ignored.
--*/
{
DWORD addrScbQueue;
WCHAR ServerName[64];
BOOL b;
PLIST_ENTRY ScbQueueList;
DWORD addrNpScb, addrScb;
NONPAGED_SCB NpScb;
SCB Scb;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
//
// Get the address of the server list in the rdr.
//
addrScbQueue = getsymaddr("nwrdr!scbqueue");
if ( addrScbQueue == 0 ) {
printf("The server list was not locatable.\n");
return;
}
//
// Walk the list of servers.
//
printf("pNpScb pScb Ref State Name\n");
printf("---------------------------------------------------------------------------\n");
for ( GET_DWORD( &ScbQueueList, addrScbQueue );
ScbQueueList != (PLIST_ENTRY)addrScbQueue;
GET_DWORD( &ScbQueueList, ScbQueueList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrNpScb = (DWORD)CONTAINING_RECORD( ScbQueueList, NONPAGED_SCB, ScbLinks );
printf("%08lx ", addrNpScb );
b = (getmem)((LPVOID)addrNpScb,
&NpScb,
sizeof( NpScb ),
NULL);
if ( b == 0 ) {
printf("<could not continue>\n");
return;
}
addrScb = (DWORD)NpScb.pScb;
printf("%08lx ", addrScb );
printf("%8lx ", NpScb.Reference);
printf("%-25s", ScbStateToString( NpScb.State ) );
if ( addrScb != 0 ) {
b = (getmem)((LPVOID)addrScb,
&Scb,
sizeof( Scb ),
NULL);
if ( b == 0 ) {
printf("<unreadable>\n");
continue;
}
// Get the server name.
b = GET_STRING( ServerName, Scb.UidServerName );
if ( b ) {
printf( "%ws\n", ServerName );
} else {
printf( "Unreadable\n" );
}
} else {
printf( "Permanent SCB\n" );
}
}
printf("---------------------------------------------------------------------------\n");
}
VOID
trace(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
Routine Description:
This function dumps the nwrdr trace buffer. Arguments to
this function are ignored.
To Be Done:
Read trace buffer size out of nwrdrd and dynamically size.
--*/
{
ULONG addrDBuffer, addrDBufferPtr, DBufferPtr;
ULONG BufferSize;
PCHAR TraceStart, CurrentPtr;
char buffer[80 + 1];
char *bptr;
char *newptr;
int i;
int readsize;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
addrDBuffer = getsymaddr( "nwrdr!dbuffer" );
if ( !addrDBuffer ) {
printf("(unable to locate the trace buffer address)\n");
return;
} else {
printf("Address of Dbuffer = %08lx\n", addrDBuffer );
}
addrDBufferPtr = getsymaddr( "nwrdr!dbufferptr" );
if ( !addrDBuffer ) {
printf("(unable to locate the trace buffer pointer)\n");
return;
} else {
printf("Address of DbufferPtr = %08lx\n", addrDBufferPtr );
}
GET_DWORD( &DBufferPtr, addrDBufferPtr );
printf("DbufferPtr = %08lx\n", DBufferPtr );
// Set up state variables and loop.
TraceStart = (char *)addrDBuffer;
BufferSize = 100*255+1;
CurrentPtr = (char *)DBufferPtr;
buffer[80] = '\0';
newptr = CurrentPtr + 1;
while ( 1 ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
if ( newptr + 80 > TraceStart+BufferSize ) {
readsize = TraceStart+BufferSize - newptr;
} else {
readsize = 80;
}
getmem( newptr, buffer, readsize, NULL );
bptr = buffer;
for (i = 0; i<80 ; i++ ) {
if ( buffer[i] == '\n') {
buffer[i] = 0;
printf( "%s\n", bptr );
bptr = &buffer[i+1];
}
}
printf( "%s", bptr );
//
// If we're back to where we started, break out of here.
//
if ( (newptr <= CurrentPtr) &&
(newptr + readsize) >= CurrentPtr ) {
break;
}
//
// Advance the running pointer.
//
newptr += readsize;
if ( newptr >= TraceStart+BufferSize ) {
newptr = TraceStart;
}
}
printf( "\n");
}
VOID
reftrace(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
Routine Description:
This function dumps the nwrdr reference trace buffer.
--*/
{
ULONG addrRBuffer, addrRBufferPtr, RBufferPtr;
ULONG BufferSize;
PCHAR TraceStart, CurrentPtr;
char buffer[80 + 1];
char *bptr;
char *newptr;
int i;
int readsize;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
addrRBuffer = getsymaddr( "nwrdr!RBuffer" );
if ( !addrRBuffer ) {
printf("(unable to locate the trace buffer address)\n");
return;
} else {
printf("Address of RBuffer = %08lx\n", addrRBuffer );
}
addrRBufferPtr = getsymaddr( "nwrdr!RBufferptr" );
if ( !addrRBuffer ) {
printf("(unable to locate the trace buffer pointer)\n");
return;
} else {
printf("Address of RBufferPtr = %08lx\n", addrRBufferPtr );
}
GET_DWORD( &RBufferPtr, addrRBufferPtr );
printf("RBufferPtr = %08lx\n", RBufferPtr );
// Set up state variables and loop.
TraceStart = (char *)addrRBuffer;
BufferSize = 100*255+1;
CurrentPtr = (char *)RBufferPtr;
buffer[80] = '\0';
newptr = CurrentPtr + 1;
while ( 1 ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
if ( newptr + 80 > TraceStart+BufferSize ) {
readsize = TraceStart+BufferSize - newptr;
} else {
readsize = 80;
}
getmem( newptr, buffer, readsize, NULL );
bptr = buffer;
for (i = 0; i<80 ; i++ ) {
if ( buffer[i] == '\n') {
buffer[i] = 0;
printf( "%s\n", bptr );
bptr = &buffer[i+1];
}
}
printf( "%s", bptr );
//
// If we're back to where we started, break out of here.
//
if ( (newptr <= CurrentPtr) &&
(newptr + readsize) >= CurrentPtr ) {
break;
}
//
// Advance the running pointer.
//
newptr += readsize;
if ( newptr >= TraceStart+BufferSize ) {
newptr = TraceStart;
}
}
printf( "\n");
}
VOID
logonlist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
Routine Description:
This routine prints out the logon list for the rdr. Arguments
to this function are ignored.
--*/
{
DWORD addrLogonList;
WCHAR Data[64];
BOOL b;
PLIST_ENTRY LogonList;
DWORD addrLogonEntry;
LOGON Logon;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
// Get the address of the logon list.
addrLogonList = getsymaddr( "nwrdr!logonlist" );
if ( addrLogonList == 0 ) {
printf("The logon list could not be located.\n");
return;
}
// Walk the list of servers
printf("pLogon User Name Password Pref Server UID\n" );
printf("---------------------------------------------------------------------------\n" );
for ( GET_DWORD( &LogonList, addrLogonList );
LogonList != (PLIST_ENTRY)addrLogonList;
GET_DWORD( &LogonList, LogonList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrLogonEntry = (DWORD)CONTAINING_RECORD( LogonList, LOGON, Next );
printf("%08lx ", addrLogonEntry );
b = (getmem)((LPVOID)addrLogonEntry,
&Logon,
sizeof( Logon ),
NULL);
if ( b == 0 ) return;
if ( Logon.NodeTypeCode != NW_NTC_LOGON ) {
printf( "<invalid node type>\n" );
return;
}
b = GET_STRING( Data, Logon.UserName );
if ( b ) {
printf( "%-15ws", Data );
} else {
printf( "%-15s", "Unreadable" );
}
/*
b = GET_STRING( Data, Logon.PassWord );
if ( b ) {
printf( "%-15ws", Data );
} else {
printf( "%-15s", "Unreadable" );
}
*/
printf( "%-15s", "<secret>" );
b = GET_STRING( Data, Logon.ServerName );
if ( b ) {
printf( "%-15ws", Data );
} else {
printf( "%-15s", "Unreadable" );
}
printf( "%08lx:%08x\n", Logon.UserUid.HighPart, Logon.UserUid.LowPart );
}
printf("---------------------------------------------------------------------------\n" );
}
//
// Functions that help mangle lists of objects.
//
VOID
vcblist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function takes a pointer to the pageable portion
or non-pageable portion of an SCB and dumps the VCB
list for that SCB.
--*/
{
BOOL b;
PVOID objAddr;
PLIST_ENTRY VcbList;
DWORD addrVcbList;
PVCB addrVcb;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
// Figure out which object we have.
objAddr = (PVOID)getexpr( lpArgumentString );
// Invariant: If we leave the switch, objAddr must point to the
// pageable portion of the SCB that we are interested in.
switch ( GetNodeType( (DWORD)objAddr, lpExtensionApis ) ) {
case NW_NTC_SCB:
break;
case NW_NTC_SCBNP:
GET_DWORD( &objAddr,
( (PCHAR)objAddr + FIELD_OFFSET( NONPAGED_SCB, pScb ) ) );
if ( objAddr == 0 ) return;
break;
default:
printf( "(invalid node type code: argument must point to an scb or npscb)\n" );
return;
}
// Get the head of the vcb list.
addrVcbList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( SCB, ScbSpecificVcbQueue ));
// Walk the list and print.
for ( GET_DWORD( &VcbList, addrVcbList ) ;
VcbList != (PLIST_ENTRY)addrVcbList ;
GET_DWORD( &VcbList, VcbList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrVcb = (PVCB)CONTAINING_RECORD( VcbList, VCB, VcbListEntry );
if( GetNodeType( (DWORD)addrVcb, lpExtensionApis ) != NW_NTC_VCB )
printf( "(invalid entry in vcb list)\n" );
else
DumpVcb( (DWORD)addrVcb, lpExtensionApis );
}
}
VOID
irplist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function takes a pointer to the non-pageable portion
of an SCB and dumps the IRP list for that non-pageable SCB.
--*/
{
PLIST_ENTRY IrpList;
DWORD addrIrpList;
PIRP_CONTEXT addrIrp;
PVOID objAddr;
BOOL b;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
// Figure out which object we have.
objAddr = (PVOID)getexpr( lpArgumentString );
// Invariant: If we leave the switch, objAddr must point to the
// non-pageable portion of the SCB that we are interested in.
switch ( GetNodeType( (DWORD)objAddr, lpExtensionApis ) ) {
case NW_NTC_SCB:
GET_DWORD( &objAddr,
( (PCHAR)objAddr + FIELD_OFFSET( SCB, pNpScb ) ) );
if ( objAddr == 0 ) return;
break;
case NW_NTC_SCBNP:
break;
default:
printf( "(invalid node type code: argument must point to an scb or npscb)\n" );
return;
}
// Get the head of the request list.
addrIrpList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( NONPAGED_SCB, Requests ));
// Walk the list and print.
for ( GET_DWORD( &IrpList, addrIrpList ) ;
IrpList != (PLIST_ENTRY)addrIrpList ;
GET_DWORD( &IrpList, IrpList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrIrp = (PIRP_CONTEXT)CONTAINING_RECORD( IrpList, IRP_CONTEXT, NextRequest );
if( GetNodeType( (DWORD)addrIrp, lpExtensionApis ) != NW_NTC_IRP_CONTEXT )
printf( "(invalid entry in the irp context list)\n" );
else
DumpIrpContext( (DWORD)addrIrp, lpExtensionApis );
}
}
VOID
fcblist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function takes a pointer to a VCB and dumps
the FCB list for that VCB.
--*/
{
PLIST_ENTRY FcbList;
DWORD addrFcbList;
PFCB addrFcb;
NODE_TYPE_CODE ntc;
PVOID objAddr;
BOOL b;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
// Figure out which object we have.
objAddr = (PVOID)getexpr( lpArgumentString );
if ( GetNodeType( (DWORD)objAddr, lpExtensionApis ) != NW_NTC_VCB ) {
printf( "(invalid node type code: argument must point to a vcb)\n" );
return;
}
// Get the head of the fcb list.
addrFcbList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( VCB, FcbList ));
for ( GET_DWORD( &FcbList, addrFcbList ) ;
FcbList != (PLIST_ENTRY)addrFcbList ;
GET_DWORD( &FcbList, FcbList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrFcb = (PFCB)CONTAINING_RECORD( FcbList, FCB, FcbListEntry );
ntc = GetNodeType( (DWORD)addrFcb, lpExtensionApis );
if( (ntc != NW_NTC_FCB) && (ntc != NW_NTC_DCB) )
printf( "(invalid entry in the fcb list)\n" );
else
DumpFcb( (DWORD)addrFcb, lpExtensionApis, TRUE );
}
}
VOID
icblist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function takes a pointer to the pageable portion
of an SCB or FCB and dumps the ICB list for that SCB or FCB.
--*/
{
PVOID objAddr;
BOOL b;
NODE_TYPE_CODE ntc;
PICB addrIcb;
PLIST_ENTRY IcbList;
DWORD addrIcbList, IcbCount;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
// Figure out which object we have.
objAddr = (PVOID)getexpr( lpArgumentString );
// Invariant: If we leave the switch, addrIcbList must point
// to the head of the ICB list that we are interested in.
switch ( GetNodeType( (DWORD)objAddr, lpExtensionApis ) ) {
case NW_NTC_SCB:
addrIcbList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( SCB, IcbList ));
break;
case NW_NTC_SCBNP:
// Look up the pageable portion.
GET_DWORD( &objAddr,
( (PCHAR)objAddr + FIELD_OFFSET( NONPAGED_SCB, pScb ) ) );
if ( objAddr == 0 ) return;
// Now get it.
addrIcbList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( SCB, IcbList));
break;
case NW_NTC_FCB:
case NW_NTC_DCB:
addrIcbList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( FCB, IcbList ));
break;
case NW_NTC_NONPAGED_FCB:
// Look up the pageable portion.
GET_DWORD( &objAddr,
( (PCHAR)objAddr + FIELD_OFFSET( NONPAGED_FCB, Fcb ) ) );
if (objAddr == 0) return;
// Now get it.
addrIcbList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( FCB, IcbList ));
break;
default:
printf( "(invalid node type: argument must be: scb, npscb, fcb, dcb, or npfcb)\n" );
return;
}
// Walk the list.
for ( GET_DWORD( &IcbList, addrIcbList ) ;
IcbList != (PLIST_ENTRY)addrIcbList ;
GET_DWORD( &IcbList, IcbList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrIcb = (PICB)CONTAINING_RECORD( IcbList, ICB, ListEntry );
ntc = GetNodeType( (DWORD)addrIcb, lpExtensionApis );
if( (ntc != NW_NTC_ICB) && (ntc != NW_NTC_ICB_SCB) )
printf( "(invalid entry in icb list)\n" );
else
DumpIcb( (DWORD)addrIcb, lpExtensionApis );
}
}
VOID
credlist(
#ifdef WINDBG
HANDLE hProcess,
HANDLE hThread,
#endif
DWORD dwCurrentPc,
PNTKD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
This function takes a pointer to a LOGON and dumps
the NDS credential list for that user.
--*/
{
PLIST_ENTRY CredList;
DWORD addrCredList;
PNDS_SECURITY_CONTEXT addrCred;
NODE_TYPE_CODE ntc;
PVOID objAddr;
BOOL b;
PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
// Figure out which object we have.
objAddr = (PVOID)getexpr( lpArgumentString );
if ( GetNodeType( (DWORD)objAddr, lpExtensionApis ) != NW_NTC_LOGON ) {
printf( "(invalid node type code: argument must point to a logon)\n" );
return;
}
// Get the head of the fcb list.
addrCredList = (DWORD)((PCHAR)objAddr + FIELD_OFFSET( LOGON, NdsCredentialList ));
for ( GET_DWORD( &CredList, addrCredList ) ;
CredList != (PLIST_ENTRY)addrCredList ;
GET_DWORD( &CredList, CredList ) ) {
if ( lpCheckControlCRoutine() ) {
printf("<<<User Stop>>>\n");
break;
}
addrCred = (PNDS_SECURITY_CONTEXT)
CONTAINING_RECORD( CredList,
NDS_SECURITY_CONTEXT,
Next );
ntc = GetNodeType( (DWORD)addrCred, lpExtensionApis );
if( (ntc != NW_NTC_NDS_CREDENTIAL ) )
printf( "(invalid entry in the credential list)\n" );
else
DumpCredential( (DWORD)addrCred, lpExtensionApis);
printf("\n");
}
}