windows-nt/Source/XPSP1/NT/drivers/storage/kdext/redbook/redbook.c

1388 lines
33 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) Microsoft Corporation, 1992 - 1999
Module Name:
redbook.c
Abstract:
Debugger Extension Api for interpretting scsiport structures
Author:
Henry Gabryjelski 23-Oct-1998
Environment:
User Mode.
Revision History:
--*/
#include "pch.h"
#define INDENT 2
//#define PRINT_LINE() dprintf("Line %4d File %s\n", __LINE__, __FILE__)
#define DUMP_STRUCT(v,d,x,y) \
if ((v) <= Detail) { xdprintf( (d), "%-20s - %#010x\n", (x), (y) ); }
#define DUMP_STRUCT_P(v,d,x,y) \
if ((v) <= Detail) { xdprintf( (d), "%-20s - %#p\n", (x), (y) ); }
#define DUMP_STRUCT64(v,d,x,y) \
if ((v) <= Detail) { xdprintf( (d), "%-20s - %#016I64x\n", (x), (y) ); }
#define PRINT_FLAGS(Flags,b) \
if (Flags & b) { dprintf( #b ", " ); }
typedef struct _FLAG_NAME {
ULONG Flag;
PUCHAR Name;
} FLAG_NAME, *PFLAG_NAME;
#define FLAG_NAME(flag) {flag, #flag}
FLAG_NAME CdFlags[] = {
FLAG_NAME(CD_STOPPED), // 0000 0001
FLAG_NAME(CD_PAUSED), // 0000 0002
FLAG_NAME(CD_PLAYING), // 0000 0004
FLAG_NAME(CD_STOPPING), // 0000 0010
FLAG_NAME(CD_PAUSING), // 0000 0020
{0,0}
};
PUCHAR const REDBOOK_CC_STRINGS[5] = {
" Read ",
" Stream ",
" Read Com ",
"Stream Com",
"*Unknown* "
};
VOID
DumpToc(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpContext(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpFlags(
LONG Depth,
PUCHAR Name,
ULONG Flags,
PFLAG_NAME FlagTable
);
VOID
DumpList(
PVOID AddressOfListHead
);
VOID
DumpRedBookBufferData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpRedBookCdromInfo(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpRedBookExtension(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpRedBookStreamData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpRedBookThreadData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpRedBookWmiData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
DumpRedBookWmiPerf(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
);
VOID
GetPointer(
IN ULONG_PTR Address,
OUT ULONG_PTR *Value
);
VOID
GetAddressAndDetailLevelFromArgs(
PCSTR Args,
PULONG_PTR Address,
PULONG Detail
);
VOID
ParseArguments(
PCSTR Args,
PULONG_PTR Address,
PULONG Detail,
PVOID Block
);
VOID
xdprintf(
LONG Depth,
PCCHAR S,
...
);
////////////////////////////////////////////////////////////////////////////////
DECLARE_API(ext)
/*++
Routine Description:
Dumps the device extension for a given device object, or dumps the
given device extension
--*/
{
ULONG_PTR address;
ULONG detail = 0;
UCHAR block[sizeof(REDBOOK_DEVICE_EXTENSION)];
PUCHAR blah;
ParseArguments(args, &address, &detail, block);
if (address == 0) {
return;
}
blah = block; // no field offset
// address = FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, .);
DumpRedBookExtension(block, address, detail, 0);
return;
}
DECLARE_API(toc)
/*++
Routine Description:
Dumps the device extension for a given device object, or dumps the
given device extension
--*/
{
ULONG_PTR address;
ULONG detail = 0;
UCHAR block[sizeof(CDROM_TOC)];
ULONG result;
GetAddressAndDetailLevelFromArgs(args, &address, &detail);
if (address == 0) {
return;
}
if(!ReadMemory(address, block, sizeof(CDROM_TOC), &result)) {
xdprintf(0, "Error reading CDROM_TOC at address %p\n", address);
return;
}
DumpToc(block, address, detail, 0);
return;
}
DECLARE_API(context)
/*++
Routine Description:
Dumps the device extension for a given device object, or dumps the
given device extension
--*/
{
ULONG_PTR address;
ULONG detail = 0;
UCHAR block[sizeof(REDBOOK_COMPLETION_CONTEXT)];
ULONG result;
GetAddressAndDetailLevelFromArgs(args, &address, &detail);
if (address == 0) {
return;
}
if(!ReadMemory(address, block, sizeof(REDBOOK_COMPLETION_CONTEXT), &result)) {
xdprintf(0, "Error reading CDROM_TOC at address %p\n", address);
return;
}
DumpContext(block, address, detail, 0);
return;
}
DECLARE_API(silence)
{
ULONG_PTR silenceAddress;
ULONG silence;
ULONG result;
UCHAR * silenceString = "redbook!RedBookForceSilence";
silenceAddress = (ULONG_PTR) GetExpression(silenceString);
if (!silenceAddress) {
dprintf(
"Unable to get address of %s\n"
"It could be that redbook is not loaded,"
"was build FRE, or the symbols are wrong\n",
silenceString
);
return;
}
if (!ReadMemory(silenceAddress, &silence, sizeof(ULONG), &result)) {
dprintf("Unable to read current value for silence (%p)!\n",
silenceAddress);
return;
}
//
// allow them to provide an argument?
//
if (args[0]) {
silence = (ULONG) GetExpression(args);
dprintf("Setting ForceSilence %s\n", (silence?"on":"off"));
} else {
dprintf("Toggling ForceSilence from %s to %s\n",
(silence?"on":"off"),
(silence?"off":"on"));
silence = (silence?0:1);
}
if(!WriteMemory(silenceAddress, &silence, sizeof(ULONG), &result)) {
dprintf("Unable to set ForceSilence %s\n", (silence?"on":"off"));
return;
}
return;
}
DECLARE_API(wmiperfclear)
{
ULONG_PTR address;
ULONG detail = 0;
ULONG result;
UCHAR block[sizeof(REDBOOK_DEVICE_EXTENSION)];
PREDBOOK_DEVICE_EXTENSION deviceExtension;
ParseArguments(args, &address, &detail, block);
if (address == 0) {
return;
}
deviceExtension = (PREDBOOK_DEVICE_EXTENSION)block;
deviceExtension->WmiPerf.TimeReadDelay = 0;
deviceExtension->WmiPerf.TimeReading = 0;
deviceExtension->WmiPerf.TimeStreamDelay = 0;
deviceExtension->WmiPerf.TimeStreaming = 0;
deviceExtension->WmiPerf.DataProcessed = 0;
deviceExtension->WmiPerf.StreamPausedCount = 0;
if(!WriteMemory(address, (PVOID)block, sizeof(REDBOOK_DEVICE_EXTENSION), &result)) {
xdprintf(0, "Error writing redbook wmi data to address %p\n", address);
return;
}
return;
}
////////////////////////////////////////////////////////////////////////////////
PUCHAR ErrorText[REDBOOK_ERR_MAXIMUM] = {
"Errors Reading Raw Audio",
"Errors Streaming Raw Audio",
"Errors opening SysAudio Mixer",
"Errors creating virtual source",
"Errors opening preferred waveout device",
"Errors getting number of pins on waveout device",
"Errors connecting to playback pins on waveout device",
"Errors initializing WMI",
"Errors creating thread",
"Warning due to insufficient data (stream paused)",
"This is an unsupported drive"
};
VOID
DumpRedBookErrors(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_DEVICE_EXTENSION DeviceExtension = X;
ULONG_PTR errorCountAddress;
ULONG tmp;
ULONG errors[REDBOOK_ERR_MAXIMUM];
Depth += INDENT;
errorCountAddress =
(ULONG_PTR)((PUCHAR)Address +
FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, ErrorLog.RCount[0]));
xdprintf(Depth, "%x Errors Reported. Error Counts at %p\n",
DeviceExtension->ErrorLog.Count, errorCountAddress);
if (!ReadMemory(errorCountAddress, &errors,
sizeof(ULONG) * REDBOOK_ERR_MAXIMUM, &tmp)) {
xdprintf(Depth, "Unable to read error information\n");
return;
}
Depth += INDENT;
for (tmp = 0; tmp < REDBOOK_ERR_MAXIMUM; tmp++) {
if (errors[tmp] != 0) {
xdprintf(Depth, "%2x - %s\n", errors[tmp], ErrorText[tmp]);
}
}
Depth -= INDENT;
}
////////////////////////////////////////////////////////////////////////////////
VOID
DumpRedBookExtension(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_DEVICE_EXTENSION DeviceExtension = X;
Depth += INDENT;
dprintf("\n");
xdprintf(Depth, "Device Extension at %p\n", Address);
xdprintf(Depth, "TargetDevObj %p TargetPdo %p SelfDevObj %p\n",
DeviceExtension->TargetDeviceObject,
DeviceExtension->TargetPdo,
DeviceExtension->SelfDeviceObject);
xdprintf(Depth, "PNP: CurrentState %x PreviousState %x\n",
DeviceExtension->Pnp.CurrentState,
DeviceExtension->Pnp.PreviousState);
xdprintf(Depth, " RemovePending %x IoRemoveLock %p\n",
DeviceExtension->Pnp.RemovePending,
Address+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, RemoveLock));
xdprintf(Depth, "WmiLibInfo: %p (%x bytes) Paging Path Count: %x\n",
Address+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, WmiLibInfo),
sizeof(WMILIB_CONTEXT),
DeviceExtension->PagingPathCount);
dprintf("\n");
DumpRedBookErrors(X, Address, Detail, Depth);
DumpRedBookCdromInfo((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,CDRom),
Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,CDRom),
Detail,
Depth
);
DumpRedBookStreamData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Stream),
Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Stream),
Detail,
Depth
);
DumpRedBookThreadData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Thread),
Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Thread),
Detail,
Depth
);
DumpRedBookWmiData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiData),
Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiData),
Detail,
Depth
);
DumpRedBookWmiPerf((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiPerf),
Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiPerf),
Detail,
Depth
);
DumpRedBookBufferData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Buffer),
Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Buffer),
Detail,
Depth
);
if (Detail) {
ULONG Index;
ULONG i;
PUCHAR savedIo;
Index = DeviceExtension->SavedIoCurrentIndex + (SAVED_IO_MAX - 1);
Index %= SAVED_IO_MAX;
savedIo = (PUCHAR)Address;
savedIo += FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,SavedIo[0].IrpWithoutStack);
xdprintf(Depth, "Irp History: \n");
for (i=0; i < SAVED_IO_MAX; i++) {
ULONG realIndex;
realIndex = Index + i;
realIndex %= SAVED_IO_MAX;
xdprintf(Depth, "Irp %p: !irp %p\n",
DeviceExtension->SavedIo[realIndex].OriginalIrp,
savedIo + (sizeof(SAVED_IO) * realIndex)
);
}
}
dprintf("\n");
return;
}
VOID
DumpRedBookCdromInfo(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_CDROM_INFO Cdrom = X;
xdprintf(Depth, "CDROM INFO at %p\n", Address);
Depth += INDENT;
xdprintf(Depth, "CachedToc %p MediaChangeCount %x\n",
Cdrom->Toc,
Cdrom->CheckVerify);
DumpFlags(Depth, "CdState", Cdrom->StateNow, CdFlags);
xdprintf(Depth, "Sector information:\n");
xdprintf(Depth, "NextToRead %x NextToStream %x FinishedStreaming %x\n",
Cdrom->NextToRead,
Cdrom->NextToStream,
Cdrom->FinishedStreaming);
xdprintf(Depth, "EndPlay %x ReadErrors %x StreamErrors %x\n",
Cdrom->EndPlay,
Cdrom->ReadErrors,
Cdrom->StreamErrors);
xdprintf(Depth, "Volume for ports 0-3: %x %x %x %x\n",
Cdrom->Volume.PortVolume[0],
Cdrom->Volume.PortVolume[1],
Cdrom->Volume.PortVolume[2],
Cdrom->Volume.PortVolume[3]);
Depth -= INDENT;
return;
}
VOID
DumpRedBookWmiData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_WMI_STD_DATA WmiData = X;
xdprintf(Depth, "WMIDATA at %p\n", Address);
Depth += INDENT;
xdprintf(Depth, "Number of buffers: %x\n",
WmiData->NumberOfBuffers
);
xdprintf(Depth, "Sectors: Per Read %x Mask %x Maximum\n",
WmiData->SectorsPerRead,
WmiData->SectorsPerReadMask,
WmiData->MaximumSectorsPerRead
);
xdprintf(Depth, "Enabled %x CDDASupported %x CDDAAccurate %x\n",
WmiData->PlayEnabled,
WmiData->CDDASupported,
WmiData->CDDAAccurate
);
Depth -= INDENT;
return;
}
VOID
DumpRedBookWmiPerf(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_WMI_PERF_DATA WmiPerf = X;
xdprintf(Depth, "WMIPERF at %p\n", Address);
//
// problems printing the info below.
// it actually crashes the debugger.
//
Depth += INDENT;
xdprintf(Depth, "ReadDelay %I64x Reading %I64x\n",
WmiPerf->TimeReadDelay,
WmiPerf->TimeReading
);
xdprintf(Depth, "StreamDelay %I64x Streaming %I64x\n",
WmiPerf->TimeStreamDelay,
WmiPerf->TimeStreaming
);
xdprintf(Depth, "DataProcessed %I64x StreamPausedCount %x\n",
WmiPerf->DataProcessed,
WmiPerf->StreamPausedCount
);
return;
#if 0
if (WmiPerf->DataRead != 0) {
xdprintf( Depth, "\n" );
xdprintf( Depth, " stat seconds\n" );
xdprintf( Depth, "------------- -----------------------------\n" );
#define TIME_FORMAT_STRINGa "%12s: %7I64d.%-02I64d\n"
#define TIME_FORMAT_STRING "%12s: %7I64d.%-07I64d\n"
#define UNITS_PER_SECOND ((LONG64)10000000)
xdprintf( Depth, TIME_FORMAT_STRINGa,
"audio data",
WmiPerf->DataRead / (RAW_SECTOR_SIZE * 75),
(WmiPerf->DataRead / RAW_SECTOR_SIZE) % 75
);
//
// what is the approximate transfer speed of the drive?
// in kb/s, but actually calculated as b/(s / 1024^2)
//
tempStat = WmiPerf->DataRead / 0x00000400; // kb
xdprintf( Depth, " Kbytes read: %I64d\n", tempStat );
xdprintf( Depth, " seconds: %I64d . %I64d\n",
WmiPerf->TimeReading / UNITS_PER_SECOND,
WmiPerf->TimeReading % UNITS_PER_SECOND
);
//
// need to keep the numbers large, so:
//
tempStat = WmiPerf->TimeReading;
tempStat /= (UNITS_PER_SECOND / 0x00000400);
xdprintf( Depth, " approx drive speed: %I64d kb/s\n",
WmiPerf->DataRead / tempStat );
tempStat = WmiPerf->TimeReading +
WmiPerf->TimeReadDelay +
WmiPerf->TimeStreamDelay;
tempStat /= (UNITS_PER_SECOND / 0x00000400);
xdprintf( Depth, "effective drive speed: %I64d kb/s\n",
WmiPerf->DataRead / tempStat );
/*
tempStat /= WmiPerf->TimeReading / UNITS_PER_SECOND; // per second
xdprintf( Depth, "Approximate drive speed: %I64d kb/s\n", tempStat );
xdprintf( Depth, TIME_FORMAT_STRING
"reading",
WmiPerf->TimeReading / UNITS_PER_SECOND,
WmiPerf->TimeReading % UNITS_PER_SECOND
);
xdprintf( Depth, TIME_FORMAT_STRING
"streaming",
WmiPerf->TimeStreaming / UNITS_PER_SECOND,
WmiPerf->TimeStreaming % UNITS_PER_SECOND
);
xdprintf( Depth, TIME_FORMAT_STRING
"read delay",
WmiPerf->TimeReadDelay / UNITS_PER_SECOND,
WmiPerf->TimeReadDelay % UNITS_PER_SECOND
);
xdprintf( Depth, TIME_FORMAT_STRING
"stream delay",
WmiPerf->TimeStreaming / UNITS_PER_SECOND,
WmiPerf->TimeStreaming % UNITS_PER_SECOND
);
//
// now do some simple analysis, use seconds as unit
//
*/
}
Depth -= INDENT;
return;
#endif // 0
}
VOID
DumpRedBookBufferData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_BUFFER_DATA Buffer = X;
ULONG numBuf;
ULONG sectorsPerRead;
ULONG i;
PULONG readOk_X;
PULONG streamOk_X;
ULONG result;
xdprintf(Depth, "BUFFERS at %p\n", Address);
numBuf = CONTAINING_RECORD(X, REDBOOK_DEVICE_EXTENSION, Buffer)->WmiData.NumberOfBuffers;
sectorsPerRead = CONTAINING_RECORD(X, REDBOOK_DEVICE_EXTENSION, Buffer)->WmiData.SectorsPerRead;
Depth += INDENT;
if (Buffer->ReadOk_X == NULL ||
Buffer->StreamOk_X == NULL ||
Buffer->Contexts == NULL) {
xdprintf(Depth, "One of the pointers is NULL\n");
return;
}
readOk_X = (PULONG)LocalAlloc(LPTR, sizeof(ULONG)*numBuf);
streamOk_X = (PULONG)LocalAlloc(LPTR, sizeof(ULONG)*numBuf);
if (readOk_X == NULL ||
streamOk_X == NULL) {
if (readOk_X) {
LocalFree(readOk_X);
}
if (streamOk_X) {
LocalFree(streamOk_X);
}
xdprintf(Depth, "Can't Alloc Memory\n");
return;
}
if(!ReadMemory((ULONG_PTR)(Buffer->ReadOk_X),
readOk_X,
sizeof(ULONG)*numBuf,
&result)) {
xdprintf(0, "Error reading ReadOk_X\n");
LocalFree(readOk_X);
LocalFree(streamOk_X);
return;
}
if(!ReadMemory((ULONG_PTR)(Buffer->StreamOk_X),
streamOk_X,
sizeof(ULONG)*numBuf,
&result)) {
xdprintf(0, "Error reading StreamOk_X\n");
LocalFree(readOk_X);
LocalFree(streamOk_X);
return;
}
//
// now just parse and print
//
xdprintf(Depth, "SkipBuffer %p to %p (%x bytes)\n",
Buffer->SkipBuffer,
Buffer->SkipBuffer + (RAW_SECTOR_SIZE * sectorsPerRead * numBuf),
RAW_SECTOR_SIZE * sectorsPerRead
);
xdprintf(Depth, "IrpStack %x Stream is %s\n",
Buffer->MaxIrpStack,
(Buffer->Paused ?
(Buffer->FirstPause ? "in its first pause" : "paused")
: "not paused")
);
xdprintf(Depth, "Silent Buffer %p Silent Mdl %p\n",
Buffer->SilentBuffer,
Buffer->SilentMdl
);
dprintf("\n");
xdprintf(Depth, "PRINTING %x BUFFERS (does it match?)\n", numBuf);
xdprintf(Depth, " %8s | %10s | %8s | %8s | %8s | %8s\n",
" Index ",
" Reason ",
" Buffer ",
" Mdl ",
" Irp ",
" R/S OK "
);
xdprintf(Depth, "----------+------------+----------+----------+----------+"
"----------\n");
for (i=0;i<numBuf;i++) {
REDBOOK_COMPLETION_CONTEXT context;
if(!ReadMemory((ULONG_PTR)(Buffer->Contexts+i),
&context,
sizeof(REDBOOK_COMPLETION_CONTEXT),
&result)) {
xdprintf(0, "Error reading CompletionContext at address %p\n",
Buffer->Contexts + i);
} else {
xdprintf(Depth, "");
dprintf(" %8x |",
context.Index);
if (context.Reason > 4) {
dprintf(" %s |", REDBOOK_CC_STRINGS[4]);
} else {
dprintf(" %s |", REDBOOK_CC_STRINGS[context.Reason]);
}
dprintf(" %8p |",
context.Buffer);
dprintf(" %8p |",
context.Mdl);
dprintf(" %8p |",
context.Irp);
dprintf(" %4s\n",
(readOk_X[i] ? "R" : (streamOk_X[i] ? "S" : "-")));
}
}
dprintf("\n");
LocalFree(readOk_X);
LocalFree(streamOk_X);
Depth -= INDENT;
return;
}
VOID
DumpRedBookStreamData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_STREAM_DATA Stream = X;
xdprintf(Depth, "STREAM DATA at %p\n", Address);
Depth += INDENT;
xdprintf(Depth, " Pin: FileObject %p DeviceObject %p\n",
Stream->PinFileObject,
Stream->PinDeviceObject);
xdprintf(Depth, "Mixer: FileObject %p PinId %x VolumeNodeId %x\n",
Stream->MixerFileObject,
Stream->MixerPinId,
Stream->VolumeNodeId);
xdprintf(Depth, "Connect@ %p Format@ %p (%x and %x bytes)\n",
Address+FIELD_OFFSET(REDBOOK_STREAM_DATA,Connect),
Address+FIELD_OFFSET(REDBOOK_STREAM_DATA,Format),
sizeof(KSPIN_CONNECT),
sizeof(KSDATAFORMAT_WAVEFORMATEX));
Depth -= INDENT;
return;
}
VOID
DumpRedBookThreadData(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_THREAD_DATA Thread = X;
PUCHAR X2 = (PUCHAR)Address;
xdprintf(Depth, "THREAD DATA at %p\n", Address);
Depth += INDENT;
xdprintf(Depth, "Handle %x Pointer %p ",
Thread->SelfHandle,
Thread->SelfPointer
);
if (Thread->IoctlCurrent) {
dprintf("Current Ioctl: %p\n", Thread->IoctlCurrent);
} else {
dprintf("Current Ioctl: None\n");
}
Thread = X; // BUGBUG - remove this, and Thread gets set to zero above?
xdprintf(Depth, "PendingRead %x Pending Stream %x\n",
Thread->PendingRead,
Thread->PendingStream
);
xdprintf(Depth, "IoctlList:");
DumpList(X2 + FIELD_OFFSET(REDBOOK_THREAD_DATA, IoctlList));
dprintf("\n");
xdprintf(Depth, "WmiList:");
DumpList(X2 + FIELD_OFFSET(REDBOOK_THREAD_DATA, WmiList));
dprintf("\n");
xdprintf(Depth, "DigitalList:");
DumpList(X2 + FIELD_OFFSET(REDBOOK_THREAD_DATA, DigitalList));
dprintf("\n");
Depth -= INDENT;
}
VOID
xdprintf(
LONG Depth,
PCCHAR S,
...
)
{
va_list ap;
LONG i;
CCHAR DebugBuffer[256];
// Tree output as follows:
//
// +- Item
// |
//
//
for (i=0;i<Depth;i++) {
dprintf(" ");
}
va_start(ap, S);
vsprintf(DebugBuffer, S, ap);
dprintf (DebugBuffer);
va_end(ap);
}
VOID
DumpFlags(
LONG 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("NONE\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 %lx\n", prolog, (Flags & (~mask)));
}
return;
}
VOID
GetPointer(
IN ULONG_PTR Address,
OUT ULONG_PTR *Value
)
{
ULONG result;
if(!ReadMemory(Address, (PVOID)*Value, sizeof(ULONG_PTR), &result) ||
result != sizeof(ULONG_PTR)) {
*Value = 0;
}
return;
}
VOID
DumpList(
PVOID AddressOfListHead
)
{
LIST_ENTRY listHead;
LIST_ENTRY current;
LIST_ENTRY slow;
ULONG result;
BOOLEAN advanceSlowList;
if (!ReadMemory((ULONG_PTR)AddressOfListHead,
&listHead,
sizeof(LIST_ENTRY),
&result)) {
dprintf("Unable to read head of list at %p", AddressOfListHead);
return;
}
slow = listHead;
current = listHead;
advanceSlowList = FALSE;
if (current.Flink == AddressOfListHead) {
dprintf("Empty");
return;
}
//
// list is empty when FLink points is AddressOfListHead
// list is looping when Current.BLink == Slow.Blink
//
while (!CheckControlC()) {
if (current.Flink == AddressOfListHead) {
return;
}
//
// print it
//
dprintf(" %p", current.Flink);
//
// advance the list pointers
//
if (!ReadMemory((ULONG_PTR)current.Flink,
&current,
sizeof(LIST_ENTRY),
&result)) {
dprintf(" !! Unable to read memory at %p", AddressOfListHead);
return;
}
if (advanceSlowList) {
// won't fail since current already read this in successfully
ReadMemory((ULONG_PTR)slow.Flink,
&slow,
sizeof(LIST_ENTRY),
&result);
}
advanceSlowList = !advanceSlowList;
//
// check for loops
//
if (current.Blink == slow.Blink) {
dprintf(" !! List %p has a loop!", AddressOfListHead);
return;
}
}
//
// should always exit from above loop
//
}
VOID
GetAddressAndDetailLevelFromArgs(
PCSTR Args,
PULONG_PTR Address,
PULONG Detail
)
{
UCHAR addressBuffer[256];
UCHAR detailBuffer[256];
addressBuffer[0] = '\0';
detailBuffer[0] = '\0';
(VOID)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 = (ULONG_PTR) 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);
}
}
}
VOID
ParseArguments(
PCSTR Args,
PULONG_PTR Address,
PULONG Detail,
PVOID Block
)
{
ULONG result;
PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)Block;
GetAddressAndDetailLevelFromArgs(Args, Address, Detail);
//
// grab this thing as a device object. If it's type field matches what
// we expect then adjust address to point to the actual device extension
//
if(!ReadMemory(*Address, Block, sizeof(DEVICE_OBJECT), &result)) {
xdprintf(0, "Error reading data at address %p\n", *Address);
return;
}
if(deviceObject->Type == IO_TYPE_DEVICE) {
*Address = (ULONG_PTR)deviceObject->DeviceExtension;
}
//
// now get the device extension
//
if(!ReadMemory(*Address, Block, sizeof(REDBOOK_DEVICE_EXTENSION), &result)) {
xdprintf(0, "Error reading device extension at address %p\n", *Address);
return;
}
return;
}
VOID
DumpToc(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PCDROM_TOC Toc = X;
PTRACK_DATA trackData;
ULONG numberOfTracks;
ULONG i;
numberOfTracks = Toc->LastTrack - Toc->FirstTrack;
xdprintf(Depth, "TOC at %p\n", Address);
Depth += INDENT;
xdprintf(Depth, "Key for Control Field:\n");
xdprintf(Depth, " P - Preemphasis\n");
xdprintf(Depth, " C - Copy Protect\n");
xdprintf(Depth, " D,A - Data or Audio Track\n");
xdprintf(Depth, " # - Number of Audio Channels\n\n");
xdprintf(Depth, "FirstTrack %x LastTrack %x NumberOfTracks %x Size: %x\n",
Toc->FirstTrack,
Toc->LastTrack,
numberOfTracks,
(Toc->Length[0] << 8) | (Toc->Length[1])
);
xdprintf(Depth, "Index Track Control MSF Address\n");
xdprintf(Depth, "---------------------------------------------\n");
for (i=0,trackData = Toc->TrackData;
(!CheckControlC()) && i<numberOfTracks+2; // lead-in, lead-out track
i++,trackData++) {
ULONG lba;
UCHAR m,s,f;
if (trackData->Reserved || trackData->Reserved1) {
xdprintf(Depth, "TrackData[%x] has reserved fields filled in. "
"Most likely not a TOC\n", i);
return;
}
lba =
(trackData->Address[0] << 24) |
(trackData->Address[1] << 16) |
(trackData->Address[2] << 8) |
(trackData->Address[3] << 0);
LBA_TO_MSF(lba, m, s, f);
m = s = f = 0;
xdprintf(Depth, " %2x %2x %s %s %s %s %02x:%02x:%02x 0x%06x\n",
i,
trackData->TrackNumber,
TEST_FLAG(trackData->Control, AUDIO_WITH_PREEMPHASIS) ? "P" : "-",
TEST_FLAG(trackData->Control, DIGITAL_COPY_PERMITTED) ? "C" : "-",
TEST_FLAG(trackData->Control, AUDIO_DATA_TRACK) ? "D" : "A",
TEST_FLAG(trackData->Control, TWO_FOUR_CHANNEL_AUDIO) ? "4" : "2",
m, s, f, lba
);
}
Depth -= INDENT;
return;
}
VOID
DumpContext(
IN PVOID X,
IN ULONG_PTR Address,
IN ULONG Detail,
IN LONG Depth
)
{
PREDBOOK_COMPLETION_CONTEXT Context = X;
ULONG i;
xdprintf(Depth, "Context %x for devext %p at %p\n",
Context->Index, Context->DeviceExtension, Address);
Depth += INDENT;
if (Context->ListEntry.Flink != Context->ListEntry.Blink) {
if (Context->Reason > 4) {
xdprintf(Depth, "Context is queued for %s\n",
REDBOOK_CC_STRINGS[ Context->Reason ]);
} else {
xdprintf(Depth, "Context is queued for %s\n",
REDBOOK_CC_STRINGS[ 4 ]);
}
}
xdprintf(Depth, "\\");
for (i=0;i<2000;i++) {
UCHAR array[5] = "|/-\\";
dprintf("\b%c", array[ i%4 ]);
}
dprintf("\b \n");
xdprintf(Depth, "Irp %p Buffer %p Mdl %p\n",
Context->Irp, Context->Buffer, Context->Mdl);
xdprintf(Depth,
"KSSTREAM Header at %p\n",
Address + FIELD_OFFSET(REDBOOK_COMPLETION_CONTEXT, Header)
);
xdprintf(Depth,
"Size = %x\n",
Context->Header.Size
);
xdprintf(Depth,
"TypeSpecificFlags = %x\n",
Context->Header.TypeSpecificFlags
);
xdprintf(Depth,
"Duration = %I64x\n",
Context->Header.Duration
);
xdprintf(Depth,
"FrameExtent = %x\n",
Context->Header.FrameExtent
);
xdprintf(Depth,
"DataUsed = %x\n",
Context->Header.DataUsed
);
xdprintf(Depth,
"Data = %p\n",
Context->Header.Data
);
xdprintf(Depth,
"OptionsFlags = %x\n",
Context->Header.OptionsFlags
);
xdprintf(Depth,
"PresentationTime.Time = %I64x\n",
Context->Header.PresentationTime.Time
);
xdprintf(Depth,
"PresentationTime.Numerator = %x\n",
Context->Header.PresentationTime.Numerator
);
xdprintf(Depth,
"PresentationTime.Denominator = %x\n",
Context->Header.PresentationTime.Denominator
);
return;
}