windows-nt/Source/XPSP1/NT/base/cluster/clusdisk/kdcd/kdcd.c
2020-09-26 16:20:57 +08:00

726 lines
18 KiB
C

/*++
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 <address> - dump a devobj's extension structure\n");
dprintf(" cddrvobj <address> - dump the driver object\n");
dprintf(" cddevobj <address> - dump the devobj's extension\n");
dprintf(" cddumpall - dump all devobj extensions, given a drvobj address\n\n");
return;
}