/*++ Copyright (c) 1990 Microsoft Corporation Module Name: kdcd.c Abstract: Cluster Disk driver KD extension - based on Vert's skeleton Author: John Vert (jvert) 6-Aug-1992 Revision History: --*/ #include "precomp.h" PCHAR DiskStateTitles[] = { "Offline", "Online", " *** Failed *** ", " *** Stalled *** " }; PCHAR BusTypeTitles[] = { "Root", "SCSI", "Unknown" }; #define IRP_LIST_MAX 20 // // globals // EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 }; WINDBG_EXTENSION_APIS ExtensionApis; USHORT SavedMajorVersion; USHORT SavedMinorVersion; #define TrueOrFalse( _x ) ( _x ? "True" : "False" ) /* forwards */ BOOL ReadTargetMemory( PVOID TargetAddress, PVOID LocalBuffer, ULONG BytesToRead ); __inline PCHAR ListInUse( PLIST_ENTRY, PLIST_ENTRY ); __inline PCHAR TrueFalse( BOOLEAN Value ); /* end forwards */ DllInit( HANDLE hModule, DWORD dwReason, DWORD dwReserved ) { switch (dwReason) { case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; case DLL_PROCESS_ATTACH: break; } return TRUE; } VOID WinDbgExtensionDllInit( PWINDBG_EXTENSION_APIS lpExtensionApis, USHORT MajorVersion, USHORT MinorVersion ) { ExtensionApis = *lpExtensionApis; SavedMajorVersion = MajorVersion; SavedMinorVersion = MinorVersion; return; } DECLARE_API( cdversion ) { #if DBG PCHAR DebuggerType = "Checked"; #else PCHAR DebuggerType = "Free"; #endif dprintf("%s Extension dll for Build %d debugging %s kernel for Build %d\n", DebuggerType, VER_PRODUCTBUILD, SavedMajorVersion == 0x0c ? "Checked" : "Free", SavedMinorVersion ); } VOID CheckVersion( VOID ) { #if DBG if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) { dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n", VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" ); } #else if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) { dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n", VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" ); } #endif } LPEXT_API_VERSION ExtensionApiVersion( VOID ) { return &ApiVersion; } VOID Dump_DrvObj( IN PDRIVER_OBJECT DriverObject ) /* * dump all the devobjs and devexts */ { PCLUS_DEVICE_EXTENSION DevExtension; PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT TargetDevObject; DRIVER_OBJECT LocalDriverObject; DEVICE_OBJECT LocalDeviceObject; CLUS_DEVICE_EXTENSION LocalDevExtension; // // read memory from target machine // if ( !ReadTargetMemory((PVOID)DriverObject, (PVOID)&LocalDriverObject, sizeof(DRIVER_OBJECT))) { return; } dprintf( "DriverObject @ %08X\n", DriverObject ); DeviceObject = LocalDriverObject.DeviceObject; while ( DeviceObject ) { if ( !ReadTargetMemory((PVOID)DeviceObject, (PVOID)&LocalDeviceObject, sizeof(DEVICE_OBJECT))) { return; } TargetDevObject = NULL; DevExtension = LocalDeviceObject.DeviceExtension; if ( DevExtension ) { if ( !ReadTargetMemory((PVOID)DevExtension, (PVOID)&LocalDevExtension, sizeof(CLUS_DEVICE_EXTENSION))) { return; } TargetDevObject = LocalDevExtension.TargetDeviceObject; } dprintf( " DevObj/DevExt/TargetDev: %08X, %08X, %08X\n", DeviceObject, DevExtension, TargetDevObject ); DeviceObject = LocalDeviceObject.NextDevice; } // while return; } // Dump_DrvObj DECLARE_API( cddrvobj ) /* * dump all the devobjs and devexts */ { PDRIVER_OBJECT DriverObject; PCLUS_DEVICE_EXTENSION DevExtension; PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT TargetDevObject; DRIVER_OBJECT LocalDriverObject; DEVICE_OBJECT LocalDeviceObject; CLUS_DEVICE_EXTENSION LocalDevExtension; DriverObject = (PDRIVER_OBJECT)GetExpression( args ); if ( !DriverObject ) { dprintf("bad string conversion (%s) \n", args ); dprintf("try !object \\device\\clusdisk0 \n"); return; } Dump_DrvObj( DriverObject ); return; } // drvobj VOID Dump_DevExt( IN PCLUS_DEVICE_EXTENSION TargetExt ) /* * dump the clusdisk extension structure */ { CLUS_DEVICE_EXTENSION LocalExt; BOOL success; LONG BytesRead; WCHAR LocalDeviceName[512]; // // read memory from target machine // if ( !ReadTargetMemory((PVOID)TargetExt, (PVOID)&LocalExt, sizeof(CLUS_DEVICE_EXTENSION))) { return; } dprintf( " Extension @ %08X\n", TargetExt ); dprintf( " This extension's DevObj = %08X\n", LocalExt.DeviceObject ); dprintf( " Target DevObj = %08X\n", LocalExt.TargetDeviceObject ); dprintf( " Physical (Part0) DevObj = %08X", LocalExt.PhysicalDevice ); if ( LocalExt.DeviceObject == LocalExt.PhysicalDevice ) { dprintf( " [ This device is the physical device ] \n" ); } else { dprintf( " \n" ); } dprintf( " Scsi Address = Port %u Path %u Target %u Lun %u\n", LocalExt.ScsiAddress.PortNumber, LocalExt.ScsiAddress.PathId, LocalExt.ScsiAddress.TargetId, LocalExt.ScsiAddress.Lun); dprintf( " Signature = %08X\n", LocalExt.Signature ); dprintf( " Disk number = %08X (%u)\n", LocalExt.DiskNumber, LocalExt.DiskNumber ); dprintf( " Disk State = %s **** \n", ( LocalExt.DiskState <= DiskStateMaximum ? DiskStateTitles[LocalExt.DiskState] : "Out of Range")); dprintf( " Reservation Timer = %08X\n", LocalExt.ReserveTimer ); dprintf( " Last reserve time = %I64X\n", LocalExt.LastReserve ); dprintf( " Event @ %08X\n", &TargetExt->Event ); dprintf( " Cluster Bus Type = %s\n", (LocalExt.BusType <= UnknownBus ? BusTypeTitles[LocalExt.BusType] : "Out of Range")); dprintf( " Last Reserve Status = %08X\n", LocalExt.ReserveFailure ); dprintf( " HoldIO @ %08X \n", &TargetExt->HoldIO ); dprintf( " %s\n", ListInUse( &LocalExt.HoldIO, (PLIST_ENTRY)&TargetExt->HoldIO )); dprintf( " WaitingIoctls @ %08X\n", &TargetExt->WaitingIoctls ); dprintf( " %s\n", ListInUse( &LocalExt.WaitingIoctls, (PLIST_ENTRY)&TargetExt->WaitingIoctls )); dprintf( " WorkItem @ %08X\n", &TargetExt->WorkItem ); dprintf( " Perform Reserves = %s\n", TrueOrFalse( LocalExt.PerformReserves )); dprintf( " Timer Busy = %s\n", TrueOrFalse( LocalExt.TimerBusy )); dprintf( " AttachValid = %s\n", TrueOrFalse( LocalExt.AttachValid )); dprintf( " Detached = %s\n", TrueOrFalse( LocalExt.Detached )); dprintf( " Driver Object = %08X\n", LocalExt.DriverObject ); dprintf( " Last Partition Number = %u\n", LocalExt.LastPartitionNumber ); dprintf( " Disk Notification Entry = %08X\n", LocalExt.DiskNotificationEntry ); dprintf( " Vol Notification Entry = %08X\n", LocalExt.VolumeNotificationEntry ); dprintf( " Sector Size = %u\n", LocalExt.SectorSize ); dprintf( " Arbitration Sector = %u\n", LocalExt.ArbitrationSector ); dprintf( " Last Write Time (approx) = %I64X \n", LocalExt.LastWriteTime ); dprintf( " VolumeHandles @ %08X \n", &TargetExt->VolumeHandles ); dprintf( " RemoveLock @ %08X [use !remlock] \n", &TargetExt->RemoveLock ); #if 0 if ( ReadTargetMemory((PVOID)LocalExt.DeviceName, (PVOID)&LocalDeviceName, sizeof(LocalDeviceName))) { dprintf( " DeviceName = %ws\n", LocalDeviceName ); } else { dprintf( " DeviceName @ %08X\n", LocalExt.DeviceName ); } #endif dprintf( " Paging event @ %08X \n", &TargetExt->PagingPathCountEvent ); dprintf( " Paging path count = %08X \n", LocalExt.PagingPathCount ); dprintf( " Hibernation path count = %08X \n", LocalExt.HibernationPathCount ); dprintf( " Dump path count = %08X \n", LocalExt.DumpPathCount ); dprintf( " ReclaimInProgress = %08X \n", LocalExt.ReclaimInProgress ); dprintf(" \n"); return; } VOID Dump_All( IN PDRIVER_OBJECT DriverObject ) /* * dump all the devobjs and devexts fully */ { PCLUS_DEVICE_EXTENSION DevExtension; PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT TargetDevObject; DRIVER_OBJECT LocalDriverObject; DEVICE_OBJECT LocalDeviceObject; CLUS_DEVICE_EXTENSION LocalDevExtension; // // read memory from target machine // if ( !ReadTargetMemory((PVOID)DriverObject, (PVOID)&LocalDriverObject, sizeof(DRIVER_OBJECT))) { return; } dprintf( "DriverObject @ %08X\n\n", DriverObject ); DeviceObject = LocalDriverObject.DeviceObject; while ( DeviceObject ) { if ( !ReadTargetMemory((PVOID)DeviceObject, (PVOID)&LocalDeviceObject, sizeof(DEVICE_OBJECT))) { return; } TargetDevObject = NULL; DevExtension = LocalDeviceObject.DeviceExtension; if ( DevExtension ) { if ( !ReadTargetMemory((PVOID)DevExtension, (PVOID)&LocalDevExtension, sizeof(CLUS_DEVICE_EXTENSION))) { return; } TargetDevObject = LocalDevExtension.TargetDeviceObject; } dprintf( "--- \n"); dprintf( " DevObj/DevExt/TargetDev @ %08X, %08X, %08X\n", DeviceObject, DevExtension, TargetDevObject ); if ( DevExtension ) { Dump_DevExt( DevExtension ); } DeviceObject = LocalDeviceObject.NextDevice; } // while return; } // Dump_All DECLARE_API( cddevext ) /* * dump the clusdisk extension structure */ { PCLUS_DEVICE_EXTENSION TargetExt; CLUS_DEVICE_EXTENSION LocalExt; BOOL success; LONG BytesRead; WCHAR LocalDeviceName[512]; // // get address of RGP symbol // TargetExt = (PCLUS_DEVICE_EXTENSION)GetExpression( args ); if ( !TargetExt ) { dprintf("bad string conversion (%s) \n", args ); return; } Dump_DevExt( TargetExt ); return; } DECLARE_API( cddevobj ) /* * dump the clusdisk extension structure for the specfied device object */ { PDEVICE_OBJECT deviceAddr; DEVICE_OBJECT deviceObject; ULONG result; // // get address of RGP symbol // deviceAddr = (PDEVICE_OBJECT)GetExpression( args ); if ( !deviceAddr ) { dprintf("bad string conversion (%s) \n", args ); return; } if ((!ReadMemory( (ULONG_PTR)deviceAddr, &deviceObject, sizeof(deviceObject), &result)) || result < sizeof(deviceObject)) { return; } dprintf( "Device Object @ %08X \n", deviceAddr ); dprintf( " Driver Object @ %08X\n", deviceObject.DriverObject ); Dump_DevExt( deviceObject.DeviceExtension ); return; } DECLARE_API( cddumpall ) /* * dump all the devobjs and devexts */ { PDEVICE_OBJECT deviceAddr; PDEVICE_OBJECT deviceObject; DEVICE_OBJECT localDeviceObject; ULONG result; // // Get clusdisk0 device object. // deviceAddr = (PDEVICE_OBJECT)GetExpression( "clusdisk!RootDeviceObject" ); if ( !deviceAddr ) { dprintf( "Can't get \\device\\clusdisk0 expression \n" ); return; } // // Get a copy of clusdisk0 device object. // if ((!ReadMemory( (ULONG_PTR) deviceAddr, &deviceObject, sizeof(deviceObject), &result)) || result < sizeof(deviceObject)) { dprintf( "Unable to read \\device\\clusdisk0 device object \n" ); return; } dprintf( "ClusDisk0 DevObj @ %08X \n", deviceObject ); if ((!ReadMemory( (ULONG_PTR) deviceObject, &localDeviceObject, sizeof(localDeviceObject), &result)) || result < sizeof(localDeviceObject)) { dprintf( "Unable to read \\device\\clusdisk0 device object \n" ); return; } // dprintf( " Driver Object @ %08X \n", localDeviceObject.DriverObject ); Dump_All( localDeviceObject.DriverObject ); return; } // dumpall DECLARE_API( cddevlist ) /* * run down the device list dumping out the contents */ { PDEVICE_LIST_ENTRY targetDevList; PDEVICE_OBJECT deviceAddr; DEVICE_LIST_ENTRY localDevList; PDEVICE_OBJECT deviceObject; DEVICE_OBJECT localDeviceObject; ULONG result; targetDevList = (PDEVICE_LIST_ENTRY)GetExpression( "clusdisk!ClusDiskDeviceList" ); if ( !targetDevList ) { dprintf("Can't convert clusdisk!ClusDiskDeviceList symbol\n"); return; } // // Get clusdisk0 device object. deviceAddr = (PDEVICE_OBJECT)GetExpression( "clusdisk!RootDeviceObject" ); if ( !deviceAddr ) { dprintf( "Can't get \\device\\clusdisk0 expression \n" ); return; } // // Get a copy of clusdisk0 device object. // if ((!ReadMemory( (ULONG_PTR) deviceAddr, &deviceObject, sizeof(deviceObject), &result)) || result < sizeof(deviceObject)) { dprintf( "Unable to read \\device\\clusdisk0 device object \n" ); return; } dprintf( "ClusDisk0 Device Object @ %08X \n", deviceObject ); if ((!ReadMemory( (ULONG_PTR) deviceObject, &localDeviceObject, sizeof(localDeviceObject), &result)) || result < sizeof(localDeviceObject)) { dprintf( "Unable to read \\device\\clusdisk0 device object \n" ); return; } dprintf( " Driver Object @ %08X \n", localDeviceObject.DriverObject ); // // read head of device list's contents from other machine // if ( !ReadTargetMemory( targetDevList, &targetDevList, sizeof( PDEVICE_LIST_ENTRY ))) { dprintf("Can't get ClusDiskDeviceList data\n"); return; } while ( targetDevList != NULL ) { if (CheckControlC()) { return; } // // read device list entry out of target's memory // if ( !ReadTargetMemory( targetDevList, &localDevList, sizeof( DEVICE_LIST_ENTRY ))) { dprintf("Problem reading device list at %x\n", targetDevList ); return; } dprintf( "\nDeviceList @ %08X\n", targetDevList ); #if 0 // Not needed... dprintf( " Next DeviceList @ %08X\n", localDevList.Next ); #endif dprintf( " Signature = %08X\n", localDevList.Signature ); dprintf( " DeviceObject = %08X\n", localDevList.DeviceObject ); dprintf( " Attached = %s\n", TrueOrFalse( localDevList.Attached )); dprintf( " LettersAssigned = %s\n", TrueOrFalse( localDevList.LettersAssigned )); targetDevList = (PDEVICE_LIST_ENTRY)localDevList.Next; } dprintf("\n"); } // devlist BOOL ReadTargetMemory( PVOID TargetAddress, PVOID LocalBuffer, ULONG BytesToRead ) { BOOL success; ULONG BytesRead; success = ReadMemory((ULONG_PTR)TargetAddress, LocalBuffer, BytesToRead, &BytesRead); if (success) { if (BytesRead != BytesToRead) { dprintf("wrong byte count. expected=%d, read =%d\n", BytesToRead, BytesRead); } } else { dprintf("Problem reading memory at %08X for %u bytes\n", TargetAddress, BytesToRead); success = FALSE; } return success; } PCHAR ListInUse( PLIST_ENTRY ListToCheck, PLIST_ENTRY RealListAddress ) /* * The Lists only hold IRPs! */ { PIRP Irp; IRP LocalIrp; PLIST_ENTRY Next; USHORT irpCount = 0; if ( ListToCheck->Flink == RealListAddress ) { return( "(empty)" ); } else { dprintf( "\n" ); Next = ListToCheck->Flink; while ( Next != RealListAddress ) { Irp = CONTAINING_RECORD( Next, IRP, Tail.Overlay.ListEntry ); if ( !ReadTargetMemory((PVOID)Irp, (PVOID)&LocalIrp, sizeof(IRP))) { dprintf( "Failed to read irp @ %08X \n", Irp ); return(""); } dprintf( " ++ IRP: %08X\n", Irp ); Next = LocalIrp.Tail.Overlay.ListEntry.Flink; if ( irpCount++ > IRP_LIST_MAX ) { dprintf( " ++ Exceeded IRP max (possibly corrupt list) - stopping \n" ); break; } } return (""); } } DECLARE_API( help ) { dprintf("Clusdisk kd extensions\n\n"); dprintf(" cddevlist - dump the clusdisk device list\n"); dprintf(" cddevext
- dump a devobj's extension structure\n"); dprintf(" cddrvobj
- dump the driver object\n"); dprintf(" cddevobj
- dump the devobj's extension\n"); dprintf(" cddumpall - dump all devobj extensions, given a drvobj address\n\n"); return; }