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.

926 lines
25 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. FatKd.c
  5. Abstract:
  6. KD Extension Api for examining Fat specific data structures
  7. Author:
  8. Tom Jolly [tomjolly] 14-Sep-99
  9. (ntfskd) Keith Kaplan [KeithKa] 24-Apr-96
  10. Portions by Jeff Havens
  11. Environment:
  12. User Mode.
  13. Revision History:
  14. --*/
  15. #include "pch.h"
  16. #undef FlagOn
  17. #undef WordAlign
  18. #undef LongAlign
  19. #undef QuadAlign
  20. #undef DebugPrint
  21. #undef MAXULONGLONG
  22. #define KDEXT
  23. //#include "gentable.h"
  24. #undef DebugTrace
  25. #include "..\nodetype.h"
  26. #include "..\..\cdfs\nodetype.h"
  27. #include "..\..\udfs\nodetype.h"
  28. #ifdef UDFS_RW_IN_BUILD
  29. #include "..\..\udfsrw\nodetype.h"
  30. #endif
  31. #include "fatkd.h"
  32. #include "cdfskd.h"
  33. #include "udfskd.h"
  34. //
  35. // Lookup table that tells how many clear bits (i.e., 0) there are in a byte
  36. //
  37. CONST UCHAR BitsClearTotal[] =
  38. { 8,7,7,6,7,6,6,5,7,6,6,5,6,5,5,4,
  39. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  40. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  41. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  42. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  43. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  44. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  45. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  46. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  47. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  48. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  49. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  50. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  51. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  52. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  53. 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
  54. VOID
  55. DumpStr(
  56. IN ULONG FieldOffset,
  57. IN ULONG64 StringAddress,
  58. IN PUCHAR Label,
  59. IN BOOLEAN CrFirst,
  60. IN BOOLEAN Wide
  61. )
  62. {
  63. WCHAR Buffer[512];
  64. ULONG64 StringChars = 0; // *64
  65. USHORT DisplayLength;
  66. UNICODE_STRING String;
  67. ROE( GetFieldValue( StringAddress, "UNICODE_STRING", "Buffer", StringChars));
  68. ROE( GetFieldValue( StringAddress, "UNICODE_STRING", "Length", DisplayLength));
  69. ROE( GetFieldValue( StringAddress, "UNICODE_STRING", "MaximumLength", String.MaximumLength));
  70. if (DisplayLength > sizeof( Buffer)) {
  71. DisplayLength = sizeof(Buffer);
  72. }
  73. if (CrFirst) {
  74. dprintf("\n");
  75. }
  76. if (DisplayLength) {
  77. if (StringChars) {
  78. ReadM( Buffer, StringChars, DisplayLength);
  79. String.Length = DisplayLength;
  80. String.Buffer = Buffer;
  81. }
  82. else {
  83. String.Buffer = (PWCHAR)"<<NULL buffer pointer>>";
  84. String.Length = 23;
  85. Wide = FALSE;
  86. }
  87. }
  88. else {
  89. String.Buffer = (PWCHAR)"<<empty>>";
  90. String.Length = 9;
  91. Wide = FALSE;
  92. }
  93. if (Wide) {
  94. dprintf( "%s: (%03x/%03x) '%wZ'\n",
  95. Label, DisplayLength, String.MaximumLength,
  96. &String );
  97. }
  98. else {
  99. dprintf( "%s: (%03x/%03x) '%Z'\n",
  100. Label, DisplayLength, String.MaximumLength,
  101. &String );
  102. }
  103. }
  104. ULONG
  105. Dt( IN UCHAR *Type,
  106. IN ULONG64 Addr,
  107. IN ULONG Recur,
  108. IN ULONG FieldInfoCount,
  109. IN FIELD_INFO FieldInfo[]
  110. )
  111. {
  112. SYM_DUMP_PARAM Param;
  113. Param.size = sizeof( Param);
  114. Param.sName = Type;
  115. Param.Options = DBG_DUMP_RECUR_LEVEL(Recur);
  116. Param.addr = Addr;
  117. Param.listLink = NULL;
  118. Param.Context = NULL;
  119. Param.CallbackRoutine = NULL;
  120. Param.nFields = FieldInfoCount;
  121. Param.Fields = FieldInfo;
  122. return Ioctl( IG_DUMP_SYMBOL_INFO, &Param, Param.size);
  123. }
  124. //
  125. // The help strings printed out
  126. //
  127. static LPSTR Extensions[] = {
  128. "FAT/CDFS/UDFS Debugger Extension Commands, where...\n\n [FS] => CD/UDF/FAT\n -> in output denotes address of embedded structure\n",
  129. " [FS]mcb [addr] [1] Dump MCB",
  130. " [1] Dump out extent list",
  131. " [FS]vdo [addr] Volume device object (from direct addr *OR* VCB addr)",
  132. " fo [addr] [1] Dump FileObject."
  133. "\n [1] Also dump associated Fcb/Ccb structures",
  134. " [2] dump SHARED_CACHE_MAP",
  135. " ",
  136. " d [addr] [...] Dump any tagged structure (any FS). Understands...",
  137. " VCB, CCB, fsDATA, IRPCONTEXT, IRPCONTEXTLITE,"
  138. "\n FCB / SCB (** see command ouput for further options)",
  139. " and (UDF ONLY) PCB, VMCB,",
  140. " LCB - options",
  141. " [1] dump associated FCB"
  142. " ",
  143. " For structures without options, second parameter is dump recurse level",
  144. " ",
  145. " db [addr] [recur] As !d, but just a straight DT of the structure based on node type",
  146. " ",
  147. " cdrawdirent [addr] [count] Dump a COUNT raw ISO9660 dirents starting at ADDR",
  148. " ",
  149. " udficbsc [addr] (UDFS only) Dump an ICB_CONTEXT",
  150. " udftag [addr] Dump out a UDF on disk format descriptor tag in detail (3/7.2)",
  151. " ud [addr] [...] Dump any on disc format UDF structure which has a descr.tag",
  152. " Currently: PVD,AVDP,VDP,PD,LVD,FSD,FID,FE",
  153. " [1] (FE) Dump allocation decriptors",
  154. " ",
  155. " vmcb [addr] Use on pre 1.10.2000 builds (vmcb not tagged) rather than !d ",
  156. " ",
  157. " tree [addr] (UDFS only) Dumps a summary of the F/Scb tree (names, ref counts) from",
  158. " the specified Scb down. If a Vcb address is specified will",
  159. " dump from root down",
  160. " ",
  161. " countclearbits [addr] [bytes] Count clear bits in mem range",
  162. " countdwords [addr] [dword] Count occurences of dword in mem range",
  163. " ",
  164. " ",
  165. " fshelp ...",
  166. 0
  167. };
  168. STATE FoFlags[] = {
  169. { FO_FILE_OPEN, FO_FILE_OPEN, "Open" },
  170. { FO_SYNCHRONOUS_IO, FO_SYNCHRONOUS_IO, "Synchronous" },
  171. { FO_ALERTABLE_IO, FO_ALERTABLE_IO, "Alertable" },
  172. { FO_NO_INTERMEDIATE_BUFFERING, FO_NO_INTERMEDIATE_BUFFERING, "NoIntermediateBuffering" },
  173. { FO_WRITE_THROUGH, FO_WRITE_THROUGH, "WriteThrough"},
  174. { FO_SEQUENTIAL_ONLY, FO_SEQUENTIAL_ONLY, "SequentialOnly"},
  175. { FO_CACHE_SUPPORTED, FO_CACHE_SUPPORTED, "CacheSupported"},
  176. { FO_NAMED_PIPE, FO_NAMED_PIPE, "NamedPipe"},
  177. { FO_STREAM_FILE, FO_STREAM_FILE, "StreamFile"},
  178. { FO_MAILSLOT, FO_MAILSLOT, "MailSlot"},
  179. { FO_GENERATE_AUDIT_ON_CLOSE, FO_GENERATE_AUDIT_ON_CLOSE, "AuditOnClose"},
  180. { FO_DIRECT_DEVICE_OPEN, FO_DIRECT_DEVICE_OPEN, "DirectDeviceOpen"},
  181. { FO_FILE_MODIFIED, FO_FILE_MODIFIED, "Modified"},
  182. { FO_FILE_SIZE_CHANGED, FO_FILE_SIZE_CHANGED, "SizeChanged"},
  183. { FO_CLEANUP_COMPLETE, FO_CLEANUP_COMPLETE, "CleanupComplete"},
  184. { FO_TEMPORARY_FILE, FO_TEMPORARY_FILE, "Temporary"},
  185. { FO_DELETE_ON_CLOSE, FO_DELETE_ON_CLOSE, "DeleteOnClose"},
  186. { FO_OPENED_CASE_SENSITIVE, FO_OPENED_CASE_SENSITIVE, "CaseSensitive"},
  187. { FO_HANDLE_CREATED, FO_HANDLE_CREATED, "HandleCreated"},
  188. { FO_FILE_FAST_IO_READ, FO_FILE_FAST_IO_READ, "FastIoRead"},
  189. { FO_RANDOM_ACCESS, FO_RANDOM_ACCESS, "RandomAccess"},
  190. { FO_FILE_OPEN_CANCELLED, FO_FILE_OPEN_CANCELLED, "OpenCancelled"},
  191. { FO_VOLUME_OPEN, FO_VOLUME_OPEN, "VolumeOpen"},
  192. { 0 }
  193. };
  194. //
  195. // FSRTL Common header flags
  196. //
  197. STATE HeaderFlags[] = {
  198. { FSRTL_FLAG_FILE_MODIFIED, FSRTL_FLAG_FILE_MODIFIED, "Modified"},
  199. { FSRTL_FLAG_FILE_LENGTH_CHANGED, FSRTL_FLAG_FILE_LENGTH_CHANGED, "LengthChanged"},
  200. { FSRTL_FLAG_LIMIT_MODIFIED_PAGES, FSRTL_FLAG_LIMIT_MODIFIED_PAGES, "LimitModPages"},
  201. { FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX, FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX, "ModWrAcqMainEx"},
  202. { FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH, FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH, "ModWrAcqMainSh"},
  203. { FSRTL_FLAG_USER_MAPPED_FILE, FSRTL_FLAG_USER_MAPPED_FILE, "UserMapped"},
  204. { FSRTL_FLAG_ADVANCED_HEADER, FSRTL_FLAG_ADVANCED_HEADER, "AdvancedHeader"},
  205. { FSRTL_FLAG_EOF_ADVANCE_ACTIVE, FSRTL_FLAG_EOF_ADVANCE_ACTIVE, "EofAdvanceActive"},
  206. { 0 }
  207. };
  208. STATE HeaderFlags2[] = {
  209. { FSRTL_FLAG2_DO_MODIFIED_WRITE, FSRTL_FLAG2_DO_MODIFIED_WRITE, "DoModWrite"},
  210. { FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS, "FilterContexts"},
  211. { FSRTL_FLAG2_PURGE_WHEN_MAPPED, FSRTL_FLAG2_PURGE_WHEN_MAPPED, "PurgeOnMap"},
  212. { 0 }
  213. };
  214. VOID
  215. DumpList(
  216. IN ULONG64 RemoteListEntryAddress,
  217. IN ELEMENT_DUMP_ROUTINE ProcessElementRoutine,
  218. IN ULONG OffsetToContainerStart,
  219. IN BOOLEAN ProcessThisEntry,
  220. IN ULONG Options
  221. )
  222. {
  223. LIST_ENTRY64 Entry;
  224. ULONG64 CurrentEntryRemoteAddress = 0;
  225. //
  226. // Read the first LIST_ENTRY structure
  227. //
  228. ROE( !ReadListEntry( RemoteListEntryAddress, &Entry));
  229. //
  230. // Scan through until we end up back at the 3start again.
  231. //
  232. while (CurrentEntryRemoteAddress != RemoteListEntryAddress) {
  233. if (ProcessThisEntry) {
  234. (ProcessElementRoutine)( CurrentEntryRemoteAddress - OffsetToContainerStart, Options);
  235. }
  236. else {
  237. ProcessThisEntry = TRUE;
  238. }
  239. CurrentEntryRemoteAddress = Entry.Flink;
  240. ROE( !ReadListEntry( CurrentEntryRemoteAddress, &Entry));
  241. }
  242. }
  243. /*
  244. * Dump structures
  245. */
  246. typedef BOOLEAN (WINAPI *PENUM_PROCESS_CALLBACK)(PVOID ProcessAddress, PVOID Process, PVOID ThreadAddress, PVOID Thread);
  247. typedef VOID (* ENUM_PROCESSES_FUNC)(PENUM_PROCESS_CALLBACK CallBack);
  248. VOID
  249. PrintState(STATE *ps, ULONG state)
  250. {
  251. ULONG ul = 0;
  252. if (NULL == ps) {
  253. dprintf(" << NULL flags supplied! >>\n");
  254. return;
  255. }
  256. while (ps->mask != 0)
  257. {
  258. ul |= ps->mask;
  259. if ((state & ps->mask) == ps->value)
  260. {
  261. dprintf(" %s", ps->pszname);
  262. }
  263. ps++;
  264. }
  265. state &= ~ul;
  266. if (state != 0)
  267. {
  268. dprintf(" +%lx!!", state);
  269. }
  270. dprintf("\n");
  271. }
  272. DUMP_ROUTINE( DumpVmcb);
  273. DUMP_ROUTINE( DumpFileObject);
  274. DUMP_ROUTINE( DumpAnyStruct);
  275. VOID
  276. PrintHelp (
  277. VOID
  278. );
  279. //
  280. // NULL dump function means just do DT with type.
  281. //
  282. NODE_TYPE_INFO_NEW NewNodeTypeCodes[] = {
  283. // RO UDFS
  284. { UDFS_NTC_DATA_HEADER, "UDFS DATA", "Udfs!UDF_DATA", DumpUdfData},
  285. { UDFS_NTC_VCB, "UDFS VCB", "Udfs!VCB", DumpUdfVcb},
  286. { UDFS_NTC_FCB_INDEX, "UDFS FCB (INDEX)", "Udfs!FCB", DumpUdfFcb},
  287. { UDFS_NTC_FCB_DATA, "UDFS FCB (DATA) ", "Udfs!FCB", DumpUdfFcb},
  288. { UDFS_NTC_FCB_NONPAGED, "UDFS FCB (nonpaged)", "Udfs!FCB_NONPAGED", NULL},
  289. { UDFS_NTC_CCB, "UDFS CCB", "Udfs!CCB", DumpUdfCcb},
  290. { UDFS_NTC_IRP_CONTEXT, "UDFS IRPCONTEXT", "Udfs!IRP_CONTEXT", DumpUdfIrpContext},
  291. { UDFS_NTC_IRP_CONTEXT_LITE, "UDFS IRPCONTEXT LITE", "Udfs!IRP_CONTEXT_LITE",DumpUdfIrpContextLite},
  292. { UDFS_NTC_LCB, "UDFS LCB", "Udfs!LCB", DumpUdfLcb},
  293. { UDFS_NTC_PCB, "UDFS PCB", "Udfs!PCB", DumpUdfPcb},
  294. { UDFS_NTC_VMCB, "UDFS VMCB", "Udfs!VMCB", DumpVmcb},
  295. #ifdef UDFS_RW_IN_BUILD
  296. // RW UDFS, same dump fn.
  297. { UDFSRW_NTC_DATA_HEADER, "UDFSRW DATA", "Udfs!UDF_DATA", DumpUdfData},
  298. { UDFSRW_NTC_IRP_CONTEXT, "UDFSRW IRPCONTEXT", "Udfs!IRP_CONTEXT", DumpUdfIrpContext},
  299. { UDFSRW_NTC_IRP_CONTEXT_LITE,"UDFSRW IRPCONTEXT LITE", "Udfs!IRP_CONTEXT_LITE",DumpUdfIrpContextLite},
  300. { UDFSRW_NTC_CCB, "UDFSRW CCB", "Udfs!CCB", DumpUdfCcb},
  301. { UDFSRW_NTC_LCB, "UDFSRW LCB", "Udfs!LCB", DumpUdfLcb},
  302. { UDFSRW_NTC_PCB, "UDFSRW PCB", "Udfs!PCB", DumpUdfPcb},
  303. { UDFSRW_NTC_VCB, "UDFSRW VCB", "Udfs!VCB", DumpUdfVcb},
  304. { UDFSRW_NTC_VMCB, "UDFSRW VMCB", "Udfs!VMCB", DumpVmcb},
  305. { UDFSRW_NTC_FCB, "UDFSRW FCB", "Udfs!FCB", DumpUdfFcb}, // TODO: Dump stream SCB list?
  306. { UDFSRW_NTC_FCB_NONPAGED, "UDFSRW FCB (nonpaged)", "Udfs!FCB_NONPAGED", DumpUdfFcb},
  307. // RW UDFS specific dump fn.
  308. { UDFSRW_NTC_SCB_INDEX, "UDFSRW SCB (INDEX)", "Udfs!SCB_INDEX_TYPE", DumpUdfScb},
  309. { UDFSRW_NTC_SCB_DATA, "UDFSRW SCB (DATA) ", "Udfs!SCB_DATA_TYPE", DumpUdfScb},
  310. { UDFSRW_NTC_SCB_NONPAGED, "UDFSRW SCB (nonpaged)", "Udfs!SCB_NONPAGED", NULL},
  311. #endif
  312. { FAT_NTC_VCB, "FAT VCB", "FastFat!VCB", DumpFatVcb},
  313. { FAT_NTC_FCB, "FAT FCB", "FastFat!FCB", DumpFatFcb},
  314. { FAT_NTC_DCB, "FAT DCB", "FastFat!FCB", DumpFatFcb},
  315. { FAT_NTC_CCB, "FAT CCB", "FastFat!CCB", DumpFatCcb},
  316. { FAT_NTC_ROOT_DCB, "FAT ROOT DCB", "FastFat!FCB", DumpFatFcb},
  317. { FAT_NTC_IRP_CONTEXT, "FAT IRP CONTEXT", "FastFat!IRP_CONTEXT", DumpFatIrpContext},
  318. { FAT_NTC_DATA_HEADER, "FAT DATA", "FastFat!FAT_DATA", NULL},
  319. { CDFS_NTC_DATA_HEADER, "CDFS DATA", "Cdfs!CD_DATA", NULL},
  320. { CDFS_NTC_VCB, "CDFS VCB", "Cdfs!VCB", DumpCdVcb},
  321. { CDFS_NTC_FCB_PATH_TABLE, "CDFS FCB (PATH TABLE)","Cdfs!FCB", DumpCdFcb},
  322. { CDFS_NTC_FCB_INDEX, "CDFS FCB (INDEX)", "Cdfs!FCB", DumpCdFcb},
  323. { CDFS_NTC_FCB_DATA, "CDFS FCB (DATA) ", "Cdfs!FCB", DumpCdFcb},
  324. { CDFS_NTC_FCB_NONPAGED, "CDFS FCB (nonpaged)", "Cdfs!FCB_NONPAGED", NULL},
  325. { CDFS_NTC_CCB, "CDFS CCB", "Cdfs!CCB", DumpCdCcb},
  326. { CDFS_NTC_IRP_CONTEXT, "CDFS IRPCONTEXT", "Cdfs!IRP_CONTEXT", DumpCdIrpContext},
  327. { CDFS_NTC_IRP_CONTEXT_LITE, "CDFS IRPCONTEXT (LITE)","Cdfs!IRP_CONTEXT_LITE",NULL},
  328. // { CACHE_NTC_SHARED_CACHE_MAP, "CC Shared Cache Map", "nt!SHARED_CACHE_MAP", NULL},
  329. { 0, "Undefined", NULL, NULL}
  330. };
  331. ULONG
  332. SearchTypeCodeIndex (
  333. IN USHORT TypeCode,
  334. IN NODE_TYPE_INFO_NEW TypeCodes[]
  335. )
  336. /*++
  337. Routine Description:
  338. Guess at a structure's type code
  339. Arguments:
  340. TypeCode - Type code from the data structure
  341. Return Value:
  342. None
  343. --*/
  344. {
  345. int i = 0;
  346. while (TypeCodes[i].TypeCode != 0 &&
  347. TypeCodes[i].TypeCode != TypeCode) {
  348. i++;
  349. }
  350. return i;
  351. }
  352. DUMP_ROUTINE( DumpFileObject)
  353. {
  354. ULONG Result;
  355. ULONG Flags, Offset;
  356. USHORT ObType;
  357. ULONG64 Adr, Scm;
  358. dprintf( "\nFileObject @ %I64X\n", Address );
  359. dprintf( "\n[ Options: 1 = dump FsContext & FsContext2, 2 = dump shared cache map ]\n");
  360. ReadM( &ObType, Address, sizeof( USHORT));
  361. if (ObType != IO_TYPE_FILE) {
  362. dprintf( "Invalid signature, probably not a file object" );
  363. return;
  364. }
  365. GetFieldValue( Address, "nt!FILE_OBJECT", "Flags", Flags);
  366. dprintf("\nFlags: ");
  367. PrintState( FoFlags, Flags);
  368. dprintf( "\n" );
  369. Dt( "nt!FILE_OBJECT", Address, 0, 0, NULL);
  370. dprintf( "\n" );
  371. GetFieldValue( Address, "nt!FILE_OBJECT", "SectionObjectPointer", Adr);
  372. if (Adr) {
  373. Dt( "nt!SECTION_OBJECT_POINTERS", Adr, 0, 0, NULL);
  374. }
  375. GetFieldValue( Adr, "nt!SECTION_OBJECT_POINTERS", "SharedCacheMap", Scm);
  376. if (Options & 2) {
  377. dprintf( "\n" );
  378. Dt( "nt!SHARED_CACHE_MAP", Scm, 0, 0, NULL);
  379. }
  380. if (Options & 1) {
  381. GetFieldValue( Address, "nt!FILE_OBJECT", "FsContext", Adr);
  382. if (Adr) {
  383. DumpAnyStruct( Adr, 0, NULL);
  384. }
  385. GetFieldValue( Address, "nt!FILE_OBJECT", "FsContext2", Adr);
  386. if (Adr) {
  387. DumpAnyStruct( Adr, 0, NULL);
  388. }
  389. }
  390. dprintf( "\n" );
  391. }
  392. DUMP_ROUTINE( DumpVmcb)
  393. {
  394. ULONG Result;
  395. ULONG Offset;
  396. dprintf( "\nVMCB @ %I64X\n", Address );
  397. Dt( "udfs!VMCB", Address, 0, 0, NULL);
  398. #ifdef UDFS_RW_IN_BUILD
  399. if (Options & 2) {
  400. USHORT NodeType;
  401. //
  402. // UDFS in Win2k had no nodetype field in the vmcb
  403. //
  404. if (!GetFieldValue( Address, "udfs!VMCB", "NodeTypeCode", NodeType)) {
  405. if (NodeType == UDFSRW_NTC_VMCB) {
  406. //
  407. // Summarize the dirty bitmap, if
  408. // these fields are present.
  409. //
  410. // TODO: Dump dirty blocks
  411. }
  412. }
  413. }
  414. #endif
  415. if (Options & 1) {
  416. dprintf("\n\nLbn->Vbn Mappings\n");
  417. ROE( GetFieldOffset( "udfs!VMCB", "LbnIndexed", &Offset));
  418. DumpLargeMcb( Address + Offset, Options, NULL);
  419. dprintf("\nVbn->Lbn Mappings\n");
  420. ROE( GetFieldOffset( "udfs!VMCB", "VbnIndexed", &Offset));
  421. DumpLargeMcb( Address + Offset, Options, NULL);
  422. }
  423. dprintf("\n");
  424. }
  425. VOID
  426. CountClearBits(
  427. IN UINT64 Address,
  428. IN ULONG Length
  429. )
  430. {
  431. UCHAR Buffer[2048];
  432. ULONG Result;
  433. ULONG ThisBytes;
  434. ULONG ClearBits = 0;
  435. ULONG CurrByte;
  436. // address, length
  437. dprintf("\nCounting clear bits in range 0x%p L 0x%x\n", Address, Length);
  438. while (Length) {
  439. ThisBytes = (Length > sizeof( Buffer)) ? sizeof( Buffer) : Length;
  440. if ( !ReadMemory( (DWORD_PTR)Address, Buffer, ThisBytes, &Result) ) {
  441. dprintf( "Unable to read %d bytes at %p\n", ThisBytes, Address);
  442. return;
  443. }
  444. for (CurrByte = 0; CurrByte < ThisBytes; ++CurrByte) {
  445. ClearBits += BitsClearTotal[ Buffer[CurrByte]];
  446. }
  447. Address += ThisBytes;
  448. Length -= ThisBytes;
  449. }
  450. dprintf("\n0x%x bits clear.\n\n", ClearBits);
  451. }
  452. VOID CountDwords(
  453. IN UINT64 Address,
  454. IN ULONG Length,
  455. IN ULONG Dword
  456. )
  457. {
  458. ULONG Buffer[512];
  459. ULONG Result;
  460. ULONG ThisBytes;
  461. ULONG Count = 0;
  462. ULONG CurrByte;
  463. // address, length
  464. dprintf("\nCounting ocurrences of DWORD 0x%x in range 0x%p L 0x%x\n", Dword, Address, Length);
  465. if (Length & 3) {
  466. dprintf("Length must be multiple of 4 bytes\n");
  467. return;
  468. }
  469. while (Length) {
  470. ThisBytes = (Length > sizeof( Buffer)) ? sizeof( Buffer) : Length;
  471. if ( !ReadMemory( (DWORD_PTR)Address, Buffer, ThisBytes, &Result) ) {
  472. dprintf( "Unable to read %d bytes at %p\n", ThisBytes, Address);
  473. return;
  474. }
  475. for (CurrByte = 0; CurrByte < (ThisBytes >> 2); ++CurrByte) {
  476. if (Buffer[ CurrByte] == Dword) {
  477. ++Count;
  478. }
  479. }
  480. Address += ThisBytes;
  481. Length -= ThisBytes;
  482. }
  483. dprintf("\n0x%x found.\n\n", Count);
  484. }
  485. DUMP_ROUTINE( DumpAnyStruct)
  486. /*++
  487. Routine Description:
  488. Dump a tagged structure, guessing based on node type code.
  489. Arguments:
  490. Address - Gives the address of the structure
  491. Return Value:
  492. None
  493. --*/
  494. {
  495. STRUCT_DUMP_ROUTINE Routine;
  496. ULONG TagAndSize, *TagAndSizePtr, Result, Error;
  497. LONG InfoIndex;
  498. RM( Address, TagAndSize, TagAndSizePtr, PULONG, Result );
  499. //
  500. // Find out what function should be used to dump the stucture (if we can)
  501. //
  502. InfoIndex = TypeCodeInfoIndex( (USHORT)(TagAndSize & 0xffff));
  503. Routine = NodeTypeDumpFunction( InfoIndex);
  504. if ( 0 == NewNodeTypeCodes[ InfoIndex].TypeCode) {
  505. dprintf( "\nNode type %0x%04x unknown.\n", (USHORT)TagAndSize & 0xffff);
  506. return;
  507. }
  508. dprintf("\n%s @ 0x%I64X\n\n", NewNodeTypeCodes[InfoIndex].Text, Address);
  509. if (Routine) {
  510. //
  511. // And call it...
  512. //
  513. (Routine)(Address, Options, &NewNodeTypeCodes[InfoIndex]);
  514. }
  515. else {
  516. //
  517. // No special routine - just DT it, treating first parameter following
  518. // address as level of recursion
  519. //
  520. Error = Dt( NewNodeTypeCodes[InfoIndex].TypeName, Address, Options, 0, NULL);
  521. if (Error) {
  522. dprintf("Error %d from debugger when dumping structure\n", Error);
  523. }
  524. }
  525. }
  526. DUMP_ROUTINE( DtAnyStruct)
  527. /*++
  528. Routine Description:
  529. Dump a tagged structure, guessing based on node type code.
  530. Arguments:
  531. Address - Gives the address of the structure
  532. Return Value:
  533. None
  534. --*/
  535. {
  536. ULONG TagAndSize, *TagAndSizePtr, Result;
  537. ULONG Error;
  538. LONG InfoIndex;
  539. RM( Address, TagAndSize, TagAndSizePtr, PULONG, Result );
  540. InfoIndex = TypeCodeInfoIndex( (USHORT)(TagAndSize & 0xffff));
  541. dprintf("\n%s @ 0x%X\n\n", NewNodeTypeCodes[InfoIndex].Text, Address);
  542. Error = Dt( NewNodeTypeCodes[InfoIndex].TypeName, Address, Options, 0, NULL);
  543. if (Error) {
  544. dprintf("Error %d\n", Error);
  545. }
  546. }
  547. //
  548. // Entry points, parameter parsers, etc. below
  549. //
  550. VOID
  551. ParseAndDump (
  552. IN PCHAR args,
  553. IN STRUCT_DUMP_ROUTINE DumpFunction,
  554. ULONG Processor,
  555. HANDLE hCurrentThread
  556. )
  557. /*++
  558. Routine Description:
  559. Parse command line arguments and dump an ntfs structure.
  560. Arguments:
  561. Args - String of arguments to parse.
  562. DumpFunction - Function to call with parsed arguments.
  563. Return Value:
  564. None
  565. --*/
  566. {
  567. CHAR StringStructToDump[1024]; // See other kd routines for size
  568. CHAR Dummy[24];
  569. LARGE_INTEGER StructToDump;
  570. LONG Options;
  571. //
  572. // If the caller specified an address then that's the item we dump
  573. //
  574. StructToDump.QuadPart = 0;
  575. Options = 0;
  576. StringStructToDump[0] = '\0';
  577. //dprintf("Args %s\n", args);
  578. sscanf(args,"%s %lx", StringStructToDump, &Options );
  579. //dprintf("GetExpr %s\n", StringStructToDump);
  580. if (!GetExpressionEx( StringStructToDump, &StructToDump.QuadPart, NULL)) {
  581. dprintf("GetExpression failed\n");
  582. return;
  583. }
  584. //dprintf("Getexpr returned %I64X\n", StructToDump.QuadPart);
  585. if (!StructToDump.QuadPart){
  586. dprintf("unable to get expression %s\n",StringStructToDump);
  587. return;
  588. }
  589. (*DumpFunction) ( StructToDump.QuadPart, Options, NULL );
  590. dprintf( "\n" );
  591. }
  592. VOID
  593. PrintHelp (
  594. VOID
  595. )
  596. {
  597. int i;
  598. for( i=0; Extensions[i]; i++ )
  599. dprintf( " %s\n", Extensions[i] );
  600. }
  601. DECLARE_API( fshelp )
  602. {
  603. UNREFERENCED_PARAMETER( args );
  604. UNREFERENCED_PARAMETER( dwProcessor );
  605. UNREFERENCED_PARAMETER( dwCurrentPc );
  606. UNREFERENCED_PARAMETER( hCurrentProcess );
  607. UNREFERENCED_PARAMETER( hCurrentThread );
  608. PrintHelp();
  609. }
  610. DECLARE_API( d)
  611. {
  612. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpAnyStruct, dwProcessor, hCurrentThread );
  613. }
  614. DECLARE_API( fo)
  615. {
  616. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpFileObject, dwProcessor, hCurrentThread );
  617. }
  618. DECLARE_API( vmcb)
  619. {
  620. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpVmcb, dwProcessor, hCurrentThread );
  621. }
  622. DECLARE_API( db )
  623. {
  624. UNREFERENCED_PARAMETER( dwCurrentPc );
  625. UNREFERENCED_PARAMETER( hCurrentProcess );
  626. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DtAnyStruct, dwProcessor, hCurrentThread );
  627. }
  628. DECLARE_API( countclearbits)
  629. {
  630. CHAR StringStructToDump[1024]; // See other kd routines for size
  631. UINT64 StructToDump;
  632. ULONG Length;
  633. //
  634. // If the caller specified an address then that's the item we dump
  635. //
  636. StructToDump = 0;
  637. Length = 0;
  638. StringStructToDump[0] = '\0';
  639. sscanf(args,"%s %lx", StringStructToDump, &Length );
  640. if (!GetExpressionEx( StringStructToDump, &StructToDump, NULL )) {
  641. dprintf("unable to get expression %s\n",StringStructToDump);
  642. return;
  643. }
  644. CountClearBits( StructToDump, Length);
  645. }
  646. DECLARE_API( countdwords)
  647. {
  648. CHAR StringStructToDump[1024]; // See other kd routines for size
  649. UINT64 StructToDump;
  650. ULONG Length;
  651. ULONG Dword;
  652. //
  653. // If the caller specified an address then that's the item we dump
  654. //
  655. StructToDump = 0;
  656. Length = 0;
  657. StringStructToDump[0] = '\0';
  658. sscanf(args,"%s %lx %lx", StringStructToDump, &Length, &Dword);
  659. if (!GetExpressionEx( StringStructToDump, &StructToDump, NULL)) {
  660. dprintf("unable to get expression %s\n",StringStructToDump);
  661. return;
  662. }
  663. CountDwords( StructToDump, Length, Dword);
  664. }