1257 lines
34 KiB
C
1257 lines
34 KiB
C
/*++
|
|
|
|
Copyright (c) 1992-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
power.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
// podev - dump power relevent data (and other data) about a device object
|
|
// polist [arg] - if no arg, dump data about powerirpseriallist
|
|
// if arg, show entries in serialist that refer to that device object
|
|
// podevnode - dump inverted tree and inclusion %
|
|
// podevnode <any> - dump normal pnp tree, used only for testing with inverted tree
|
|
// postate - dump state statistics
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
VOID
|
|
popDumpDeviceName(
|
|
ULONG64 DeviceAddress
|
|
);
|
|
|
|
__inline
|
|
ULONG64
|
|
GetAddress(
|
|
IN ULONG64 Base,
|
|
IN PCHAR Type,
|
|
IN PCHAR Field)
|
|
{
|
|
ULONG Offset;
|
|
|
|
GetFieldOffset(Type, Field, &Offset);
|
|
return(Base + Offset);
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
ULONG Flags;
|
|
PUCHAR String;
|
|
} DEFBITS, *PDEFBITS;
|
|
|
|
|
|
DEFBITS ActFlags[] = {
|
|
POWER_ACTION_QUERY_ALLOWED, "QueryApps",
|
|
POWER_ACTION_UI_ALLOWED, "UIAllowed",
|
|
POWER_ACTION_OVERRIDE_APPS, "OverrideApps",
|
|
POWER_ACTION_DISABLE_WAKES, "DisableWakes",
|
|
POWER_ACTION_CRITICAL, "Critical",
|
|
0, NULL
|
|
};
|
|
|
|
PUCHAR rgPowerNotifyOrder[PO_ORDER_MAXIMUM+1] = {
|
|
"Non-Paged, PnP, Video",
|
|
"Non-Paged, PnP",
|
|
"Non-Paged, Root-Enum, Video",
|
|
"Non-Paged, Root-Enum",
|
|
"Paged, PnP, Video",
|
|
"Paged, PnP",
|
|
"Paged, Root-Enum, Video",
|
|
"Paged, Root-Enum"
|
|
};
|
|
|
|
|
|
static UCHAR Buffer[50];
|
|
|
|
|
|
|
|
VOID
|
|
poDumpDevice(
|
|
ULONG64 DeviceAddress
|
|
);
|
|
|
|
|
|
DECLARE_API( podev )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the power relevent fields of a device object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object of interest
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 deviceToDump;
|
|
|
|
deviceToDump = GetExpression(args);
|
|
dprintf("Device object is for:\n");
|
|
poDumpDevice(deviceToDump);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
VOID
|
|
poDumpDevice(
|
|
ULONG64 DeviceAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays the driver name for the device object if possible, and
|
|
then displays power relevent fields.
|
|
|
|
Arguments:
|
|
|
|
DeviceAddress - address of device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG result;
|
|
ULONG i;
|
|
PUCHAR buffer;
|
|
UNICODE_STRING unicodeString;
|
|
ULONG64 nextEntry;
|
|
ULONG64 queueAddress;
|
|
ULONG64 irp;
|
|
ULONG64 pObjectHeader;
|
|
ULONG64 pNameInfo;
|
|
ULONG rmr;
|
|
ULONG Type;
|
|
ULONG Flags;
|
|
ULONG64 Temp, DeviceObjectExtension, Dope;
|
|
USHORT Length;
|
|
|
|
|
|
if (GetFieldValue(DeviceAddress,
|
|
"nt!_DEVICE_OBJECT",
|
|
"Type",
|
|
Type)) {
|
|
dprintf("%08p: Could not read device object\n", DeviceAddress);
|
|
return;
|
|
}
|
|
|
|
if (Type != IO_TYPE_DEVICE) {
|
|
dprintf("%08p: is not a device object\n", DeviceAddress);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Dump the device name if present.
|
|
//
|
|
|
|
pObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(DeviceAddress);
|
|
if (GetFieldValue(pObjectHeader,
|
|
"nt!_OBJECT_HEADER",
|
|
"Type",
|
|
Temp)) {
|
|
USHORT Length;
|
|
ULONG64 pName;
|
|
|
|
KD_OBJECT_HEADER_TO_NAME_INFO( pObjectHeader, &pNameInfo );
|
|
if (GetFieldValue(pNameInfo,
|
|
"nt!_OBJECT_HEADER_NAME_INFO",
|
|
"Name.Length",
|
|
Length)) {
|
|
buffer = LocalAlloc(LPTR, Length);
|
|
if (buffer != NULL) {
|
|
unicodeString.MaximumLength = Length;
|
|
unicodeString.Length = Length;
|
|
unicodeString.Buffer = (PWSTR)buffer;
|
|
GetFieldValue(pNameInfo,
|
|
"nt!_OBJECT_HEADER_NAME_INFO",
|
|
"Name.Buffer",
|
|
pName);
|
|
if (ReadMemory(pName,
|
|
buffer,
|
|
unicodeString.Length,
|
|
&result) && (result == unicodeString.Length)) {
|
|
dprintf(" %wZ", &unicodeString);
|
|
}
|
|
LocalFree(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Dump Irps related to driver.
|
|
//
|
|
|
|
InitTypeRead(DeviceAddress, nt!_DEVICE_OBJECT);
|
|
dprintf(" DriverObject %08lx\n", ReadField(DriverObject));
|
|
dprintf("Current Irp %08lx RefCount %d Type %08lx ",
|
|
ReadField(CurrentIrp),
|
|
ReadField(ReferenceCount),
|
|
ReadField(DeviceType));
|
|
if (ReadField(AttachedDevice)) {
|
|
dprintf("AttachedDev %08p ", ReadField(AttachedDevice));
|
|
}
|
|
if (ReadField(Vpb)) {
|
|
dprintf("Vpb %08p ", ReadField(Vpb));
|
|
}
|
|
|
|
dprintf("DevFlags %08lx", (Flags = (ULONG) ReadField(Flags)));
|
|
if (Flags & DO_POWER_PAGABLE) dprintf(" DO_POWER_PAGABLE");
|
|
if (Flags & DO_POWER_INRUSH) dprintf(" DO_POWER_INRUSH");
|
|
if (Flags & DO_POWER_NOOP) dprintf(" DO_POWER_NOOP");
|
|
dprintf("\n");
|
|
DeviceObjectExtension = ReadField(DeviceObjectExtension);
|
|
|
|
if (ReadField(DeviceQueue.Busy)) {
|
|
ULONG Off;
|
|
|
|
GetFieldOffset("nt!_DEVICE_OBJECT", "DeviceQueue.DeviceListHead", &Off);
|
|
nextEntry = ReadField(DeviceQueue.DeviceListHead.Flink);
|
|
|
|
if (nextEntry == DeviceAddress + Off) {
|
|
dprintf("Device queue is busy -- Queue empty\n");
|
|
} else {
|
|
ULONG Qoffset, IrpOffset;
|
|
|
|
dprintf("DeviceQueue: ");
|
|
i = 0;
|
|
|
|
GetFieldOffset("nt!_DEVICE_OBJECT", "DeviceListEntry", &Qoffset);
|
|
GetFieldOffset("nt!_IRP", "Tail.Overlay.DeviceQueueEntry", &IrpOffset);
|
|
while ( nextEntry != ( DeviceAddress + Off )) {
|
|
queueAddress = (nextEntry - Qoffset);
|
|
if (GetFieldValue(queueAddress,
|
|
"nt!_KDEVICE_QUEUE_ENTRY",
|
|
"DeviceListEntry.Flink",
|
|
nextEntry)) {
|
|
dprintf("%08p: Could not read queue entry\n", DeviceAddress);
|
|
return;
|
|
}
|
|
|
|
// nextEntry = queueEntry.DeviceListEntry.Flink;
|
|
|
|
irp = (queueAddress - IrpOffset);
|
|
|
|
dprintf("%08p%s",
|
|
irp,
|
|
(i & 0x03) == 0x03 ? "\n\t " : " ");
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
} else {
|
|
dprintf("Device queue is not busy.\n");
|
|
}
|
|
|
|
dprintf("Device Object Extension: %08p:\n", DeviceObjectExtension);
|
|
if (GetFieldValue(DeviceObjectExtension,
|
|
"nt!_DEVOBJ_EXTENSION",
|
|
"PowerFlags",
|
|
Flags)) {
|
|
dprintf("Could not read Device Object Extension %p\n", DeviceObjectExtension);
|
|
return;
|
|
}
|
|
dprintf("PowerFlags: %08lx =>", Flags);
|
|
|
|
#define PopGetDoSystemPowerState(Flags) \
|
|
(Flags & POPF_SYSTEM_STATE)
|
|
|
|
#define PopGetDoDevicePowerState(Flags) \
|
|
((Flags & POPF_DEVICE_STATE) >> 4)
|
|
|
|
|
|
dprintf("SystemState=%1x", PopGetDoSystemPowerState(Flags) );
|
|
dprintf(" DeviceState=%lx", PopGetDoDevicePowerState(Flags) );
|
|
if (Flags & POPF_SYSTEM_ACTIVE) dprintf(" syact");
|
|
if (Flags & POPF_SYSTEM_PENDING) dprintf(" sypnd");
|
|
if (Flags & POPF_DEVICE_ACTIVE) dprintf(" dvact");
|
|
if (Flags & POPF_DEVICE_PENDING) dprintf(" dvpnd");
|
|
|
|
GetFieldValue(DeviceObjectExtension,"nt!_DEVOBJ_EXTENSION","Dope",Dope);
|
|
dprintf("\nDope: %08lx:\n", Dope);
|
|
if (Dope != 0) {
|
|
rmr = GetFieldValue(Dope, "nt!_DEVICE_OBJECT_POWER_EXTENSION",
|
|
"DeviceType", Type);
|
|
if (!rmr) {
|
|
InitTypeRead(Dope, nt!_DEVICE_OBJECT_POWER_EXTENSION);
|
|
|
|
dprintf("IdleCount: %08p ConIdlTime: %08p PerfIdlTime: %08p\n",
|
|
ReadField(IdleCount), ReadField(ConservationIdleTime), ReadField(PerformanceIdleTime));
|
|
dprintf("NotifySourceList fl:%08p bl:%08p\n",
|
|
ReadField(NotifySourceList.Flink), ReadField(NotifySourceList.Blink));
|
|
dprintf("NotifyTargetList fl:%08p bl:%08p\n",
|
|
ReadField(NotifyTargetList.Flink), ReadField(NotifyTargetList.Blink));
|
|
dprintf("PowerChannelSummary TotalCount: %08p D0Count: %08p\n",
|
|
ReadField(PowerChannelSummary.TotalCount), ReadField(PowerChannelSummary.D0Count));
|
|
|
|
dprintf("PowerChannelSummary NotifyList fl:%08p bl:%08p\n",
|
|
ReadField(PowerChannelSummary.NotifyList.Flink),
|
|
ReadField(PowerChannelSummary.NotifyList.Blink)
|
|
);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
poDumpList(
|
|
ULONG64 DeviceAddress
|
|
);
|
|
|
|
|
|
DECLARE_API( polist )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the irp serial list, unless a devobj address is given,
|
|
in which case dump the irps in the serial list that point to
|
|
that device object
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object of interest
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 deviceToDump;
|
|
|
|
deviceToDump = 0;
|
|
deviceToDump = GetExpression(args);
|
|
if (deviceToDump == 0) {
|
|
dprintf("All entries in Power Irp Serial List\n");
|
|
} else {
|
|
dprintf("Entries in Power Irp Serial List for: %08p:\n", deviceToDump);
|
|
}
|
|
if (!IsPtr64()) {
|
|
deviceToDump = (ULONG64) (LONG64) (LONG) deviceToDump;
|
|
}
|
|
poDumpList(deviceToDump);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
VOID
|
|
poDumpList(
|
|
ULONG64 DeviceAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceAddress - address of device object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 listhead, irpa, iosla, p;
|
|
ULONG isll, result;
|
|
ULONG IrpOffset;
|
|
|
|
isll = GetUlongValue("nt!PopIrpSerialListLength");
|
|
dprintf("PopIrpSerialListLength = %d\n", isll);
|
|
|
|
listhead = GetExpression("nt!PopIrpSerialList");
|
|
GetFieldOffset("nt!_IRP", "Tail.Overlay.DeviceQueueEntry", &IrpOffset);
|
|
|
|
for (p = GetPointerFromAddress( listhead );
|
|
p != listhead;
|
|
p = GetPointerFromAddress( p))
|
|
{
|
|
ULONG64 DeviceObject, CurrentStackLocation;
|
|
irpa = p - IrpOffset;
|
|
|
|
if (GetFieldValue(irpa, "nt!_IRP", "Tail.Overlay.CurrentStackLocation", CurrentStackLocation))
|
|
{
|
|
dprintf("Cannot read Irp: %08p\n", irpa);
|
|
return;
|
|
}
|
|
|
|
iosla = CurrentStackLocation + DBG_PTR_SIZE;
|
|
|
|
if (GetFieldValue(iosla, "nt!_IO_STACK_LOCATION", "DeviceObject", DeviceObject) )
|
|
{
|
|
dprintf("Cannot read Io Stk Loc: %08p\n", iosla);
|
|
return;
|
|
}
|
|
|
|
InitTypeRead(iosla, nt!_IO_STACK_LOCATION);
|
|
if ((DeviceAddress == 0) || (DeviceAddress == DeviceObject)) {
|
|
dprintf("Irp:%08p DevObj:%08p ", irpa, DeviceObject);
|
|
dprintf("Ctx:%08p ", ReadField(Parameters.Power.SystemContext));
|
|
if (ReadField(Parameters.Power.SystemContext) & POP_INRUSH_CONTEXT) {
|
|
dprintf("inrush ");
|
|
} else {
|
|
dprintf(" ");
|
|
}
|
|
|
|
if (ReadField(Parameters.Power.Type) == SystemPowerState) {
|
|
dprintf("sysirp ");
|
|
dprintf("S%d\n", (LONG)(ReadField(Parameters.Power.State.SystemState)) - (LONG)PowerSystemWorking);
|
|
} else {
|
|
dprintf("devirp ");
|
|
dprintf("D%d\n", (LONG)(ReadField(Parameters.Power.State.DeviceState)) - (LONG)PowerDeviceD0);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
poDumpRequestedList(
|
|
ULONG64 DeviceAddress
|
|
);
|
|
|
|
|
|
DECLARE_API( poreqlist )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the irp serial list, unless a devobj address is given,
|
|
in which case dump the irps in the serial list that point to
|
|
that device object
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object of interest
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 deviceToDump;
|
|
|
|
deviceToDump = GetExpression(args);
|
|
if (deviceToDump == 0) {
|
|
dprintf("All active Power Irps from PoRequestPowerIrp\n");
|
|
} else {
|
|
dprintf("Active Power Irps from PoRequestPowerIrp for: %08p:\n",
|
|
deviceToDump);
|
|
}
|
|
poDumpRequestedList(deviceToDump);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
VOID
|
|
poDumpRequestedList (
|
|
ULONG64 DeviceAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump PopRequestedIrps List, "A list of all the power irps created from
|
|
PoReqestPowerIrp.
|
|
|
|
Arguments:
|
|
|
|
DeviceAddress - optional address to which requested power IRPs were sent
|
|
|
|
--*/
|
|
{
|
|
BOOL blocked = FALSE;
|
|
ULONG64 listhead;
|
|
ULONG64 p, spAddr, irpAddr;
|
|
ULONG result;
|
|
ULONG Off;
|
|
|
|
dprintf("PopReqestedPowerIrpList\n");
|
|
|
|
listhead = GetExpression("nt!PopRequestedIrps");
|
|
|
|
GetFieldOffset("nt!_IO_STACK_LOCATION", "Parameters.Others.Argument1", &Off);
|
|
dprintf("FieldOffset = %p\n",Off);
|
|
for (p = GetPointerFromAddress( listhead );
|
|
p != listhead;
|
|
p = GetPointerFromAddress( p ))
|
|
{
|
|
ULONG64 CurrentStackLocation;
|
|
ULONG MajorFunction;
|
|
|
|
//
|
|
// Reguested list is a double list of stack locations
|
|
//
|
|
spAddr = p - Off;
|
|
if (GetFieldValue(spAddr, "nt!_IO_STACK_LOCATION",
|
|
"Parameters.Others.Argument3", irpAddr)) {
|
|
|
|
dprintf("Cannot read 1st stack Location: %08p\n", spAddr);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// The 3rd argument of which has the pointer to the irp itself
|
|
//
|
|
if (GetFieldValue(irpAddr, "nt!_IRP", "Tail.Overlay.CurrentStackLocation", CurrentStackLocation))
|
|
{
|
|
dprintf("Cannot read Irp: %08p\n", irpAddr);
|
|
return;
|
|
}
|
|
dprintf ("Irp %08p ", irpAddr);
|
|
|
|
//
|
|
// Assume the if the IRP is in this list that it has a valid
|
|
// current stack location
|
|
//
|
|
spAddr = CurrentStackLocation;
|
|
|
|
if (GetFieldValue(spAddr, "nt!_IO_STACK_LOCATION", "MajorFunction", MajorFunction) )
|
|
{
|
|
dprintf("Cannot read current stack location: %08p\n", spAddr);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check to see if the irp is blocked
|
|
//
|
|
blocked = FALSE;
|
|
if (MajorFunction != IRP_MJ_POWER) {
|
|
|
|
//
|
|
// Irp is blocked. The next stack location is the real one
|
|
//
|
|
blocked = TRUE;
|
|
spAddr = CurrentStackLocation + DBG_PTR_SIZE;
|
|
if (GetFieldValue(spAddr, "nt!_IO_STACK_LOCATION", "MajorFunction", MajorFunction) )
|
|
{
|
|
dprintf("Cannot read current stack location: %08p\n", spAddr);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
if ((DeviceAddress == 0) || (DeviceAddress == ReadField(DeviceObject))) {
|
|
|
|
ULONG MinorFunction = 0;
|
|
ULONG64 DeviceObject = 0;
|
|
ULONG64 SystemContext = 0;
|
|
ULONG64 Temp = 0;
|
|
UCHAR IOStack[] = "nt!_IO_STACK_LOCATION";
|
|
|
|
GetFieldValue(spAddr,IOStack, "DeviceObject", DeviceObject);
|
|
GetFieldValue(spAddr,IOStack, "Parameters.Power.SystemContext", SystemContext);
|
|
GetFieldValue(spAddr,IOStack, "MinorFunction", MinorFunction);
|
|
|
|
dprintf("DevObj %08p", DeviceObject);
|
|
DumpDevice(DeviceObject,0, FALSE);
|
|
dprintf(" Ctx %08p ", SystemContext);
|
|
if ((SystemContext & POP_INRUSH_CONTEXT) == POP_INRUSH_CONTEXT) {
|
|
|
|
dprintf("* ");
|
|
} else {
|
|
dprintf(" ");
|
|
}
|
|
|
|
switch (MinorFunction) {
|
|
case IRP_MN_QUERY_POWER:
|
|
dprintf ("Query Power ");
|
|
goto PoDumpRequestedListPowerPrint;
|
|
case IRP_MN_SET_POWER:
|
|
dprintf ("Set Power ");
|
|
PoDumpRequestedListPowerPrint:
|
|
GetFieldValue(spAddr, IOStack, "Parameters.Power.Type",Temp);
|
|
if ((ULONG) Temp == SystemPowerState) {
|
|
GetFieldValue(spAddr, IOStack, "Parameters.Power.State.SystemState", Temp);
|
|
dprintf("S%d ", (LONG)Temp - (LONG)PowerSystemWorking);
|
|
} else {
|
|
GetFieldValue(spAddr, IOStack, "Parameters.Power.State.DeviceState", Temp);
|
|
dprintf("D%d ", (LONG)Temp - (LONG)PowerDeviceD0);
|
|
}
|
|
GetFieldValue(spAddr,IOStack,"Parameters.Power.ShutdownType", Temp);
|
|
dprintf ("ShutdownType %x", (LONG) Temp);
|
|
break;
|
|
|
|
case IRP_MN_WAIT_WAKE:
|
|
GetFieldValue(spAddr, IOStack, "Parameters.WaitWake.PowerState", Temp);
|
|
dprintf ("Wait Wake S%d", (LONG)Temp - (LONG)PowerSystemWorking);
|
|
break;
|
|
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
dprintf ("Power Sequence Irp");
|
|
break;
|
|
}
|
|
if (blocked) {
|
|
|
|
dprintf(" [blocked]");
|
|
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID poDumpNodePower();
|
|
|
|
DECLARE_API( ponode )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If an argument is present, dump the devnode list in pnp order.
|
|
(used only for testing)
|
|
|
|
Otherwise dump the devnode inverted stack.
|
|
(po enumeration order)
|
|
|
|
Arguments:
|
|
|
|
args - flag
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG flag;
|
|
|
|
dprintf("Dump Inverted DevNode Tree (power order)\n");
|
|
poDumpNodePower();
|
|
return S_OK;
|
|
}
|
|
|
|
VOID
|
|
poDumpNodePower(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the devnode tree in power order.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
#if 0
|
|
LONG level, SizeOfLE, LevelOff, pdo_off;
|
|
ULONG64 parray, listhead, effaddr, pdo, devNodeAddr, limit;
|
|
|
|
level = GetUlongValue("nt!IopMaxDeviceNodeLevel");
|
|
parray = GetExpression("nt!IopDeviceNodeStack");
|
|
|
|
dprintf("Max level = %5d\n", level);
|
|
dprintf("IopDeviceNodeStack %08p\n", parray);
|
|
parray = GetPointerFromAddress(parray);
|
|
dprintf("*IopDeviceNodeStack %08p\n", parray);
|
|
|
|
dprintf("Level ListHead DevNode PDO\n");
|
|
dprintf("----- -------- -------- --------\n");
|
|
|
|
SizeOfLE = GetTypeSize("nt!_LIST_ENTRY");
|
|
GetFieldOffset("nt!_DEVICE_NODE", "LevelList", &LevelOff);
|
|
GetFieldOffset("nt!_DEVICE_NODE", "PhysicalDeviceObject", &pdo_off);
|
|
for ( ; level >= 0; level--) {
|
|
|
|
effaddr = (level * SizeOfLE) + parray;
|
|
listhead = GetPointerFromAddress( effaddr);
|
|
|
|
dprintf("%5d %08lx\n", level, listhead);
|
|
|
|
if (listhead) {
|
|
|
|
limit = 0;
|
|
for (effaddr = GetPointerFromAddress(listhead);
|
|
effaddr != listhead;
|
|
effaddr = GetPointerFromAddress(effaddr))
|
|
{
|
|
devNodeAddr = (effaddr - LevelOff);
|
|
|
|
pdo = GetPointerFromAddress((devNodeAddr+pdo_off));
|
|
|
|
dprintf(" %08p %08p ", devNodeAddr, pdo);
|
|
popDumpDeviceName(pdo);
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
popDumpDeviceName(
|
|
ULONG64 DeviceAddress
|
|
)
|
|
{
|
|
ULONG result;
|
|
|
|
|
|
PUCHAR buffer;
|
|
UNICODE_STRING unicodeString;
|
|
ULONG64 pObjectHeader;
|
|
ULONG64 pNameInfo;
|
|
ULONG Type;
|
|
ULONG Flags;
|
|
ULONG64 Temp;
|
|
USHORT Length;
|
|
|
|
|
|
if (GetFieldValue(DeviceAddress, "nt!_DEVICE_OBJECT", "Type", Type)) {
|
|
dprintf("%08p: Could not read device object\n", DeviceAddress);
|
|
return;
|
|
}
|
|
|
|
if (Type != IO_TYPE_DEVICE) {
|
|
dprintf("%08p: is not a device object\n", DeviceAddress);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Dump the device name if present.
|
|
//
|
|
|
|
pObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(DeviceAddress);
|
|
if (GetFieldValue(pObjectHeader, "nt!_OBJECT_HEADER", "Type", Temp)) {
|
|
ULONG64 pName;
|
|
|
|
KD_OBJECT_HEADER_TO_NAME_INFO( pObjectHeader, &pNameInfo );
|
|
if (GetFieldValue(pNameInfo, "nt!_OBJECT_HEADER_NAME_INFO",
|
|
"Name.Length",
|
|
Length)) {
|
|
buffer = LocalAlloc(LPTR, Length);
|
|
if (buffer != NULL) {
|
|
unicodeString.MaximumLength = Length;
|
|
unicodeString.Length = Length;
|
|
unicodeString.Buffer = (PWSTR)buffer;
|
|
GetFieldValue(pNameInfo,
|
|
"nt!_OBJECT_HEADER_NAME_INFO",
|
|
"Name.Buffer",
|
|
pName);
|
|
if (ReadMemory(pName,
|
|
buffer,
|
|
unicodeString.Length,
|
|
&result) && (result == unicodeString.Length)) {
|
|
dprintf(" %wZ", &unicodeString);
|
|
}
|
|
LocalFree(buffer);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
PUCHAR
|
|
PowerAction(
|
|
IN POWER_ACTION Action
|
|
)
|
|
{
|
|
switch (Action) {
|
|
case PowerActionNone: return "None";
|
|
case PowerActionReserved: return "Reserved";
|
|
case PowerActionSleep: return "Sleep";
|
|
case PowerActionHibernate: return "Hibernate";
|
|
case PowerActionShutdown: return "Shutdown";
|
|
case PowerActionShutdownReset: return "ShutdownReset";
|
|
case PowerActionShutdownOff: return "ShutdownOff";
|
|
case PowerActionWarmEject: return "WarmEject";
|
|
}
|
|
|
|
return "???";
|
|
}
|
|
|
|
PUCHAR
|
|
SystemState(
|
|
SYSTEM_POWER_STATE State
|
|
)
|
|
{
|
|
switch (State) {
|
|
case PowerSystemUnspecified: return "Unspecified";
|
|
case PowerSystemWorking: return "Working";
|
|
case PowerSystemSleeping1: return "Sleeping1";
|
|
case PowerSystemSleeping2: return "Sleeping2";
|
|
case PowerSystemSleeping3: return "Sleeping3";
|
|
case PowerSystemHibernate: return "Hibernate";
|
|
case PowerSystemShutdown: return "Shutdown";
|
|
}
|
|
|
|
sprintf (Buffer, "State=%x", State);
|
|
return Buffer;
|
|
}
|
|
|
|
PUCHAR
|
|
PoIrpMinor (
|
|
UCHAR IrpMinor
|
|
)
|
|
{
|
|
switch (IrpMinor) {
|
|
case IRP_MN_QUERY_POWER: return "QueryPower";
|
|
case IRP_MN_SET_POWER: return "SetPower";
|
|
}
|
|
|
|
return "??";
|
|
}
|
|
|
|
|
|
|
|
PUCHAR
|
|
TF (
|
|
BOOLEAN Flag
|
|
)
|
|
{
|
|
switch (Flag) {
|
|
case TRUE: return "TRUE";
|
|
case FALSE: return "FALSE";
|
|
}
|
|
|
|
sprintf (Buffer, "%x", Flag);
|
|
return Buffer;
|
|
}
|
|
|
|
|
|
|
|
|
|
PWCHAR
|
|
DumpDoName (
|
|
IN ULONG64 Str
|
|
)
|
|
{
|
|
static WCHAR Name[50];
|
|
|
|
memset (Name, 0, sizeof(Name));
|
|
ReadMemory (Str, Name, sizeof(Name), NULL);
|
|
Name[sizeof(Name)-1] = 0;
|
|
return Name;
|
|
}
|
|
|
|
PUCHAR
|
|
DumpQueueHead (
|
|
IN ULONG64 StrucAddr,
|
|
IN ULONG64 Struc,
|
|
IN ULONG Offset
|
|
)
|
|
{
|
|
ULONG64 Head, Flink, Blink;
|
|
ULONG64 Va;
|
|
|
|
Head = Struc + Offset;
|
|
Va = StrucAddr + Offset;
|
|
|
|
GetFieldValue(Head, "nt!_LIST_ENTRY", "Flink", Flink);
|
|
GetFieldValue(Head, "nt!_LIST_ENTRY", "Blink", Blink);
|
|
if (Flink == Va && Blink == Va) {
|
|
sprintf (Buffer, "Head:%08p Empty", Va);
|
|
} else {
|
|
sprintf (Buffer, "Head:%08p F:%08p B:%08p", Va, Flink, Blink);
|
|
}
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpDevicePowerIrp (
|
|
IN PUCHAR Desc,
|
|
IN ULONG64 StrucAddr,
|
|
IN ULONG64 Head,
|
|
IN ULONG Offset
|
|
)
|
|
{
|
|
ULONG64 Va;
|
|
ULONG64 Link;
|
|
ULONG64 Addr;
|
|
ULONG Off;
|
|
|
|
GetFieldOffset("nt!_POP_DEVICE_SYS_STATE", "Head", &Off);
|
|
Va = (StrucAddr + Off + Offset);
|
|
Link = GetPointerFromAddress(Head + Offset);
|
|
|
|
if (Link == Va) {
|
|
return ;
|
|
}
|
|
|
|
dprintf ("\n%s:\n", Desc);
|
|
|
|
while (Link != Va) {
|
|
ULONG64 Irp, Notify;
|
|
|
|
Addr = Link - Offset;
|
|
if (GetFieldValue(Addr, "nt!_POP_DEVICE_POWER_IRP", "Irp", Irp)) {
|
|
dprintf ("Could not power irp\n");
|
|
break;
|
|
}
|
|
GetFieldValue(Addr, "nt!_POP_DEVICE_SYS_STATE", "Notify", Notify);
|
|
dprintf (" Irp: %08p Notify %08p\n", Irp, Notify);
|
|
|
|
Link = GetPointerFromAddress(Addr + Offset);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
poDumpOldNotifyList(
|
|
VOID
|
|
)
|
|
{
|
|
BOOLEAN GdiOff;
|
|
UCHAR LastOrder;
|
|
ULONG PartOffset, NoLists, SizeOfLE, Off, HeadOff;
|
|
ULONG64 DevState, Notify;
|
|
LONG i;
|
|
ULONG64 ListHead;
|
|
ULONG64 Link;
|
|
|
|
dprintf(" NoLists........: %p\n", (NoLists = (ULONG) ReadField(Order.NoLists)));
|
|
SizeOfLE = GetTypeSize("nt!_LIST_ENTRY");
|
|
GdiOff = FALSE;
|
|
LastOrder = 0xff;
|
|
Notify = ReadField(Order.Notify);
|
|
for (i=NoLists-1; i >= 0; i--) {
|
|
ListHead = Notify + i*SizeOfLE;
|
|
if (GetFieldValue(ListHead, "nt!_LIST_ENTRY", "Flink", Link)) {
|
|
dprintf ("Could not read list head\n");
|
|
break;
|
|
}
|
|
|
|
while (Link != ListHead) {
|
|
UCHAR OrderLevel;
|
|
|
|
if (GetFieldValue(Link, "nt!_PO_DEVICE_NOTIFY", "OrderLevel", OrderLevel)) {
|
|
dprintf ("Could not read link\n");
|
|
break;
|
|
}
|
|
|
|
if (LastOrder != OrderLevel) {
|
|
LastOrder = OrderLevel;
|
|
dprintf (" %x %s",
|
|
LastOrder,
|
|
LastOrder <= PO_ORDER_MAXIMUM ? rgPowerNotifyOrder[LastOrder] : ""
|
|
);
|
|
|
|
if (!GdiOff && OrderLevel <= PO_ORDER_GDI_NOTIFICATION) {
|
|
GdiOff = TRUE;
|
|
dprintf (", GdiOff\n");
|
|
} else {
|
|
dprintf ("\n");
|
|
}
|
|
}
|
|
|
|
InitTypeRead(Link, nt!_PO_DEVICE_NOTIFY);
|
|
dprintf (" %02x %x:%x %08x %c",
|
|
i,
|
|
OrderLevel,
|
|
(ULONG) ReadField(NodeLevel),
|
|
Link,
|
|
((UCHAR) ReadField(WakeNeeded) ? 'w' : ' ')
|
|
);
|
|
|
|
dprintf (" %ws\t", DumpDoName (ReadField(DriverName)));
|
|
dprintf (" %ws\n", DumpDoName (ReadField(DeviceName)));
|
|
|
|
Link = ReadField(Link.Flink);
|
|
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
DumpNotifyCallback(
|
|
PFIELD_INFO pAddrInfo,
|
|
PVOID Context
|
|
)
|
|
{
|
|
if (CheckControlC()) {return 0;}
|
|
|
|
InitTypeRead(pAddrInfo->address, nt!_PO_DEVICE_NOTIFY);
|
|
dprintf(" %c %08p: %08p %ws\t",
|
|
ReadField(WakeNeeded) ? 'w' : ' ',
|
|
pAddrInfo->address,
|
|
ReadField(Node),
|
|
DumpDoName(ReadField(DriverName)));
|
|
dprintf("%ws\n",DumpDoName(ReadField(DeviceName)));
|
|
|
|
return(0);
|
|
}
|
|
|
|
VOID
|
|
poDumpNewNotifyList(
|
|
IN ULONG64 DevState
|
|
)
|
|
{
|
|
BOOLEAN GdiOff;
|
|
UCHAR LastOrder;
|
|
ULONG PartOffset, NoLists, SizeOfLE, Off, HeadOff;
|
|
ULONG64 Level, Notify;
|
|
LONG i,j;
|
|
ULONG64 ListHead;
|
|
ULONG64 Link;
|
|
ULONG LevelOffset;
|
|
ULONG SizeOfLevel;
|
|
CHAR FlinkBuff[32];
|
|
PCHAR NotifyList[] = {"WaitSleep",
|
|
"ReadySleep",
|
|
"Pending",
|
|
"Complete",
|
|
"ReadyS0",
|
|
"WaitS0"};
|
|
|
|
SizeOfLevel = GetTypeSize("nt!_PO_NOTIFY_ORDER_LEVEL");
|
|
GdiOff = FALSE;
|
|
if (GetFieldOffset("nt!_POP_DEVICE_SYS_STATE",
|
|
"Order.OrderLevel",
|
|
&LevelOffset)) {
|
|
dprintf("Couldn't get field offset for Order.OrderLevel.");
|
|
return;
|
|
}
|
|
for (i=PO_ORDER_MAXIMUM;i>=0;i--) {
|
|
if (CheckControlC()) {return;}
|
|
Level = DevState + LevelOffset + i*SizeOfLevel;
|
|
InitTypeRead(Level, nt!_PO_NOTIFY_ORDER_LEVEL);
|
|
if (ReadField(DeviceCount)) {
|
|
dprintf("Level %d (%08p) %d/%d\t%s\n",
|
|
i,
|
|
Level,
|
|
(ULONG)ReadField(ActiveCount),
|
|
(ULONG)ReadField(DeviceCount),
|
|
rgPowerNotifyOrder[i]);
|
|
|
|
for (j=0;j<sizeof(NotifyList)/sizeof(PCHAR);j++) {
|
|
if (CheckControlC()) {return;}
|
|
sprintf(FlinkBuff, "%s.Flink",NotifyList[j]);
|
|
if (GetFieldValue(Level,
|
|
"nt!_PO_NOTIFY_ORDER_LEVEL",
|
|
FlinkBuff,
|
|
Link)) {
|
|
dprintf("couldn't get field value for PO_NOTIFY_ORDER_LEVEL.%s\n",FlinkBuff);
|
|
return;
|
|
}
|
|
if (Link != GetAddress(Level, "nt!_PO_NOTIFY_ORDER_LEVEL", FlinkBuff)) {
|
|
dprintf(" %s:\n",NotifyList[j]);
|
|
ListType("_PO_DEVICE_NOTIFY",
|
|
Link,
|
|
1,
|
|
"Link.Flink",
|
|
NULL,
|
|
DumpNotifyCallback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PoDevState (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the current power action structure
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object of interest
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 addr;
|
|
LONG i;
|
|
ULONG64 ListHead;
|
|
ULONG64 Link;
|
|
ULONG64 DevState, Notify;
|
|
BOOLEAN GdiOff;
|
|
UCHAR IrpMinor;
|
|
ULONG PartOffset, NoLists, SizeOfLE, Off, HeadOff;
|
|
|
|
addr = GetExpression( "nt!PopAction" );
|
|
if (!addr) {
|
|
dprintf("Error retrieving address of PopAction\n");
|
|
return;
|
|
}
|
|
|
|
if (GetFieldValue(addr, "nt!POP_POWER_ACTION", "DevState", DevState)) {
|
|
dprintf("Error reading PopAction\n");
|
|
return;
|
|
}
|
|
|
|
if (!DevState) {
|
|
dprintf("No Device State allocated on PopAction\n");
|
|
return;
|
|
}
|
|
|
|
if (GetFieldValue(DevState, "nt!_POP_DEVICE_SYS_STATE", "IrpMinor", IrpMinor)) {
|
|
dprintf("Error reading device state structure\n");
|
|
return;
|
|
}
|
|
|
|
GetFieldOffset("nt!_POP_DEVICE_SYS_STATE","PresentIrpQueue", &Off);
|
|
InitTypeRead(DevState, nt!_POP_DEVICE_SYS_STATE);
|
|
dprintf ("PopAction.DevState %08x\n", DevState);
|
|
dprintf(" Irp minor......: %s\n", PoIrpMinor (IrpMinor));
|
|
dprintf(" System State...: %s\n", SystemState((ULONG) ReadField(SystemState)));
|
|
dprintf(" Worker thread..: %08p\n", ReadField(Thread));
|
|
dprintf(" Status.........: %x\n", (ULONG) ReadField(Status));
|
|
dprintf(" Waking.........: %s\n", TF (((UCHAR) ReadField(Waking))) );
|
|
dprintf(" Cancelled......: %s\n", TF (((UCHAR) ReadField(Cancelled))) );
|
|
dprintf(" Ignore errors..: %s\n", TF (((UCHAR) ReadField(IgnoreErrors))) );
|
|
dprintf(" Ignore not imp.: %s\n", TF (((UCHAR) ReadField(IgnoreNotImplemented))) );
|
|
dprintf(" Wait any.......: %s\n", TF (((UCHAR) ReadField(WaitAny))) );
|
|
dprintf(" Wait all.......: %s\n", TF (((UCHAR) ReadField(WaitAll))) );
|
|
dprintf(" Present Irp Q..: %s\n",
|
|
DumpQueueHead (DevState, DevState, Off)
|
|
);
|
|
|
|
dprintf("\n");
|
|
dprintf("Order:\n");
|
|
dprintf(" DevNode Seq....: %x\n", (ULONG) ReadField(Order.DevNodeSequence));
|
|
if (ReadField(Order.NoLists)) {
|
|
poDumpOldNotifyList();
|
|
} else {
|
|
poDumpNewNotifyList(DevState);
|
|
}
|
|
|
|
//
|
|
// Dump device notification list order
|
|
//
|
|
|
|
|
|
//
|
|
// Dump device power irps
|
|
//
|
|
|
|
|
|
GetFieldOffset("nt!_POP_DEVICE_SYS_STATE","Head", &HeadOff);
|
|
GetFieldOffset("nt!_POP_DEVICE_POWER_IRP", "Pending", &Off);
|
|
DumpDevicePowerIrp ("Pending irps", DevState, DevState+HeadOff, Off);
|
|
GetFieldOffset("nt!_POP_DEVICE_POWER_IRP", "Complete", &Off);
|
|
DumpDevicePowerIrp ("Completed irps", DevState, DevState+HeadOff, Off);
|
|
GetFieldOffset("nt!_POP_DEVICE_POWER_IRP", "Abort", &Off);
|
|
DumpDevicePowerIrp ("Abort irps", DevState, DevState+HeadOff, Off);
|
|
GetFieldOffset("nt!_POP_DEVICE_POWER_IRP", "Failed", &Off);
|
|
DumpDevicePowerIrp ("Failed irps", DevState, DevState+HeadOff, Off);
|
|
dprintf("\n");
|
|
}
|
|
|
|
|
|
DECLARE_API( poaction )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the current power action structure
|
|
|
|
Arguments:
|
|
|
|
args - the location of the device object of interest
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 addr;
|
|
ULONG i;
|
|
UCHAR c, State, Updates;
|
|
ULONG Flags;
|
|
|
|
addr = GetExpression( "nt!PopAction" );
|
|
if (!addr) {
|
|
dprintf("Error retrieving address of PopAction\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(addr, "nt!POP_POWER_ACTION", "State", State)) {
|
|
dprintf("Error reading PopAction\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
InitTypeRead(addr, nt!POP_POWER_ACTION);
|
|
dprintf("PopAction: %08x\n", addr);
|
|
|
|
dprintf(" State..........: %x ", State);
|
|
switch (State) {
|
|
case PO_ACT_IDLE: dprintf ("- Idle\n"); break;
|
|
case PO_ACT_NEW_REQUEST: dprintf ("- New request\n"); break;
|
|
case PO_ACT_CALLOUT: dprintf ("- Winlogon callout\n"); break;
|
|
case PO_ACT_SET_SYSTEM_STATE: dprintf ("- Set System State\n"); break;
|
|
default: dprintf ("\n"); break;
|
|
}
|
|
|
|
dprintf(" Updates........: %x ", (Updates = (UCHAR) ReadField(Updates)));
|
|
if (Updates & PO_PM_USER) dprintf(" user ");
|
|
if (Updates & PO_PM_REISSUE) dprintf(" reissue ");
|
|
if (Updates & PO_PM_SETSTATE) dprintf(" setstate ");
|
|
if (ReadField(Shutdown)) dprintf(" SHUTDOWN-set ");
|
|
dprintf("\n");
|
|
|
|
dprintf(" Action.........: %s\n", PowerAction((ULONG) ReadField(Action)));
|
|
dprintf(" Lightest State.: %s\n", SystemState((ULONG) ReadField(LightestState)));
|
|
dprintf(" Flags..........: %x", (Flags = (ULONG) ReadField(Flags)));
|
|
|
|
c = ' ';
|
|
for (i=0; ActFlags[i].Flags; i++) {
|
|
if (Flags & ActFlags[i].Flags) {
|
|
dprintf ("%c%s", c, ActFlags[i].String);
|
|
c = '|';
|
|
}
|
|
}
|
|
dprintf("\n");
|
|
|
|
dprintf(" Irp minor......: %s\n", PoIrpMinor ((UCHAR)ReadField(IrpMinor)));
|
|
dprintf(" System State...: %s\n", SystemState((ULONG) ReadField(SystemState)));
|
|
dprintf(" Hiber Context..: %08p\n", ReadField(HiberContext));
|
|
|
|
if (ReadField(DevState)) {
|
|
dprintf ("\n");
|
|
PoDevState ();
|
|
}
|
|
|
|
dprintf("\n");
|
|
return S_OK;
|
|
}
|