|
|
/*++
Copyright (C) Microsoft Corporation, 1992 - 1999
Module Name:
util.c
Abstract:
Utility library used for the various debugger extensions in this library.
Author:
Peter Wieland (peterwie) 16-Oct-1995
Environment:
User Mode.
Revision History:
--*/
#include "pch.h"
#include "classkd.h" // routines that are useful for all class drivers
PUCHAR devicePowerStateNames[] = { "PowerDeviceUnspecified", "PowerDeviceD0", "PowerDeviceD1", "PowerDeviceD2", "PowerDeviceD3", "PowerDeviceMaximum", "Invalid" };
FLAG_NAME SrbFlags[] = { FLAG_NAME(SRB_FLAGS_QUEUE_ACTION_ENABLE), FLAG_NAME(SRB_FLAGS_DISABLE_DISCONNECT), FLAG_NAME(SRB_FLAGS_DISABLE_SYNCH_TRANSFER), FLAG_NAME(SRB_FLAGS_BYPASS_FROZEN_QUEUE), FLAG_NAME(SRB_FLAGS_DISABLE_AUTOSENSE), FLAG_NAME(SRB_FLAGS_DATA_IN), FLAG_NAME(SRB_FLAGS_DATA_OUT), FLAG_NAME(SRB_FLAGS_NO_DATA_TRANSFER), FLAG_NAME(SRB_FLAGS_UNSPECIFIED_DIRECTION), FLAG_NAME(SRB_FLAGS_NO_QUEUE_FREEZE), FLAG_NAME(SRB_FLAGS_ADAPTER_CACHE_ENABLE), FLAG_NAME(SRB_FLAGS_IS_ACTIVE), FLAG_NAME(SRB_FLAGS_ALLOCATED_FROM_ZONE), FLAG_NAME(SRB_FLAGS_SGLIST_FROM_POOL), FLAG_NAME(SRB_FLAGS_BYPASS_LOCKED_QUEUE), FLAG_NAME(SRB_FLAGS_NO_KEEP_AWAKE), {0,0} };
char *g_genericErrorHelpStr = "\n" \ "**************************************************************** \n" \ " Make sure you have _private_ symbols for classpnp.sys loaded.\n" \ " The FDO parameter should be the upper AttachedDevice of the disk/cdrom/etc PDO\n" \ " as returned by '!devnode 0 1 {disk|cdrom|4mmdat|etc}'.\n" \ "**************************************************************** \n\n" \ ;
VOID GetAddress( IN PCSTR Args, OUT PULONG64 Address ) { UCHAR addressBuffer[256];
addressBuffer[0] = '\0'; sscanf(Args, "%s", addressBuffer); addressBuffer[255] = '\0';
*Address = 0;
if (addressBuffer[0] != '\0') {
//
// they provided an address
//
*Address = GetExpression(addressBuffer);
//
// if that still doesn't parse, print an error
//
if (*Address==0) {
dprintf("An error occured trying to evaluate the address\n"); *Address = 0; return;
}
} return; }
VOID GetAddressAndDetailLevel( IN PCSTR Args, OUT PULONG64 Address, OUT PLONG Detail ) { UCHAR addressBuffer[256]; UCHAR detailBuffer[256];
addressBuffer[0] = '\0'; detailBuffer[0] = '\0'; sscanf(Args, "%s %s", addressBuffer, detailBuffer); addressBuffer[255] = '\0'; detailBuffer[255] = '\0';
*Address = 0; *Detail = 0;
if (addressBuffer[0] != '\0') {
//
// they provided an address
//
*Address = GetExpression(addressBuffer);
//
// if that still doesn't parse, print an error
//
if (*Address==0) {
dprintf("An error occured trying to evaluate the address\n"); *Address = 0; *Detail = 0; return;
}
//
// if they provided a detail level get it.
//
if (detailBuffer[0] == '\0') {
*Detail = 0;
} else {
*Detail = (ULONG)GetExpression(detailBuffer);
} } return; }
VOID GetAddressAndDetailLevel64( IN PCSTR Args, OUT PULONG64 Address, OUT PLONG Detail ) { UCHAR addressBuffer[256]; UCHAR detailBuffer[256];
addressBuffer[0] = '\0'; detailBuffer[0] = '\0'; sscanf(Args, "%s %s", addressBuffer, detailBuffer); addressBuffer[255] = '\0'; detailBuffer[255] = '\0';
*Address = 0; *Detail = 0;
if (addressBuffer[0] != '\0') {
//
// they provided an address
//
*Address = GetExpression(addressBuffer);
//
// if that still doesn't parse, print an error
//
if (*Address==0) {
dprintf("An error occured trying to evaluate the address\n"); *Address = 0; *Detail = 0; return;
}
//
// if they provided a detail level get it.
//
if (detailBuffer[0] == '\0') {
*Detail = 0;
} else {
*Detail = (ULONG)GetExpression(detailBuffer);
} } return; }
PUCHAR DevicePowerStateToString( IN DEVICE_POWER_STATE State )
{ if(State > PowerDeviceMaximum) { return devicePowerStateNames[PowerDeviceMaximum + 1]; } else { return devicePowerStateNames[(UCHAR) State]; } }
//
// Translates various printf formats to account for the target platform.
//
// This looks for %p type format and truncates the top 4 bytes of the ULONG64
// address argument if the debugee is a 32 bit machine.
// The %p is replaced by %I64x in format string.
//
BOOL TranslateFormat( LPSTR formatOut, LPCSTR format, va_list args, ULONG formatOutSize ) { #define Duplicate(j,i) (formatOut[j++] = format[i++])
ULONG minSize = strlen(format), i = 0, j = 0; CHAR c; BOOL TypeFormat = FALSE; BOOL FormatChanged = FALSE;
do { c = format[i];
if (c=='%') { TypeFormat = !TypeFormat; } if (TypeFormat) { switch (c) { case 'c': case 'C': case 'i': case 'd': case 'o': case 'u': case 'x': case 'X': Duplicate(j,i); va_arg(args, int); TypeFormat = FALSE; break; case 'e': case 'E': case 'f': case 'g': case 'G': Duplicate(j,i); va_arg(args, double); TypeFormat = FALSE; break; case 'n': Duplicate(j,i); va_arg(args, int*); TypeFormat = FALSE; break; case 'N': // Native pointer, turns into %p.
formatOut[j++] = 'p'; FormatChanged = TRUE; i++; va_arg(args, void*); TypeFormat = FALSE; break; case 's': case 'S': Duplicate(j,i); va_arg(args, char*); TypeFormat = FALSE; break;
case 'I': if ((format[i+1] == '6') && (format[i+2] == '4')) { Duplicate(j,i); Duplicate(j,i); va_arg(args, ULONG64); TypeFormat = FALSE; } // dprintf("I64 a0 %lx, off %lx\n", args.a0, args.offset);
Duplicate(j,i); break; case 'z': case 'Z': // unicode string
Duplicate(j,i); va_arg(args, void*); TypeFormat = FALSE; break;
case 'p': case 'P': minSize +=3; if (format[i-1] == '%') { minSize++; if (IsPtr64()) { minSize += 2; if (minSize > formatOutSize) { return FALSE; } formatOut[j++] = '0'; formatOut[j++] = '1'; formatOut[j++] = '6'; } else { if (minSize > formatOutSize) { return FALSE; } formatOut[j++] = '0'; formatOut[j++] = '8'; } }
if (minSize > formatOutSize) { return FALSE; } formatOut[j++] = 'I'; formatOut[j++] = '6'; formatOut[j++] = '4'; formatOut[j++] = (c == 'p') ? 'x' : 'X'; ++i; FormatChanged = TRUE;
if (!IsPtr64()) { PULONG64 Arg;
#ifdef _M_ALPHA
Arg = (PULONG64) ((args.a0)+args.offset); //dprintf("a0 %lx, off %lx\n", args.a0, args.offset);
#else
Arg = (PULONG64) (args); #endif
//
// Truncate signextended addresses
//
*Arg = (ULONG64) (ULONG) *Arg; }
va_arg(args, ULONG64); TypeFormat = FALSE; break;
default: Duplicate(j,i); } /* switch */ } else { Duplicate(j,i); } } while (format[i] != '\0');
formatOut[j] = '\0'; return FormatChanged; #undef Duplicate
}
/*
* xdprintf * * Prints formatted text with leading spaces. * * WARNING: DOES NOT HANDLE ULONG64 PROPERLY. */ VOID xdprintf( ULONG Depth, PCCHAR Format, ... ) { va_list args; ULONG i; CCHAR DebugBuffer[256];
for (i=0; i<Depth; i++) { dprintf (" "); }
va_start(args, Format); _vsnprintf(DebugBuffer, 255, Format, args); dprintf (DebugBuffer); va_end(args); }
VOID DumpFlags( ULONG Depth, PUCHAR Name, ULONG Flags, PFLAG_NAME FlagTable ) { ULONG i; ULONG mask = 0; ULONG count = 0;
UCHAR prolog[64];
sprintf(prolog, "%s (0x%08x): ", Name, Flags);
xdprintf(Depth, "%s", prolog);
if(Flags == 0) { dprintf("\n"); return; }
memset(prolog, ' ', strlen(prolog));
for(i = 0; FlagTable[i].Name != 0; i++) {
PFLAG_NAME flag = &(FlagTable[i]);
mask |= flag->Flag;
if((Flags & flag->Flag) == flag->Flag) {
//
// print trailing comma
//
if(count != 0) {
dprintf(", ");
//
// Only print two flags per line.
//
if((count % 2) == 0) { dprintf("\n"); xdprintf(Depth, "%s", prolog); } }
dprintf("%s", flag->Name);
count++; } }
dprintf("\n");
if((Flags & (~mask)) != 0) { xdprintf(Depth, "%sUnknown flags %#010lx\n", prolog, (Flags & (~mask))); }
return; }
BOOLEAN GetAnsiString( IN ULONG64 Address, IN PUCHAR Buffer, IN OUT PULONG Length ) { ULONG i = 0;
//
// Grab the string in 64 character chunks until we find a NULL or the
// read fails.
//
while((i < *Length) && (!CheckControlC())) {
ULONG transferSize; ULONG result;
if(*Length - i < 128) { transferSize = *Length - i; } else { transferSize = 128; }
if(!ReadMemory(Address + i, Buffer + i, transferSize, &result)) { //
// read failed and we didn't find the NUL the last time. Don't
// expect to find it this time.
//
*Length = i; return FALSE;
} else {
ULONG j;
//
// Scan from where we left off looking for that NUL character.
//
for(j = 0; j < transferSize; j++) {
if(Buffer[i + j] == '\0') { *Length = i + j; return TRUE; } } }
i += transferSize; }
//
// We never found the NUL. Don't need to update Length since it's currently
// equal to i.
//
return FALSE; }
PCHAR GuidToString( GUID* Guid ) { static CHAR Buffer [64]; sprintf (Buffer, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", Guid->Data1, Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7] );
return Buffer; }
ULONG64 GetDeviceExtension( ULONG64 address )
/*++
Routine Description:
The function accepts the address of either a device object or a device extension. If the supplied address is that of a device object, the device extension is retrieved and returned. If the address is that of a device extension, the address is returned unmodified.
Arguments:
Address - address of a device extension or a device object
Return Value:
The address of the device extension or 0 if an error occurs.
--*/
{ ULONG result; CSHORT Type; ULONG64 Address = address;
//
// The supplied address may be either the address of a device object or the
// address of a device extension. To distinguish which, we treat the
// address as a device object and read what would be its type field. If
// the
//
result = GetFieldData(Address, "scsiport!_DEVICE_OBJECT", "Type", sizeof(CSHORT), &Type ); if (result) { SCSIKD_PRINT_ERROR(result); return 0; } //
// See if the supplied address holds a device object. If it does, read the
// address of the device extension. Otherwise, we assume the supplied
// addres holds a device extension and we use it directly.
//
if (Type == IO_TYPE_DEVICE) {
result = GetFieldData(Address, "scsiport!_DEVICE_OBJECT", "DeviceExtension", sizeof(ULONG64), &Address ); if (result) { SCSIKD_PRINT_ERROR(result); return 0; } }
return Address; }
/*
* GetULONGField * * Return the field or -1 in case of error. * Yes, it screws up if the field is actually -1. */ ULONG64 GetULONGField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName) { ULONG64 result; ULONG dbgStat; dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(ULONG64), &result); if (dbgStat != 0){ dprintf("\n GetULONGField: GetFieldData failed with %xh retrieving field '%s' of struct '%s', returning bogus field value %08xh.\n", dbgStat, FieldName, StructType, BAD_VALUE); dprintf(g_genericErrorHelpStr); result = BAD_VALUE; }
return result; }
/*
* GetUSHORTField * * Return the field or -1 in case of error. * Yes, it screws up if the field is actually -1. */ USHORT GetUSHORTField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName) { USHORT result; ULONG dbgStat; dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(USHORT), &result); if (dbgStat != 0){ dprintf("\n GetUSHORTField: GetFieldData failed with %xh retrieving field '%s' of struct '%s', returning bogus field value %08xh.\n", dbgStat, FieldName, StructType, BAD_VALUE); dprintf(g_genericErrorHelpStr); result = (USHORT)BAD_VALUE; }
return result; }
/*
* GetUCHARField * * Return the field or -1 in case of error. * Yes, it screws up if the field is actually -1. */ UCHAR GetUCHARField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName) { UCHAR result; ULONG dbgStat; dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(UCHAR), &result); if (dbgStat != 0){ dprintf("\n GetUCHARField: GetFieldData failed with %xh retrieving field '%s' of struct '%s', returning bogus field value %08xh.\n", dbgStat, FieldName, StructType, BAD_VALUE); dprintf(g_genericErrorHelpStr); result = (UCHAR)BAD_VALUE; }
return result; }
ULONG64 GetFieldAddr(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName) { ULONG64 result; ULONG offset; ULONG dbgStat;
dbgStat = GetFieldOffset(StructType, FieldName, &offset); if (dbgStat == 0){ result = StructAddr+offset; } else { dprintf("\n GetFieldAddr: GetFieldOffset failed with %xh retrieving offset of struct '%s' field '%s'.\n", dbgStat, StructType, FieldName); dprintf(g_genericErrorHelpStr); result = BAD_VALUE; } return result; }
ULONG64 GetContainingRecord(ULONG64 FieldAddr, LPCSTR StructType, LPCSTR FieldName) { ULONG64 result; ULONG offset; ULONG dbgStat; dbgStat = GetFieldOffset(StructType, FieldName, &offset); if (dbgStat == 0){ result = FieldAddr-offset; } else { dprintf("\n GetContainingRecord: GetFieldOffset failed with %xh retrieving offset of struct '%s' field '%s', returning bogus address %08xh.\n", dbgStat, StructType, FieldName, BAD_VALUE); dprintf(g_genericErrorHelpStr); result = BAD_VALUE; }
return result; }
|