windows-nt/Source/XPSP1/NT/base/fs/mup/kdext/wdbgxlib.c
2020-09-26 16:20:57 +08:00

449 lines
9.4 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
wdbgxlib.c
Abstract:
This module realizes most of the routines needed for the rdbss/smbmini debugger extension.
Author:
Balan Sethu Raman (SethuR) 11-May-1994
Notes:
Revision History:
11-Nov-1994 SethuR Created
11-Nov-1995 Changed to newer windbg apis
--*/
#include <ntos.h>
#include <nturtl.h>
#include "ntverp.h"
#include <windows.h>
#include <wdbgexts.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <kdextlib.h>
WINDBG_EXTENSION_APIS ExtensionApis;
EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
#define ERRPRT dprintf
#define NL 1
#define NONL 0
USHORT SavedMajorVersion;
USHORT SavedMinorVersion;
BOOL ChkTarget; // is debuggee a CHK build?
/*
* Print out an optional message, an ANSI_STRING, and maybe a new-line
*/
BOOL
wPrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
{
PCHAR StringData;
ULONG BytesRead;
if( msg )
dprintf( msg );
if( pStr->Length == 0 ) {
if( nl )
dprintf( "\n" );
return TRUE;
}
StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
if( StringData == NULL ) {
ERRPRT( "Out of memory!\n" );
return FALSE;
}
ReadMemory( (ULONG_PTR)pStr->Buffer,
StringData,
pStr->Length,
&BytesRead );
if ( BytesRead ) {
StringData[ pStr->Length ] = '\0';
dprintf("%s%s", StringData, nl ? "\n" : "" );
}
LocalFree((HLOCAL)StringData);
return BytesRead;
}
BOOL
wPrintStringW( IN LPSTR msg OPTIONAL, IN PUNICODE_STRING pStr, IN BOOL nl )
{
UNICODE_STRING NewStr;
ULONG BytesRead;
if( msg )
dprintf( msg );
if( pStr->Length == 0 ) {
if( nl )
dprintf( "\n" );
return TRUE;
}
NewStr.Buffer = (WCHAR *)LocalAlloc( LPTR, pStr->Length + 1 );
NewStr.Length = pStr->Length;
NewStr.MaximumLength = pStr->Length+1;
if( NewStr.Buffer == NULL ) {
ERRPRT( "Out of memory!\n" );
return FALSE;
}
ReadMemory( (ULONG_PTR)pStr->Buffer,
NewStr.Buffer,
pStr->Length,
&BytesRead );
if ( BytesRead ) {
dprintf("%wZ%s", &NewStr, nl ? "\n" : "" );
}
LocalFree((HLOCAL)NewStr.Buffer);
return BytesRead;
}
/*
* Fetches the data at the given address
*/
BOOLEAN
wGetData( ULONG_PTR dwAddress, PVOID ptr, ULONG size)
{
BOOL b;
ULONG BytesRead;
b = ReadMemory( dwAddress, ptr, size, &BytesRead );
if (!b || BytesRead != size ) {
dprintf( "Unable to read %u bytes at %X, for %s\n", size, dwAddress);
return FALSE;
}
return TRUE;
}
/*
* Fetch the null terminated ASCII string at dwAddress into buf
*/
BOOL
wGetString( ULONG_PTR dwAddress, PSZ buf )
{
for(;;) {
if( !wGetData( dwAddress,buf, 1) ){
//dprintf("readfailure at %08lx\n",dwAddress);
return FALSE;
}
//dprintf ("stringing %08lx %08lx %c\n", dwAddress, buf,
// ((*buf==0)?'.':*buf) );
if ( *buf == '\0' ) { break; }
dwAddress++;
buf++;
};
return TRUE;
}
#if 0
/*
* Get 'size' bytes from the debuggee program at 'dwAddress' and place it
* in our address space at 'ptr'. Use 'type' in an error printout if necessary
*/
BOOL
wGetData_srv( IN LPVOID ptr, IN ULONG_PTR dwAddress, IN ULONG size, IN PCSTR type )
{
BOOL b;
ULONG BytesRead;
ULONG count;
while( size > 0 ) {
count = min( size, 3000 );
b = ReadMemory((ULONG) dwAddress, ptr, count, &BytesRead );
if (!b || BytesRead != count ) {
ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
return FALSE;
}
dwAddress += count;
size -= count;
ptr = (LPVOID)((ULONG)ptr + count);
}
return TRUE;
}
/*
* Follow a LIST_ENTRY list beginning with a head at dwListHeadAddr in the debugee's
* address space. For each element in the list, print out the pointer value at 'offset'
*/
BOOL
PrintListEntryList( IN ULONG_PTR dwListHeadAddr, IN LONG offset )
{
LIST_ENTRY ListEntry;
ULONG i=0;
BOOL retval = TRUE;
ULONG count = 20;
if( !wGetData_srv( &ListEntry, dwListHeadAddr, sizeof( ListEntry ), "LIST_ENTRY" ) )
return FALSE;
while( count-- ) {
if( (ULONG_PTR)ListEntry.Flink == dwListHeadAddr || (ULONG_PTR)ListEntry.Flink == 0 )
break;
if( !wGetData_srv( &ListEntry, (ULONG_PTR)ListEntry.Flink, sizeof( ListEntry ), "ListEntry" ) ) {
retval = FALSE;
break;
}
dprintf( "%16X%s", (LONG)ListEntry.Flink + offset, (i && !(i&3)) ? "\n" : "" );
i++;
}
if( count == 0 && (ULONG_PTR)ListEntry.Flink != dwListHeadAddr && ListEntry.Flink ) {
dprintf( "\nTruncated list dump\n" );
} else if( ! ( i && !(i&3) ) ) {
dprintf( "\n" );
}
return retval;
}
#endif
/*
* Print out a single HEX character
*/
VOID
wPrintHexChar( IN UCHAR c )
{
dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
}
/*
* Print out 'buf' of 'cbuf' bytes as HEX characters
*/
VOID
wPrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
{
while( cbuf-- ) {
wPrintHexChar( *buf++ );
dprintf( " " );
}
}
#if 0
/*
* Fetch the null terminated UNICODE string at dwAddress into buf
*/
BOOL
GetString( IN ULONG_PTR dwAddress, IN LPWSTR buf, IN ULONG MaxChars )
{
do {
if( !wGetData_srv( buf, dwAddress, sizeof( *buf ), "UNICODE Character" ) )
return FALSE;
dwAddress += sizeof( *buf );
} while( --MaxChars && *buf++ != '\0' );
return TRUE;
}
#endif
VOID
WinDbgExtensionDllInit(
PWINDBG_EXTENSION_APIS lpExtensionApis,
USHORT MajorVersion,
USHORT MinorVersion
)
{
ExtensionApis = *lpExtensionApis;
SavedMajorVersion = MajorVersion;
SavedMinorVersion = MinorVersion;
ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
}
VOID
CheckVersion(
VOID
)
{
#if DBG
if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
}
#else
if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
}
#endif
}
LPEXT_API_VERSION
ExtensionApiVersion(
VOID
)
{
return &ApiVersion;
}
ULONG FieldOffsetOfContextListEntryInRxC();
VOID ReadRxContextFields(ULONG_PTR RxContext,PULONG_PTR pFcb,PULONG_PTR pThread, PULONG_PTR pMiniCtx2);
DECLARE_API( dump );
HANDLE DumpFile;
CHAR wwDumpFormat[] = "-%06d: %s\n";
VOID DumpRoutine(
ULONG EntryNumber,
PSZ OriginalStringToPrint
)
{
UCHAR Buffer[200];
UCHAR StringToPrint[160];
PUCHAR p,q,r; LONG i;
ULONG n,l3,l2,l1,l0; UCHAR Numbuf[32];
ULONG ReturnedSize;
//dprintf("before %d\n",EntryNumber);
for (p=OriginalStringToPrint,q=StringToPrint,i=160;;) {
PSZ format=NULL;
if (*p==0) break;
if (*p==0x4) {
format = "%lx";
} else if (*p==0x5) {
format = "%ld";
} else if (*p < ' ') {
p++;i--;continue;
}
if (format!=NULL) {
LONG Length;
//translate the number
p++;
l0=*p++;
l1=(*p++)<<8;
l2=(*p++)<<16;
l3=(*p++)<<24;
n = l0 + l1 + l2 + l3;
//dprintf("yaya %d %08lx %08lx %08lx %08lx %08lx\n",n,n,l0,l1,l2,l3);
Length = sprintf(Numbuf,format,n);
if (Length <= i) {
for (r=Numbuf;*r;) { *q++ = *r++; }
i -= Length;
} else {
i = 0;
}
if (i>0) continue;
}
if (i<=0) break;
*q++ = *p++; i--;
}
*q = 0;
//dprintf("after %d\n",EntryNumber);
if (DumpFile == INVALID_HANDLE_VALUE) {
dprintf(wwDumpFormat,EntryNumber,StringToPrint);
return;
}
sprintf(Buffer,wwDumpFormat,EntryNumber,StringToPrint);
WriteFile(DumpFile,Buffer,strlen(Buffer),&ReturnedSize,NULL);
//should i check??
return;
}
PCWSTR ExtensionLib = NULL;
HANDLE hExtensionMod = NULL;
ULONG DebugeeArchitecture = 0;
PCWSTR GetExtensionLibPerDebugeeArchitecture(ULONG DebugeeArchitecture);
DECLARE_API( dump );
DECLARE_API( flags )
{
ULONG i,mask,newline,value;
if( args && *args ) {
sscanf(args,"%lx",&value);
dprintf("Flags for %08lx\n",value);
} else {
dprintf("error in flags: no value presented\n");
return;
}
for (i=newline=0,mask=1;i<32;i++,mask<<=1) {
if (value&mask) {
dprintf(" %02d 0x%08lx%c",i,mask,(newline==0)?' ':'\n');
newline ^= 1;
}
}
if (newline) {
dprintf("\n");
}
}
VOID dprintfsprintfbuffer(BYTE *Buffer)
{
dprintf("%s\n",Buffer);
}
BOOL
wPrintLargeInt(
LARGE_INTEGER *bigint)
{
dprintf( "%08x:%08x", bigint->HighPart, bigint->LowPart);
return( TRUE );
}