/*++ Copyright (c) 1992 Microsoft Corporation Module Name: device.c Abstract: WinDbg Extension Api Author: Wesley Witt (wesw) 15-Aug-1993 Environment: User Mode. Revision History: --*/ #include "precomp.h" #pragma hdrstop VOID DumpDriver( PVOID DriverAddress, BOOLEAN FullDetail ); DECLARE_API( devobj ) /*++ Routine Description: Dump a device object. Arguments: args - the location of the device object to dump. Return Value: None --*/ { ULONG deviceToDump; sscanf(args, "%lx", &deviceToDump); dprintf("Device object is for:\n"); DumpDevice((PVOID) deviceToDump, TRUE); } VOID DumpDevice( PVOID DeviceAddress, BOOLEAN FullDetail ) /*++ Routine Description: Displays the driver name for the device object if FullDetail == FALSE. Otherwise displays more information about the device and the device queue. Arguments: DeviceAddress - address of device object to dump. FullDetail - TRUE means the device object name, driver name, and information about Irps queued to the device. Return Value: None --*/ { ULONG result; ULONG i; PUCHAR buffer; DEVICE_OBJECT deviceObject; UNICODE_STRING unicodeString; PLIST_ENTRY nextEntry; PVOID queueAddress; PIRP irp; KDEVICE_QUEUE_ENTRY queueEntry; POBJECT_HEADER pObjectHeader; OBJECT_HEADER objectHeader; POBJECT_HEADER_NAME_INFO pNameInfo; OBJECT_HEADER_NAME_INFO NameInfo; if ((!ReadMemory( (DWORD)DeviceAddress, &deviceObject, sizeof(deviceObject), &result)) || (result < sizeof(deviceObject))) { dprintf("%08lx: Could not read device object\n", DeviceAddress); return; } if (deviceObject.Type != IO_TYPE_DEVICE) { dprintf("%08lx: is not a device object\n", DeviceAddress); return; } if (FullDetail == TRUE) { // // Dump the device name if present. // pObjectHeader = OBJECT_TO_OBJECT_HEADER(DeviceAddress); if (ReadMemory( (DWORD)pObjectHeader, &objectHeader, sizeof(objectHeader), &result) && (result == sizeof(objectHeader))) { pNameInfo = KD_OBJECT_HEADER_TO_NAME_INFO( pObjectHeader, &objectHeader ); if (ReadMemory((DWORD)pNameInfo, &NameInfo, sizeof(NameInfo), &result) && (result == sizeof(NameInfo))) { buffer = LocalAlloc(LPTR, NameInfo.Name.MaximumLength); if (buffer != NULL) { unicodeString.MaximumLength = NameInfo.Name.MaximumLength; unicodeString.Length = NameInfo.Name.Length; unicodeString.Buffer = (PWSTR)buffer; if (ReadMemory((DWORD)NameInfo.Name.Buffer, buffer, unicodeString.Length, &result) && (result == unicodeString.Length)) { dprintf(" %wZ", &unicodeString); } LocalFree(buffer); } } } } DumpDriver((PVOID) deviceObject.DriverObject, FALSE); if (FullDetail == TRUE) { // // Dump Irps related to driver. // dprintf(" DriverObject %08lx\n", deviceObject.DriverObject); dprintf("Current Irp %08lx RefCount %d Type %08lx ", deviceObject.CurrentIrp, deviceObject.ReferenceCount, deviceObject.DeviceType); if (deviceObject.AttachedDevice) { dprintf("AttachedDev %08lx ", deviceObject.AttachedDevice); } if (deviceObject.Vpb) { dprintf("Vpb %08lx ", deviceObject.Vpb); } dprintf("DevExt %08lx\n", deviceObject.DeviceExtension); if (deviceObject.DeviceQueue.Busy) { if (IsListEmpty(&deviceObject.DeviceQueue.DeviceListHead)) { dprintf("Device queue is busy -- Queue empty\n"); } else { dprintf("DeviceQueue: "); nextEntry = deviceObject.DeviceQueue.DeviceListHead.Flink; i = 0; while ((PCH) nextEntry != (PCH) ((PCH) DeviceAddress + ((PCH) &deviceObject.DeviceQueue.DeviceListHead.Flink - (PCH) &deviceObject))) { queueAddress = CONTAINING_RECORD(nextEntry, KDEVICE_QUEUE_ENTRY, DeviceListEntry); if ((!ReadMemory((DWORD)queueAddress, &queueEntry, sizeof(queueEntry), &result)) || (result < sizeof(queueEntry))) { dprintf("%08lx: Could not read queue entry\n", DeviceAddress); return; } irp = CONTAINING_RECORD(&queueEntry, IRP, Tail.Overlay.DeviceQueueEntry); dprintf("%08lx%s", irp, (i & 0x03) == 0x03 ? "\n\t " : " "); if (CheckControlC()) { break; } } dprintf("\n"); } } else { dprintf("Device queue is not busy.\n"); } } }