/*++ 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 , 09-Jan-1994 --*/ #include "procs.h" #include "nodetype.h" #include #include #include // // 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" ); } 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("\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("\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("\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("\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("\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( "\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( "\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("\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( "" ); 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 : \n" ); } b = GET_STRING( Buffer, Logon.PassWord ); if ( b ) { printf( "Password : %ws\n", Buffer ); } else { printf( "Password : \n" ); } b = GET_STRING( Buffer, Logon.ServerName ); if ( b ) { printf( "Pref Server : %ws\n", Buffer ); } else { printf( "Pref Server : \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( "\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 : \n" ); } b = GET_STRING( Buffer, Context.CurrentContext ); if ( b ) { printf( "Current Context : %ws\n", Buffer ); } else { printf( "Current Context :\n" ); } if ( Context.Credential != NULL ) { printf( "--------------------- Credential Data ----------------------\n"); b = getmem( (PVOID)Context.Credential, &Credential, sizeof(NDS_CREDENTIAL), NULL ); if (!b ) { printf( "\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( "\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( "\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( "\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("<<>>\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("\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("\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("<<>>\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("<<>>\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("<<>>\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( "\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", "" ); 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("<<>>\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("<<>>\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("<<>>\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("<<>>\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("<<>>\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"); } }