Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

725 lines
18 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. kdcd.c
  5. Abstract:
  6. Cluster Disk driver KD extension - based on Vert's skeleton
  7. Author:
  8. John Vert (jvert) 6-Aug-1992
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. PCHAR DiskStateTitles[] = {
  13. "Offline",
  14. "Online",
  15. " *** Failed *** ",
  16. " *** Stalled *** "
  17. };
  18. PCHAR BusTypeTitles[] = {
  19. "Root",
  20. "SCSI",
  21. "Unknown"
  22. };
  23. #define IRP_LIST_MAX 20
  24. //
  25. // globals
  26. //
  27. EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 };
  28. WINDBG_EXTENSION_APIS ExtensionApis;
  29. USHORT SavedMajorVersion;
  30. USHORT SavedMinorVersion;
  31. #define TrueOrFalse( _x ) ( _x ? "True" : "False" )
  32. /* forwards */
  33. BOOL
  34. ReadTargetMemory(
  35. PVOID TargetAddress,
  36. PVOID LocalBuffer,
  37. ULONG BytesToRead
  38. );
  39. __inline PCHAR
  40. ListInUse(
  41. PLIST_ENTRY,
  42. PLIST_ENTRY
  43. );
  44. __inline PCHAR
  45. TrueFalse(
  46. BOOLEAN Value
  47. );
  48. /* end forwards */
  49. DllInit(
  50. HANDLE hModule,
  51. DWORD dwReason,
  52. DWORD dwReserved
  53. )
  54. {
  55. switch (dwReason) {
  56. case DLL_THREAD_ATTACH:
  57. break;
  58. case DLL_THREAD_DETACH:
  59. break;
  60. case DLL_PROCESS_DETACH:
  61. break;
  62. case DLL_PROCESS_ATTACH:
  63. break;
  64. }
  65. return TRUE;
  66. }
  67. VOID
  68. WinDbgExtensionDllInit(
  69. PWINDBG_EXTENSION_APIS lpExtensionApis,
  70. USHORT MajorVersion,
  71. USHORT MinorVersion
  72. )
  73. {
  74. ExtensionApis = *lpExtensionApis;
  75. SavedMajorVersion = MajorVersion;
  76. SavedMinorVersion = MinorVersion;
  77. return;
  78. }
  79. DECLARE_API( cdversion )
  80. {
  81. #if DBG
  82. PCHAR DebuggerType = "Checked";
  83. #else
  84. PCHAR DebuggerType = "Free";
  85. #endif
  86. dprintf("%s Extension dll for Build %d debugging %s kernel for Build %d\n",
  87. DebuggerType,
  88. VER_PRODUCTBUILD,
  89. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  90. SavedMinorVersion
  91. );
  92. }
  93. VOID
  94. CheckVersion(
  95. VOID
  96. )
  97. {
  98. #if DBG
  99. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  100. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  101. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  102. }
  103. #else
  104. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  105. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  106. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  107. }
  108. #endif
  109. }
  110. LPEXT_API_VERSION
  111. ExtensionApiVersion(
  112. VOID
  113. )
  114. {
  115. return &ApiVersion;
  116. }
  117. VOID
  118. Dump_DrvObj(
  119. IN PDRIVER_OBJECT DriverObject
  120. )
  121. /*
  122. * dump all the devobjs and devexts
  123. */
  124. {
  125. PCLUS_DEVICE_EXTENSION DevExtension;
  126. PDEVICE_OBJECT DeviceObject;
  127. PDEVICE_OBJECT TargetDevObject;
  128. DRIVER_OBJECT LocalDriverObject;
  129. DEVICE_OBJECT LocalDeviceObject;
  130. CLUS_DEVICE_EXTENSION LocalDevExtension;
  131. //
  132. // read memory from target machine
  133. //
  134. if ( !ReadTargetMemory((PVOID)DriverObject,
  135. (PVOID)&LocalDriverObject,
  136. sizeof(DRIVER_OBJECT))) {
  137. return;
  138. }
  139. dprintf( "DriverObject @ %08X\n", DriverObject );
  140. DeviceObject = LocalDriverObject.DeviceObject;
  141. while ( DeviceObject ) {
  142. if ( !ReadTargetMemory((PVOID)DeviceObject,
  143. (PVOID)&LocalDeviceObject,
  144. sizeof(DEVICE_OBJECT))) {
  145. return;
  146. }
  147. TargetDevObject = NULL;
  148. DevExtension = LocalDeviceObject.DeviceExtension;
  149. if ( DevExtension ) {
  150. if ( !ReadTargetMemory((PVOID)DevExtension,
  151. (PVOID)&LocalDevExtension,
  152. sizeof(CLUS_DEVICE_EXTENSION))) {
  153. return;
  154. }
  155. TargetDevObject = LocalDevExtension.TargetDeviceObject;
  156. }
  157. dprintf( " DevObj/DevExt/TargetDev: %08X, %08X, %08X\n",
  158. DeviceObject,
  159. DevExtension,
  160. TargetDevObject );
  161. DeviceObject = LocalDeviceObject.NextDevice;
  162. } // while
  163. return;
  164. } // Dump_DrvObj
  165. DECLARE_API( cddrvobj )
  166. /*
  167. * dump all the devobjs and devexts
  168. */
  169. {
  170. PDRIVER_OBJECT DriverObject;
  171. PCLUS_DEVICE_EXTENSION DevExtension;
  172. PDEVICE_OBJECT DeviceObject;
  173. PDEVICE_OBJECT TargetDevObject;
  174. DRIVER_OBJECT LocalDriverObject;
  175. DEVICE_OBJECT LocalDeviceObject;
  176. CLUS_DEVICE_EXTENSION LocalDevExtension;
  177. DriverObject = (PDRIVER_OBJECT)GetExpression( args );
  178. if ( !DriverObject ) {
  179. dprintf("bad string conversion (%s) \n", args );
  180. dprintf("try !object \\device\\clusdisk0 \n");
  181. return;
  182. }
  183. Dump_DrvObj( DriverObject );
  184. return;
  185. } // drvobj
  186. VOID
  187. Dump_DevExt(
  188. IN PCLUS_DEVICE_EXTENSION TargetExt
  189. )
  190. /*
  191. * dump the clusdisk extension structure
  192. */
  193. {
  194. CLUS_DEVICE_EXTENSION LocalExt;
  195. BOOL success;
  196. LONG BytesRead;
  197. WCHAR LocalDeviceName[512];
  198. //
  199. // read memory from target machine
  200. //
  201. if ( !ReadTargetMemory((PVOID)TargetExt,
  202. (PVOID)&LocalExt,
  203. sizeof(CLUS_DEVICE_EXTENSION))) {
  204. return;
  205. }
  206. dprintf( " Extension @ %08X\n", TargetExt );
  207. dprintf( " This extension's DevObj = %08X\n", LocalExt.DeviceObject );
  208. dprintf( " Target DevObj = %08X\n", LocalExt.TargetDeviceObject );
  209. dprintf( " Physical (Part0) DevObj = %08X", LocalExt.PhysicalDevice );
  210. if ( LocalExt.DeviceObject == LocalExt.PhysicalDevice ) {
  211. dprintf( " [ This device is the physical device ] \n" );
  212. } else {
  213. dprintf( " \n" );
  214. }
  215. dprintf( " Scsi Address = Port %u Path %u Target %u Lun %u\n",
  216. LocalExt.ScsiAddress.PortNumber,
  217. LocalExt.ScsiAddress.PathId,
  218. LocalExt.ScsiAddress.TargetId,
  219. LocalExt.ScsiAddress.Lun);
  220. dprintf( " Signature = %08X\n", LocalExt.Signature );
  221. dprintf( " Disk number = %08X (%u)\n", LocalExt.DiskNumber, LocalExt.DiskNumber );
  222. dprintf( " Disk State = %s **** \n", ( LocalExt.DiskState <= DiskStateMaximum ?
  223. DiskStateTitles[LocalExt.DiskState] :
  224. "Out of Range"));
  225. dprintf( " Reservation Timer = %08X\n", LocalExt.ReserveTimer );
  226. dprintf( " Last reserve time = %I64X\n", LocalExt.LastReserve );
  227. dprintf( " Event @ %08X\n", &TargetExt->Event );
  228. dprintf( " Cluster Bus Type = %s\n", (LocalExt.BusType <= UnknownBus ?
  229. BusTypeTitles[LocalExt.BusType] :
  230. "Out of Range"));
  231. dprintf( " Last Reserve Status = %08X\n", LocalExt.ReserveFailure );
  232. dprintf( " HoldIO @ %08X \n", &TargetExt->HoldIO );
  233. dprintf( " %s\n",
  234. ListInUse( &LocalExt.HoldIO, (PLIST_ENTRY)&TargetExt->HoldIO ));
  235. dprintf( " WaitingIoctls @ %08X\n", &TargetExt->WaitingIoctls );
  236. dprintf( " %s\n",
  237. ListInUse( &LocalExt.WaitingIoctls, (PLIST_ENTRY)&TargetExt->WaitingIoctls ));
  238. dprintf( " WorkItem @ %08X\n", &TargetExt->WorkItem );
  239. dprintf( " Perform Reserves = %s\n", TrueOrFalse( LocalExt.PerformReserves ));
  240. dprintf( " Timer Busy = %s\n", TrueOrFalse( LocalExt.TimerBusy ));
  241. dprintf( " AttachValid = %s\n", TrueOrFalse( LocalExt.AttachValid ));
  242. dprintf( " Detached = %s\n", TrueOrFalse( LocalExt.Detached ));
  243. dprintf( " Driver Object = %08X\n", LocalExt.DriverObject );
  244. dprintf( " Last Partition Number = %u\n", LocalExt.LastPartitionNumber );
  245. dprintf( " Disk Notification Entry = %08X\n", LocalExt.DiskNotificationEntry );
  246. dprintf( " Vol Notification Entry = %08X\n", LocalExt.VolumeNotificationEntry );
  247. dprintf( " Sector Size = %u\n", LocalExt.SectorSize );
  248. dprintf( " Arbitration Sector = %u\n", LocalExt.ArbitrationSector );
  249. dprintf( " Last Write Time (approx) = %I64X \n", LocalExt.LastWriteTime );
  250. dprintf( " VolumeHandles @ %08X \n", &TargetExt->VolumeHandles );
  251. dprintf( " RemoveLock @ %08X [use !remlock] \n", &TargetExt->RemoveLock );
  252. #if 0
  253. if ( ReadTargetMemory((PVOID)LocalExt.DeviceName,
  254. (PVOID)&LocalDeviceName,
  255. sizeof(LocalDeviceName))) {
  256. dprintf( " DeviceName = %ws\n", LocalDeviceName );
  257. } else {
  258. dprintf( " DeviceName @ %08X\n", LocalExt.DeviceName );
  259. }
  260. #endif
  261. dprintf( " Paging event @ %08X \n", &TargetExt->PagingPathCountEvent );
  262. dprintf( " Paging path count = %08X \n", LocalExt.PagingPathCount );
  263. dprintf( " Hibernation path count = %08X \n", LocalExt.HibernationPathCount );
  264. dprintf( " Dump path count = %08X \n", LocalExt.DumpPathCount );
  265. dprintf( " ReclaimInProgress = %08X \n", LocalExt.ReclaimInProgress );
  266. dprintf(" \n");
  267. return;
  268. }
  269. VOID
  270. Dump_All(
  271. IN PDRIVER_OBJECT DriverObject
  272. )
  273. /*
  274. * dump all the devobjs and devexts fully
  275. */
  276. {
  277. PCLUS_DEVICE_EXTENSION DevExtension;
  278. PDEVICE_OBJECT DeviceObject;
  279. PDEVICE_OBJECT TargetDevObject;
  280. DRIVER_OBJECT LocalDriverObject;
  281. DEVICE_OBJECT LocalDeviceObject;
  282. CLUS_DEVICE_EXTENSION LocalDevExtension;
  283. //
  284. // read memory from target machine
  285. //
  286. if ( !ReadTargetMemory((PVOID)DriverObject,
  287. (PVOID)&LocalDriverObject,
  288. sizeof(DRIVER_OBJECT))) {
  289. return;
  290. }
  291. dprintf( "DriverObject @ %08X\n\n", DriverObject );
  292. DeviceObject = LocalDriverObject.DeviceObject;
  293. while ( DeviceObject ) {
  294. if ( !ReadTargetMemory((PVOID)DeviceObject,
  295. (PVOID)&LocalDeviceObject,
  296. sizeof(DEVICE_OBJECT))) {
  297. return;
  298. }
  299. TargetDevObject = NULL;
  300. DevExtension = LocalDeviceObject.DeviceExtension;
  301. if ( DevExtension ) {
  302. if ( !ReadTargetMemory((PVOID)DevExtension,
  303. (PVOID)&LocalDevExtension,
  304. sizeof(CLUS_DEVICE_EXTENSION))) {
  305. return;
  306. }
  307. TargetDevObject = LocalDevExtension.TargetDeviceObject;
  308. }
  309. dprintf( "--- \n");
  310. dprintf( " DevObj/DevExt/TargetDev @ %08X, %08X, %08X\n",
  311. DeviceObject,
  312. DevExtension,
  313. TargetDevObject );
  314. if ( DevExtension ) {
  315. Dump_DevExt( DevExtension );
  316. }
  317. DeviceObject = LocalDeviceObject.NextDevice;
  318. } // while
  319. return;
  320. } // Dump_All
  321. DECLARE_API( cddevext )
  322. /*
  323. * dump the clusdisk extension structure
  324. */
  325. {
  326. PCLUS_DEVICE_EXTENSION TargetExt;
  327. CLUS_DEVICE_EXTENSION LocalExt;
  328. BOOL success;
  329. LONG BytesRead;
  330. WCHAR LocalDeviceName[512];
  331. //
  332. // get address of RGP symbol
  333. //
  334. TargetExt = (PCLUS_DEVICE_EXTENSION)GetExpression( args );
  335. if ( !TargetExt ) {
  336. dprintf("bad string conversion (%s) \n", args );
  337. return;
  338. }
  339. Dump_DevExt( TargetExt );
  340. return;
  341. }
  342. DECLARE_API( cddevobj )
  343. /*
  344. * dump the clusdisk extension structure for the specfied device object
  345. */
  346. {
  347. PDEVICE_OBJECT deviceAddr;
  348. DEVICE_OBJECT deviceObject;
  349. ULONG result;
  350. //
  351. // get address of RGP symbol
  352. //
  353. deviceAddr = (PDEVICE_OBJECT)GetExpression( args );
  354. if ( !deviceAddr ) {
  355. dprintf("bad string conversion (%s) \n", args );
  356. return;
  357. }
  358. if ((!ReadMemory( (ULONG_PTR)deviceAddr,
  359. &deviceObject,
  360. sizeof(deviceObject),
  361. &result)) || result < sizeof(deviceObject)) {
  362. return;
  363. }
  364. dprintf( "Device Object @ %08X \n", deviceAddr );
  365. dprintf( " Driver Object @ %08X\n", deviceObject.DriverObject );
  366. Dump_DevExt( deviceObject.DeviceExtension );
  367. return;
  368. }
  369. DECLARE_API( cddumpall )
  370. /*
  371. * dump all the devobjs and devexts
  372. */
  373. {
  374. PDEVICE_OBJECT deviceAddr;
  375. PDEVICE_OBJECT deviceObject;
  376. DEVICE_OBJECT localDeviceObject;
  377. ULONG result;
  378. //
  379. // Get clusdisk0 device object.
  380. //
  381. deviceAddr = (PDEVICE_OBJECT)GetExpression( "clusdisk!RootDeviceObject" );
  382. if ( !deviceAddr ) {
  383. dprintf( "Can't get \\device\\clusdisk0 expression \n" );
  384. return;
  385. }
  386. //
  387. // Get a copy of clusdisk0 device object.
  388. //
  389. if ((!ReadMemory( (ULONG_PTR) deviceAddr,
  390. &deviceObject,
  391. sizeof(deviceObject),
  392. &result)) || result < sizeof(deviceObject)) {
  393. dprintf( "Unable to read \\device\\clusdisk0 device object \n" );
  394. return;
  395. }
  396. dprintf( "ClusDisk0 DevObj @ %08X \n", deviceObject );
  397. if ((!ReadMemory( (ULONG_PTR) deviceObject,
  398. &localDeviceObject,
  399. sizeof(localDeviceObject),
  400. &result)) || result < sizeof(localDeviceObject)) {
  401. dprintf( "Unable to read \\device\\clusdisk0 device object \n" );
  402. return;
  403. }
  404. // dprintf( " Driver Object @ %08X \n", localDeviceObject.DriverObject );
  405. Dump_All( localDeviceObject.DriverObject );
  406. return;
  407. } // dumpall
  408. DECLARE_API( cddevlist )
  409. /*
  410. * run down the device list dumping out the contents
  411. */
  412. {
  413. PDEVICE_LIST_ENTRY targetDevList;
  414. PDEVICE_OBJECT deviceAddr;
  415. DEVICE_LIST_ENTRY localDevList;
  416. PDEVICE_OBJECT deviceObject;
  417. DEVICE_OBJECT localDeviceObject;
  418. ULONG result;
  419. targetDevList = (PDEVICE_LIST_ENTRY)GetExpression( "clusdisk!ClusDiskDeviceList" );
  420. if ( !targetDevList ) {
  421. dprintf("Can't convert clusdisk!ClusDiskDeviceList symbol\n");
  422. return;
  423. }
  424. //
  425. // Get clusdisk0 device object.
  426. deviceAddr = (PDEVICE_OBJECT)GetExpression( "clusdisk!RootDeviceObject" );
  427. if ( !deviceAddr ) {
  428. dprintf( "Can't get \\device\\clusdisk0 expression \n" );
  429. return;
  430. }
  431. //
  432. // Get a copy of clusdisk0 device object.
  433. //
  434. if ((!ReadMemory( (ULONG_PTR) deviceAddr,
  435. &deviceObject,
  436. sizeof(deviceObject),
  437. &result)) || result < sizeof(deviceObject)) {
  438. dprintf( "Unable to read \\device\\clusdisk0 device object \n" );
  439. return;
  440. }
  441. dprintf( "ClusDisk0 Device Object @ %08X \n", deviceObject );
  442. if ((!ReadMemory( (ULONG_PTR) deviceObject,
  443. &localDeviceObject,
  444. sizeof(localDeviceObject),
  445. &result)) || result < sizeof(localDeviceObject)) {
  446. dprintf( "Unable to read \\device\\clusdisk0 device object \n" );
  447. return;
  448. }
  449. dprintf( " Driver Object @ %08X \n", localDeviceObject.DriverObject );
  450. //
  451. // read head of device list's contents from other machine
  452. //
  453. if ( !ReadTargetMemory( targetDevList, &targetDevList, sizeof( PDEVICE_LIST_ENTRY ))) {
  454. dprintf("Can't get ClusDiskDeviceList data\n");
  455. return;
  456. }
  457. while ( targetDevList != NULL ) {
  458. if (CheckControlC()) {
  459. return;
  460. }
  461. //
  462. // read device list entry out of target's memory
  463. //
  464. if ( !ReadTargetMemory( targetDevList, &localDevList, sizeof( DEVICE_LIST_ENTRY ))) {
  465. dprintf("Problem reading device list at %x\n", targetDevList );
  466. return;
  467. }
  468. dprintf( "\nDeviceList @ %08X\n", targetDevList );
  469. #if 0 // Not needed...
  470. dprintf( " Next DeviceList @ %08X\n", localDevList.Next );
  471. #endif
  472. dprintf( " Signature = %08X\n", localDevList.Signature );
  473. dprintf( " DeviceObject = %08X\n", localDevList.DeviceObject );
  474. dprintf( " Attached = %s\n", TrueOrFalse( localDevList.Attached ));
  475. dprintf( " LettersAssigned = %s\n", TrueOrFalse( localDevList.LettersAssigned ));
  476. targetDevList = (PDEVICE_LIST_ENTRY)localDevList.Next;
  477. }
  478. dprintf("\n");
  479. } // devlist
  480. BOOL
  481. ReadTargetMemory(
  482. PVOID TargetAddress,
  483. PVOID LocalBuffer,
  484. ULONG BytesToRead
  485. )
  486. {
  487. BOOL success;
  488. ULONG BytesRead;
  489. success = ReadMemory((ULONG_PTR)TargetAddress, LocalBuffer, BytesToRead, &BytesRead);
  490. if (success) {
  491. if (BytesRead != BytesToRead) {
  492. dprintf("wrong byte count. expected=%d, read =%d\n", BytesToRead, BytesRead);
  493. }
  494. } else {
  495. dprintf("Problem reading memory at %08X for %u bytes\n",
  496. TargetAddress, BytesToRead);
  497. success = FALSE;
  498. }
  499. return success;
  500. }
  501. PCHAR
  502. ListInUse(
  503. PLIST_ENTRY ListToCheck,
  504. PLIST_ENTRY RealListAddress
  505. )
  506. /*
  507. * The Lists only hold IRPs!
  508. */
  509. {
  510. PIRP Irp;
  511. IRP LocalIrp;
  512. PLIST_ENTRY Next;
  513. USHORT irpCount = 0;
  514. if ( ListToCheck->Flink == RealListAddress ) {
  515. return( "(empty)" );
  516. } else {
  517. dprintf( "\n" );
  518. Next = ListToCheck->Flink;
  519. while ( Next != RealListAddress ) {
  520. Irp = CONTAINING_RECORD( Next,
  521. IRP,
  522. Tail.Overlay.ListEntry );
  523. if ( !ReadTargetMemory((PVOID)Irp,
  524. (PVOID)&LocalIrp,
  525. sizeof(IRP))) {
  526. dprintf( "Failed to read irp @ %08X \n", Irp );
  527. return("");
  528. }
  529. dprintf( " ++ IRP: %08X\n", Irp );
  530. Next = LocalIrp.Tail.Overlay.ListEntry.Flink;
  531. if ( irpCount++ > IRP_LIST_MAX ) {
  532. dprintf( " ++ Exceeded IRP max (possibly corrupt list) - stopping \n" );
  533. break;
  534. }
  535. }
  536. return ("");
  537. }
  538. }
  539. DECLARE_API( help )
  540. {
  541. dprintf("Clusdisk kd extensions\n\n");
  542. dprintf(" cddevlist - dump the clusdisk device list\n");
  543. dprintf(" cddevext <address> - dump a devobj's extension structure\n");
  544. dprintf(" cddrvobj <address> - dump the driver object\n");
  545. dprintf(" cddevobj <address> - dump the devobj's extension\n");
  546. dprintf(" cddumpall - dump all devobj extensions, given a drvobj address\n\n");
  547. return;
  548. }