/*++ 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 - 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)) { ULONG64 pName; KD_OBJECT_HEADER_TO_NAME_INFO( pObjectHeader, &pNameInfo ); if (GetFieldValue(pNameInfo, "nt!_OBJECT_HEADER_NAME_INFO", "Name.Length", Length)) { if (Length > 0x1000) // sanity check { Length = 0x1000; } 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)) { unicodeString.Buffer[(unicodeString.Length/sizeof(WCHAR))-1] = 0; 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; 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); } } if (CheckControlC()) { break; } } 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)) { if (Length > 0x1000) // sanity check { Length = 0x1000; } 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)) { unicodeString.Buffer[(unicodeString.Length/sizeof(WCHAR))-1] = 0; 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:%08I64lx Empty", UNEXTEND64(Va)); } else { sprintf (Buffer, "Head:%08I64lx F:%08I64lx B:%08I64lx", UNEXTEND64(Va), UNEXTEND64(Flink), UNEXTEND64(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