Leaked source code of windows server 2003
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.

1205 lines
35 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. STRING AString;
  68. ROE( GetFieldValue( StringAddress, "UNICODE_STRING", "Buffer", StringChars));
  69. ROE( GetFieldValue( StringAddress, "UNICODE_STRING", "Length", DisplayLength));
  70. ROE( GetFieldValue( StringAddress, "UNICODE_STRING", "MaximumLength", String.MaximumLength));
  71. if (DisplayLength > sizeof( Buffer)) {
  72. DisplayLength = sizeof(Buffer);
  73. }
  74. if (CrFirst) {
  75. dprintf("\n");
  76. }
  77. if (DisplayLength) {
  78. if (StringChars) {
  79. ReadM( Buffer, StringChars, DisplayLength);
  80. String.Length = DisplayLength;
  81. String.Buffer = Buffer;
  82. }
  83. else {
  84. AString.Buffer = "<<NULL buffer pointer>>";
  85. AString.Length = AString.MaximumLength = 23;
  86. Wide = FALSE;
  87. }
  88. }
  89. else {
  90. AString.Buffer = "<<empty>>";
  91. AString.Length = AString.MaximumLength = 9;
  92. Wide = FALSE;
  93. }
  94. if (Wide) {
  95. dprintf( "%s: (%03x/%03x) '%wZ'\n",
  96. Label, DisplayLength, String.MaximumLength,
  97. &String );
  98. }
  99. else {
  100. dprintf( "%s: (%03x/%03x) '%Z'\n",
  101. Label, DisplayLength, AString.MaximumLength,
  102. &AString );
  103. }
  104. }
  105. ULONG
  106. Dt( IN UCHAR *Type,
  107. IN ULONG64 Addr,
  108. IN ULONG Recur,
  109. IN ULONG FieldInfoCount,
  110. IN FIELD_INFO FieldInfo[]
  111. )
  112. {
  113. SYM_DUMP_PARAM Param;
  114. Param.size = sizeof( Param);
  115. Param.sName = Type;
  116. Param.Options = DBG_DUMP_RECUR_LEVEL(Recur);
  117. Param.addr = Addr;
  118. Param.listLink = NULL;
  119. Param.Context = NULL;
  120. Param.CallbackRoutine = NULL;
  121. Param.nFields = FieldInfoCount;
  122. Param.Fields = FieldInfo;
  123. return Ioctl( IG_DUMP_SYMBOL_INFO, &Param, Param.size);
  124. }
  125. //
  126. // The help strings printed out
  127. //
  128. static LPSTR Extensions[] = {
  129. "FAT/CDFS/UDFS Debugger Extension Commands, where...\n\n [FS] => CD/UDF/FAT\n -> in output denotes address of embedded structure\n",
  130. " [FS]mcb [addr] [1] Dump MCB",
  131. " [1] Dump out extent list",
  132. " [FS]vdo [addr] Volume device object (from direct addr *OR* VCB addr)",
  133. " fo [addr] [1] Dump FileObject."
  134. "\n [1] Also dump associated Fcb/Ccb structures",
  135. " [2] dump SHARED_CACHE_MAP",
  136. " ",
  137. " d [addr] [...] Dump any tagged structure (any FS). Understands...",
  138. " VCB, CCB, fsDATA, IRPCONTEXT, IRPCONTEXTLITE,"
  139. "\n FCB / SCB (** see command ouput for further options)",
  140. " and (UDF ONLY) PCB, VMCB,",
  141. " LCB - options",
  142. " [1] dump associated FCB"
  143. " ",
  144. " For structures without options, second parameter is dump recurse level",
  145. " ",
  146. " db [addr] [recur] As !d, but just a straight DT of the structure based on node type",
  147. " ",
  148. " cdrawdirent [addr] [count] Dump a COUNT raw ISO9660 dirents starting at ADDR",
  149. " ",
  150. " udficbsc [addr] (UDFS only) Dump an ICB_CONTEXT",
  151. " udftag [addr] Dump out a UDF on disk format descriptor tag in detail (3/7.2)",
  152. " ud [addr] [...] Dump any on disc format UDF structure which has a descr.tag",
  153. " Currently: PVD,AVDP,VDP,PD,LVD,FSD,FID,FE",
  154. " [1] (FE) Dump allocation decriptors",
  155. " ",
  156. " vmcb [addr] Use on pre 1.10.2000 builds (vmcb not tagged) rather than !d ",
  157. " ",
  158. " tree [addr] (UDFS only) Dumps a summary of the F/Scb tree (names, ref counts) from",
  159. " the specified Scb down. If a Vcb address is specified will",
  160. " dump from root down",
  161. " ",
  162. " udfsplay [addr] [opt] Where (addr) is SCB or LCB address. Dumps out the (ignore case) splay ",
  163. " tree below. Opt: 0 -> ignore case, 1 -> exact case, 2 -> short names",
  164. " ",
  165. " vols List all local file system volumes (Vcb/Vpb/Device/Label etc.)",
  166. " ",
  167. " countclearbits [addr] [bytes] Count clear bits in mem range",
  168. " countdwords [addr] [dword] Count occurences of dword in mem range",
  169. " ",
  170. " splay [addr] [linksoffsetinstructure] Dumps a list of structures in an RTL_SPLAY_TREE",
  171. " given pointer to RTL_SPLAY_LINKS and offset of links",
  172. " within containing structure",
  173. " ",
  174. " fshelp ...",
  175. 0
  176. };
  177. STATE FoFlags[] = {
  178. { FO_FILE_OPEN, FO_FILE_OPEN, "Open" },
  179. { FO_SYNCHRONOUS_IO, FO_SYNCHRONOUS_IO, "Synchronous" },
  180. { FO_ALERTABLE_IO, FO_ALERTABLE_IO, "Alertable" },
  181. { FO_NO_INTERMEDIATE_BUFFERING, FO_NO_INTERMEDIATE_BUFFERING, "NoIntermediateBuffering" },
  182. { FO_WRITE_THROUGH, FO_WRITE_THROUGH, "WriteThrough"},
  183. { FO_SEQUENTIAL_ONLY, FO_SEQUENTIAL_ONLY, "SequentialOnly"},
  184. { FO_CACHE_SUPPORTED, FO_CACHE_SUPPORTED, "CacheSupported"},
  185. { FO_NAMED_PIPE, FO_NAMED_PIPE, "NamedPipe"},
  186. { FO_STREAM_FILE, FO_STREAM_FILE, "StreamFile"},
  187. { FO_MAILSLOT, FO_MAILSLOT, "MailSlot"},
  188. { FO_GENERATE_AUDIT_ON_CLOSE, FO_GENERATE_AUDIT_ON_CLOSE, "AuditOnClose"},
  189. { FO_DIRECT_DEVICE_OPEN, FO_DIRECT_DEVICE_OPEN, "DirectDeviceOpen"},
  190. { FO_FILE_MODIFIED, FO_FILE_MODIFIED, "Modified"},
  191. { FO_FILE_SIZE_CHANGED, FO_FILE_SIZE_CHANGED, "SizeChanged"},
  192. { FO_CLEANUP_COMPLETE, FO_CLEANUP_COMPLETE, "CleanupComplete"},
  193. { FO_TEMPORARY_FILE, FO_TEMPORARY_FILE, "Temporary"},
  194. { FO_DELETE_ON_CLOSE, FO_DELETE_ON_CLOSE, "DeleteOnClose"},
  195. { FO_OPENED_CASE_SENSITIVE, FO_OPENED_CASE_SENSITIVE, "CaseSensitive"},
  196. { FO_HANDLE_CREATED, FO_HANDLE_CREATED, "HandleCreated"},
  197. { FO_FILE_FAST_IO_READ, FO_FILE_FAST_IO_READ, "FastIoRead"},
  198. { FO_RANDOM_ACCESS, FO_RANDOM_ACCESS, "RandomAccess"},
  199. { FO_FILE_OPEN_CANCELLED, FO_FILE_OPEN_CANCELLED, "OpenCancelled"},
  200. { FO_VOLUME_OPEN, FO_VOLUME_OPEN, "VolumeOpen"},
  201. { 0 }
  202. };
  203. //
  204. // FSRTL Common header flags
  205. //
  206. STATE HeaderFlags[] = {
  207. { FSRTL_FLAG_FILE_MODIFIED, FSRTL_FLAG_FILE_MODIFIED, "Modified"},
  208. { FSRTL_FLAG_FILE_LENGTH_CHANGED, FSRTL_FLAG_FILE_LENGTH_CHANGED, "LengthChanged"},
  209. { FSRTL_FLAG_LIMIT_MODIFIED_PAGES, FSRTL_FLAG_LIMIT_MODIFIED_PAGES, "LimitModPages"},
  210. { FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX, FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX, "ModWrAcqMainEx"},
  211. { FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH, FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH, "ModWrAcqMainSh"},
  212. { FSRTL_FLAG_USER_MAPPED_FILE, FSRTL_FLAG_USER_MAPPED_FILE, "UserMapped"},
  213. { FSRTL_FLAG_ADVANCED_HEADER, FSRTL_FLAG_ADVANCED_HEADER, "AdvancedHeader"},
  214. { FSRTL_FLAG_EOF_ADVANCE_ACTIVE, FSRTL_FLAG_EOF_ADVANCE_ACTIVE, "EofAdvanceActive"},
  215. { 0 }
  216. };
  217. STATE HeaderFlags2[] = {
  218. { FSRTL_FLAG2_DO_MODIFIED_WRITE, FSRTL_FLAG2_DO_MODIFIED_WRITE, "DoModWrite"},
  219. { FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS, "FilterContexts"},
  220. { FSRTL_FLAG2_PURGE_WHEN_MAPPED, FSRTL_FLAG2_PURGE_WHEN_MAPPED, "PurgeOnMap"},
  221. { 0 }
  222. };
  223. ULONG DumpRtlSplay(
  224. IN ULONG64 RemoteAddress,
  225. IN ELEMENT_DUMP_ROUTINE ProcessElementRoutine,
  226. IN ULONG OffsetToContainerStart,
  227. IN ULONG Options
  228. )
  229. {
  230. ULONG64 Left,Right,Parent;
  231. ULONG E;
  232. if (0 == RemoteAddress) {
  233. return 0;
  234. }
  235. if ((*ExtensionApis.lpCheckControlCRoutine)()) {
  236. dprintf("CTRL+C - aborting\n");
  237. // AV, no easy way to bail from the recursion.
  238. *((PULONG)0) = 0;
  239. }
  240. if (E = GetFieldValue( RemoteAddress,
  241. "nt!_RTL_SPLAY_LINKS",
  242. "LeftChild",
  243. Left)) {
  244. dprintf("Error %d reading LEFT child link from node at %8I64x\n", E, RemoteAddress - OffsetToContainerStart);
  245. return E;
  246. }
  247. if (E = GetFieldValue( RemoteAddress,
  248. "nt!_RTL_SPLAY_LINKS",
  249. "RightChild",
  250. Right)) {
  251. dprintf("Error %d reading RIGHT child link from node at %8I64x\n", E, RemoteAddress - OffsetToContainerStart);
  252. return E;
  253. }
  254. //
  255. // Recurse down the left subtree
  256. //
  257. if (DumpRtlSplay( Left, ProcessElementRoutine, OffsetToContainerStart, Options)) {
  258. dprintf("Error ocurred while processing node through LEFT link from node %I64x\n", RemoteAddress - OffsetToContainerStart);
  259. }
  260. //
  261. // Dump this element
  262. //
  263. (ProcessElementRoutine)(RemoteAddress - OffsetToContainerStart, Options);
  264. //
  265. // Recurse down the right subtree
  266. //
  267. if (DumpRtlSplay( Right, ProcessElementRoutine, OffsetToContainerStart, Options)) {
  268. dprintf("Error ocurred while processing node through RIGHT link from node %I64x\n", RemoteAddress - OffsetToContainerStart);
  269. }
  270. return 0;
  271. }
  272. VOID
  273. DumpSplayNodeSimple(
  274. IN ULONG64 RemoteAddress,
  275. IN LONG Options
  276. )
  277. {
  278. dprintf("%I64x\n", RemoteAddress);
  279. }
  280. DUMP_ROUTINE( SimpleSplay)
  281. {
  282. DumpRtlSplay( Address,
  283. DumpSplayNodeSimple,
  284. Options,
  285. 0);
  286. }
  287. VOID
  288. DumpList(
  289. IN ULONG64 RemoteListEntryAddress,
  290. IN ELEMENT_DUMP_ROUTINE ProcessElementRoutine,
  291. IN ULONG OffsetToContainerStart,
  292. IN BOOLEAN ProcessThisEntry,
  293. IN ULONG Options
  294. )
  295. {
  296. LIST_ENTRY64 Entry;
  297. ULONG64 CurrentEntryRemoteAddress = 0;
  298. //
  299. // Read the first LIST_ENTRY structure
  300. //
  301. ROE( !ReadListEntry( RemoteListEntryAddress, &Entry));
  302. //
  303. // Scan through until we end up back at the 3start again.
  304. //
  305. while (CurrentEntryRemoteAddress != RemoteListEntryAddress) {
  306. if (ProcessThisEntry) {
  307. (ProcessElementRoutine)( CurrentEntryRemoteAddress - OffsetToContainerStart, Options);
  308. }
  309. else {
  310. ProcessThisEntry = TRUE;
  311. }
  312. CurrentEntryRemoteAddress = Entry.Flink;
  313. ROE( !ReadListEntry( CurrentEntryRemoteAddress, &Entry));
  314. }
  315. }
  316. /*
  317. * Dump structures
  318. */
  319. typedef BOOLEAN (WINAPI *PENUM_PROCESS_CALLBACK)(PVOID ProcessAddress, PVOID Process, PVOID ThreadAddress, PVOID Thread);
  320. typedef VOID (* ENUM_PROCESSES_FUNC)(PENUM_PROCESS_CALLBACK CallBack);
  321. VOID
  322. PrintState(STATE *ps, ULONG state)
  323. {
  324. ULONG ul = 0;
  325. if (NULL == ps) {
  326. dprintf(" << NULL flags supplied! >>\n");
  327. return;
  328. }
  329. while (ps->mask != 0)
  330. {
  331. ul |= ps->mask;
  332. if ((state & ps->mask) == ps->value)
  333. {
  334. dprintf(" %s", ps->pszname);
  335. }
  336. ps++;
  337. }
  338. state &= ~ul;
  339. if (state != 0)
  340. {
  341. dprintf(" +%lx!!", state);
  342. }
  343. dprintf("\n");
  344. }
  345. DUMP_ROUTINE( DumpVmcb);
  346. DUMP_ROUTINE( DumpFileObject);
  347. DUMP_ROUTINE( DumpAnyStruct);
  348. VOID
  349. PrintHelp (
  350. VOID
  351. );
  352. //
  353. // NULL dump function means just do DT with type.
  354. //
  355. NODE_TYPE_INFO_NEW NewNodeTypeCodes[] = {
  356. // RO UDFS
  357. { UDFS_NTC_DATA_HEADER, "UDFS DATA", "Udfs!UDF_DATA", DumpUdfData},
  358. { UDFS_NTC_VCB, "UDFS VCB", "Udfs!VCB", DumpUdfVcb},
  359. { UDFS_NTC_FCB_INDEX, "UDFS FCB (INDEX)", "Udfs!FCB", DumpUdfFcb},
  360. { UDFS_NTC_FCB_DATA, "UDFS FCB (DATA) ", "Udfs!FCB", DumpUdfFcb},
  361. { UDFS_NTC_FCB_NONPAGED, "UDFS FCB (nonpaged)", "Udfs!FCB_NONPAGED", NULL},
  362. { UDFS_NTC_CCB, "UDFS CCB", "Udfs!CCB", DumpUdfCcb},
  363. { UDFS_NTC_IRP_CONTEXT, "UDFS IRPCONTEXT", "Udfs!IRP_CONTEXT", DumpUdfIrpContext},
  364. { UDFS_NTC_IRP_CONTEXT_LITE, "UDFS IRPCONTEXT LITE", "Udfs!IRP_CONTEXT_LITE",DumpUdfIrpContextLite},
  365. { UDFS_NTC_LCB, "UDFS LCB", "Udfs!LCB", DumpUdfLcb},
  366. { UDFS_NTC_PCB, "UDFS PCB", "Udfs!PCB", DumpUdfPcb},
  367. { UDFS_NTC_VMCB, "UDFS VMCB", "Udfs!VMCB", DumpVmcb},
  368. #ifdef UDFS_RW_IN_BUILD
  369. // RW UDFS, same dump fn.
  370. { UDFSRW_NTC_DATA_HEADER, "UDFSRW DATA", "Udfs!UDF_DATA", DumpUdfData},
  371. { UDFSRW_NTC_IRP_CONTEXT, "UDFSRW IRPCONTEXT", "Udfs!IRP_CONTEXT", DumpUdfIrpContext},
  372. { UDFSRW_NTC_IRP_CONTEXT_LITE,"UDFSRW IRPCONTEXT LITE", "Udfs!IRP_CONTEXT_LITE",DumpUdfIrpContextLite},
  373. { UDFSRW_NTC_CCB, "UDFSRW CCB", "Udfs!CCB", DumpUdfCcb},
  374. { UDFSRW_NTC_LCB, "UDFSRW LCB", "Udfs!LCB", DumpUdfLcb},
  375. { UDFSRW_NTC_PCB, "UDFSRW PCB", "Udfs!PCB", DumpUdfPcb},
  376. { UDFSRW_NTC_VCB, "UDFSRW VCB", "Udfs!VCB", DumpUdfVcb},
  377. { UDFSRW_NTC_VMCB, "UDFSRW VMCB", "Udfs!VMCB", DumpVmcb},
  378. { UDFSRW_NTC_FCB, "UDFSRW FCB", "Udfs!FCB", DumpUdfFcb}, // TODO: Dump stream SCB list?
  379. { UDFSRW_NTC_FCB_NONPAGED, "UDFSRW FCB (nonpaged)", "Udfs!FCB_NONPAGED", DumpUdfFcb},
  380. // RW UDFS specific dump fn.
  381. { UDFSRW_NTC_SCB_INDEX, "UDFSRW SCB (INDEX)", "Udfs!SCB_INDEX_TYPE", DumpUdfScb},
  382. { UDFSRW_NTC_SCB_DATA, "UDFSRW SCB (DATA) ", "Udfs!SCB_DATA_TYPE", DumpUdfScb},
  383. { UDFSRW_NTC_SCB_NONPAGED, "UDFSRW SCB (nonpaged)", "Udfs!SCB_NONPAGED", NULL},
  384. #endif
  385. { FAT_NTC_VCB, "FAT VCB", "FastFat!VCB", DumpFatVcb},
  386. { FAT_NTC_FCB, "FAT FCB", "FastFat!FCB", DumpFatFcb},
  387. { FAT_NTC_DCB, "FAT DCB", "FastFat!FCB", DumpFatFcb},
  388. { FAT_NTC_CCB, "FAT CCB", "FastFat!CCB", DumpFatCcb},
  389. { FAT_NTC_ROOT_DCB, "FAT ROOT DCB", "FastFat!FCB", DumpFatFcb},
  390. { FAT_NTC_IRP_CONTEXT, "FAT IRP CONTEXT", "FastFat!IRP_CONTEXT", DumpFatIrpContext},
  391. { FAT_NTC_DATA_HEADER, "FAT DATA", "FastFat!FAT_DATA", NULL},
  392. { CDFS_NTC_DATA_HEADER, "CDFS DATA", "Cdfs!CD_DATA", NULL},
  393. { CDFS_NTC_VCB, "CDFS VCB", "Cdfs!VCB", DumpCdVcb},
  394. { CDFS_NTC_FCB_PATH_TABLE, "CDFS FCB (PATH TABLE)","Cdfs!FCB", DumpCdFcb},
  395. { CDFS_NTC_FCB_INDEX, "CDFS FCB (INDEX)", "Cdfs!FCB", DumpCdFcb},
  396. { CDFS_NTC_FCB_DATA, "CDFS FCB (DATA) ", "Cdfs!FCB", DumpCdFcb},
  397. { CDFS_NTC_FCB_NONPAGED, "CDFS FCB (nonpaged)", "Cdfs!FCB_NONPAGED", NULL},
  398. { CDFS_NTC_CCB, "CDFS CCB", "Cdfs!CCB", DumpCdCcb},
  399. { CDFS_NTC_IRP_CONTEXT, "CDFS IRPCONTEXT", "Cdfs!IRP_CONTEXT", DumpCdIrpContext},
  400. { CDFS_NTC_IRP_CONTEXT_LITE, "CDFS IRPCONTEXT (LITE)","Cdfs!IRP_CONTEXT_LITE",NULL},
  401. // { CACHE_NTC_SHARED_CACHE_MAP, "CC Shared Cache Map", "nt!SHARED_CACHE_MAP", NULL},
  402. { 0, "Undefined", NULL, NULL}
  403. };
  404. ULONG
  405. SearchTypeCodeIndex (
  406. IN USHORT TypeCode,
  407. IN NODE_TYPE_INFO_NEW TypeCodes[]
  408. )
  409. /*++
  410. Routine Description:
  411. Guess at a structure's type code
  412. Arguments:
  413. TypeCode - Type code from the data structure
  414. Return Value:
  415. None
  416. --*/
  417. {
  418. int i = 0;
  419. while (TypeCodes[i].TypeCode != 0 &&
  420. TypeCodes[i].TypeCode != TypeCode) {
  421. i++;
  422. }
  423. return i;
  424. }
  425. DUMP_ROUTINE( DumpFileObject)
  426. {
  427. ULONG Result;
  428. ULONG Flags, Offset;
  429. USHORT ObType;
  430. ULONG64 Adr, Scm;
  431. dprintf( "\nFileObject @ %I64X\n", Address );
  432. dprintf( "\n[ Options: 1 = dump FsContext & FsContext2, 2 = dump shared cache map ]\n");
  433. ReadM( &ObType, Address, sizeof( USHORT));
  434. if (ObType != IO_TYPE_FILE) {
  435. dprintf( "Invalid signature, probably not a file object" );
  436. return;
  437. }
  438. GetFieldValue( Address, "nt!FILE_OBJECT", "Flags", Flags);
  439. dprintf("\nFlags: ");
  440. PrintState( FoFlags, Flags);
  441. dprintf( "\n" );
  442. Dt( "nt!FILE_OBJECT", Address, 0, 0, NULL);
  443. dprintf( "\n" );
  444. GetFieldValue( Address, "nt!FILE_OBJECT", "SectionObjectPointer", Adr);
  445. if (Adr) {
  446. Dt( "nt!SECTION_OBJECT_POINTERS", Adr, 0, 0, NULL);
  447. }
  448. GetFieldValue( Adr, "nt!SECTION_OBJECT_POINTERS", "SharedCacheMap", Scm);
  449. if (Options & 2) {
  450. dprintf( "\n" );
  451. Dt( "nt!SHARED_CACHE_MAP", Scm, 0, 0, NULL);
  452. }
  453. if (Options & 1) {
  454. GetFieldValue( Address, "nt!FILE_OBJECT", "FsContext", Adr);
  455. if (Adr) {
  456. DumpAnyStruct( Adr, 0, NULL);
  457. }
  458. GetFieldValue( Address, "nt!FILE_OBJECT", "FsContext2", Adr);
  459. if (Adr) {
  460. DumpAnyStruct( Adr, 0, NULL);
  461. }
  462. }
  463. dprintf( "\n" );
  464. }
  465. DUMP_ROUTINE( DumpVmcb)
  466. {
  467. ULONG Result;
  468. ULONG Offset;
  469. dprintf( "\nVMCB @ %I64X\n", Address );
  470. Dt( "udfs!VMCB", Address, 0, 0, NULL);
  471. #ifdef UDFS_RW_IN_BUILD
  472. if (Options & 2) {
  473. USHORT NodeType;
  474. //
  475. // UDFS in Win2k had no nodetype field in the vmcb
  476. //
  477. if (!GetFieldValue( Address, "udfs!VMCB", "NodeTypeCode", NodeType)) {
  478. if (NodeType == UDFSRW_NTC_VMCB) {
  479. //
  480. // Summarize the dirty bitmap, if
  481. // these fields are present.
  482. //
  483. // TODO: Dump dirty blocks
  484. }
  485. }
  486. }
  487. #endif
  488. if (Options & 1) {
  489. dprintf("\n\nLbn->Vbn Mappings\n");
  490. ROE( GetFieldOffset( "udfs!VMCB", "LbnIndexed", &Offset));
  491. DumpLargeMcb( Address + Offset, Options, NULL);
  492. dprintf("\nVbn->Lbn Mappings\n");
  493. ROE( GetFieldOffset( "udfs!VMCB", "VbnIndexed", &Offset));
  494. DumpLargeMcb( Address + Offset, Options, NULL);
  495. }
  496. dprintf("\n");
  497. }
  498. VOID
  499. CountClearBits(
  500. IN UINT64 Address,
  501. IN ULONG Length
  502. )
  503. {
  504. UCHAR Buffer[2048];
  505. ULONG Result;
  506. ULONG ThisBytes;
  507. ULONG ClearBits = 0;
  508. ULONG CurrByte;
  509. // address, length
  510. dprintf("\nCounting clear bits in range 0x%p L 0x%x\n", Address, Length);
  511. while (Length) {
  512. ThisBytes = (Length > sizeof( Buffer)) ? sizeof( Buffer) : Length;
  513. if ( !ReadMemory( (DWORD_PTR)Address, Buffer, ThisBytes, &Result) ) {
  514. dprintf( "Unable to read %d bytes at %p\n", ThisBytes, Address);
  515. return;
  516. }
  517. for (CurrByte = 0; CurrByte < ThisBytes; ++CurrByte) {
  518. ClearBits += BitsClearTotal[ Buffer[CurrByte]];
  519. }
  520. Address += ThisBytes;
  521. Length -= ThisBytes;
  522. }
  523. dprintf("\n0x%x bits clear.\n\n", ClearBits);
  524. }
  525. VOID CountDwords(
  526. IN UINT64 Address,
  527. IN ULONG Length,
  528. IN ULONG Dword
  529. )
  530. {
  531. ULONG Buffer[512];
  532. ULONG Result;
  533. ULONG ThisBytes;
  534. ULONG Count = 0;
  535. ULONG CurrByte;
  536. // address, length
  537. dprintf("\nCounting ocurrences of DWORD 0x%x in range 0x%p L 0x%x\n", Dword, Address, Length);
  538. if (Length & 3) {
  539. dprintf("Length must be multiple of 4 bytes\n");
  540. return;
  541. }
  542. while (Length) {
  543. ThisBytes = (Length > sizeof( Buffer)) ? sizeof( Buffer) : Length;
  544. if ( !ReadMemory( (DWORD_PTR)Address, Buffer, ThisBytes, &Result) ) {
  545. dprintf( "Unable to read %d bytes at %p\n", ThisBytes, Address);
  546. return;
  547. }
  548. for (CurrByte = 0; CurrByte < (ThisBytes >> 2); ++CurrByte) {
  549. if (Buffer[ CurrByte] == Dword) {
  550. ++Count;
  551. }
  552. }
  553. Address += ThisBytes;
  554. Length -= ThisBytes;
  555. }
  556. dprintf("\n0x%x found.\n\n", Count);
  557. }
  558. DUMP_ROUTINE( DumpAnyStruct)
  559. /*++
  560. Routine Description:
  561. Dump a tagged structure, guessing based on node type code.
  562. Arguments:
  563. Address - Gives the address of the structure
  564. Return Value:
  565. None
  566. --*/
  567. {
  568. STRUCT_DUMP_ROUTINE Routine;
  569. ULONG TagAndSize, *TagAndSizePtr, Result, Error;
  570. LONG InfoIndex;
  571. RM( Address, TagAndSize, TagAndSizePtr, PULONG, Result );
  572. //
  573. // Find out what function should be used to dump the stucture (if we can)
  574. //
  575. InfoIndex = TypeCodeInfoIndex( (USHORT)(TagAndSize & 0xffff));
  576. Routine = NodeTypeDumpFunction( InfoIndex);
  577. if ( 0 == NewNodeTypeCodes[ InfoIndex].TypeCode) {
  578. dprintf( "\nNode type %0x%04x unknown.\n", (USHORT)TagAndSize & 0xffff);
  579. return;
  580. }
  581. dprintf("\n%s @ 0x%I64X\n\n", NewNodeTypeCodes[InfoIndex].Text, Address);
  582. if (Routine) {
  583. //
  584. // And call it...
  585. //
  586. (Routine)(Address, Options, &NewNodeTypeCodes[InfoIndex]);
  587. }
  588. else {
  589. //
  590. // No special routine - just DT it, treating first parameter following
  591. // address as level of recursion
  592. //
  593. Error = Dt( NewNodeTypeCodes[InfoIndex].TypeName, Address, Options, 0, NULL);
  594. if (Error) {
  595. dprintf("Error %d from debugger when dumping structure\n", Error);
  596. }
  597. }
  598. }
  599. DUMP_ROUTINE( DtAnyStruct)
  600. /*++
  601. Routine Description:
  602. Dump a tagged structure, guessing based on node type code.
  603. Arguments:
  604. Address - Gives the address of the structure
  605. Return Value:
  606. None
  607. --*/
  608. {
  609. ULONG TagAndSize, *TagAndSizePtr, Result;
  610. ULONG Error;
  611. LONG InfoIndex;
  612. RM( Address, TagAndSize, TagAndSizePtr, PULONG, Result );
  613. InfoIndex = TypeCodeInfoIndex( (USHORT)(TagAndSize & 0xffff));
  614. dprintf("\n%s @ 0x%X\n\n", NewNodeTypeCodes[InfoIndex].Text, Address);
  615. Error = Dt( NewNodeTypeCodes[InfoIndex].TypeName, Address, Options, 0, NULL);
  616. if (Error) {
  617. dprintf("Error %d\n", Error);
  618. }
  619. }
  620. //
  621. // Entry points, parameter parsers, etc. below
  622. //
  623. VOID
  624. ParseAndDump (
  625. IN PCHAR args,
  626. IN STRUCT_DUMP_ROUTINE DumpFunction,
  627. ULONG Processor,
  628. HANDLE hCurrentThread
  629. )
  630. /*++
  631. Routine Description:
  632. Parse command line arguments and dump an ntfs structure.
  633. Arguments:
  634. Args - String of arguments to parse.
  635. DumpFunction - Function to call with parsed arguments.
  636. Return Value:
  637. None
  638. --*/
  639. {
  640. CHAR StringStructToDump[1024]; // See other kd routines for size
  641. CHAR Dummy[24];
  642. LARGE_INTEGER StructToDump;
  643. LONG Options;
  644. LONG ret;
  645. //
  646. // If the caller specified an address then that's the item we dump
  647. //
  648. StructToDump.QuadPart = 0;
  649. Options = 0;
  650. StringStructToDump[0] = '\0';
  651. //dprintf("Args %s\n", args);
  652. ret = sscanf( args,"%s %lx", StringStructToDump, &Options );
  653. //dprintf("GetExpr %s\n", StringStructToDump);
  654. if (!GetExpressionEx( StringStructToDump, &StructToDump.QuadPart, NULL)) {
  655. dprintf("GetExpression failed\n");
  656. return;
  657. }
  658. //dprintf("Getexpr returned %I64X\n", StructToDump.QuadPart);
  659. if (!StructToDump.QuadPart){
  660. dprintf("unable to get expression %s\n",StringStructToDump);
  661. return;
  662. }
  663. (*DumpFunction) ( StructToDump.QuadPart, Options, NULL );
  664. dprintf( "\n" );
  665. }
  666. VOID
  667. PrintHelp (
  668. VOID
  669. )
  670. {
  671. int i;
  672. for( i=0; Extensions[i]; i++ )
  673. dprintf( " %s\n", Extensions[i] );
  674. }
  675. DECLARE_API( fshelp )
  676. {
  677. UNREFERENCED_PARAMETER( args );
  678. UNREFERENCED_PARAMETER( dwProcessor );
  679. UNREFERENCED_PARAMETER( dwCurrentPc );
  680. UNREFERENCED_PARAMETER( hCurrentProcess );
  681. UNREFERENCED_PARAMETER( hCurrentThread );
  682. PrintHelp();
  683. }
  684. DECLARE_API( d)
  685. {
  686. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpAnyStruct, dwProcessor, hCurrentThread );
  687. }
  688. DECLARE_API( fo)
  689. {
  690. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpFileObject, dwProcessor, hCurrentThread );
  691. }
  692. DECLARE_API( vmcb)
  693. {
  694. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpVmcb, dwProcessor, hCurrentThread );
  695. }
  696. DECLARE_API( db )
  697. {
  698. UNREFERENCED_PARAMETER( dwCurrentPc );
  699. UNREFERENCED_PARAMETER( hCurrentProcess );
  700. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DtAnyStruct, dwProcessor, hCurrentThread );
  701. }
  702. UCHAR *FsDataNames[] = { "Udfs!UdfData", "Cdfs!CdData", "Fastfat!FatData", "Ntfs!NtfsData", "" };
  703. UCHAR *FsDataTypes[] = { "udfs!UDF_DATA", "cdfs!CD_DATA", "fastfat!FAT_DATA", "ntfs!NTFS_DATA", "" };
  704. DECLARE_API( vols )
  705. {
  706. ULONG Result;
  707. UINT64 Addr;
  708. UINT64 CurrListEntry, CurrVcb, RealDo, VolDo, Vpb, VpbOnRealDo, QueueHead;
  709. USHORT LabelLen;
  710. ULONG LinksOffset, LabelOffset;
  711. ULONG CurrName = 0, FsNameLen;
  712. UCHAR FsName[10];
  713. UCHAR FsVcbName[10];
  714. WCHAR VolLabel[32];
  715. UNICODE_STRING Label;
  716. BOOLEAN Itanic = (BOOLEAN)IsPtr64();
  717. UNREFERENCED_PARAMETER( dwCurrentPc );
  718. UNREFERENCED_PARAMETER( hCurrentProcess );
  719. if (Itanic) {
  720. dprintf("\nVCB VolDev VPB RealDev On Device? / Label\n");
  721. }
  722. else {
  723. dprintf("\nVCB VolDev VPB RealDev On Device? / Label\n");
  724. }
  725. while ( *FsDataNames[CurrName] != 0) {
  726. if (!GetExpressionEx( FsDataNames[CurrName], &Addr, NULL ) ||
  727. (0 == Addr)) {
  728. dprintf("\n<< Failed to lookup '%s' - skipping FS >>\n", FsDataNames[CurrName]);
  729. }
  730. else {
  731. ROE( GetFieldValue( Addr, FsDataTypes[CurrName], "VcbQueue.Flink", CurrListEntry));
  732. ROE( GetFieldOffset( FsDataTypes[CurrName], "VcbQueue", &LinksOffset));
  733. QueueHead = Addr + LinksOffset;
  734. if (CurrListEntry != QueueHead) {
  735. FsNameLen = (ULONG)(strchr( FsDataNames[CurrName], '!') - FsDataNames[CurrName]);
  736. strncpy( FsName, FsDataNames[CurrName], FsNameLen);
  737. FsName[FsNameLen] = 0;
  738. sprintf( FsVcbName, "%s!VCB", FsName);
  739. ROE( GetFieldOffset( FsVcbName, "VcbLinks", &LinksOffset));
  740. ROE( GetFieldOffset( "nt!VPB", "VolumeLabel", &LabelOffset));
  741. dprintf("\n<< %s >>\n\n", FsName);
  742. while (CurrListEntry != QueueHead) {
  743. CurrVcb = CurrListEntry - LinksOffset;
  744. ROE( GetFieldValue( CurrVcb, FsVcbName, "Vpb", Vpb));
  745. if (0 != Vpb) {
  746. ROE( GetFieldValue( Vpb, "nt!VPB", "DeviceObject", VolDo));
  747. ROE( GetFieldValue( Vpb, "nt!VPB", "RealDevice", RealDo));
  748. ROE( GetFieldValue( Vpb, "nt!VPB", "VolumeLabelLength", LabelLen));
  749. ROE( GetFieldValue( RealDo, "nt!DEVICE_OBJECT", "Vpb", VpbOnRealDo));
  750. if (LabelLen > sizeof( VolLabel)) {
  751. dprintf("Warning - VPB label length is > max allowed\n");
  752. Label.Buffer = NULL;
  753. Label.Length = Label.MaximumLength = 0;
  754. }
  755. else {
  756. ReadM( VolLabel, (ULONG)(Vpb + LabelOffset), LabelLen);
  757. Label.Buffer = VolLabel;
  758. Label.Length = Label.MaximumLength = LabelLen;
  759. }
  760. }
  761. else {
  762. dprintf("Null VPB! ");
  763. Vpb = VolDo = RealDo = VpbOnRealDo = 0;
  764. Label.Length = 0;
  765. }
  766. if (Itanic) {
  767. dprintf("%I64x %I64x %I64x %I64x %s '%wZ'\n", CurrVcb, VolDo, Vpb, RealDo,
  768. (Vpb == VpbOnRealDo) ? "YES" : "NO ", &Label);
  769. }
  770. else {
  771. dprintf("%8x %8x %8x %8x %s '%wZ'\n", (ULONG)CurrVcb, (ULONG)VolDo, (ULONG)Vpb, (ULONG)
  772. RealDo, (Vpb == VpbOnRealDo) ? "YES" : "NO ", &Label);
  773. }
  774. ROE( GetFieldValue( CurrListEntry, "nt!LIST_ENTRY", "Flink", CurrListEntry));
  775. }
  776. }
  777. }
  778. CurrName += 1;
  779. }
  780. }
  781. DECLARE_API( countclearbits)
  782. {
  783. CHAR StringStructToDump[1024]; // See other kd routines for size
  784. UINT64 StructToDump;
  785. ULONG Length;
  786. LONG ret;
  787. //
  788. // If the caller specified an address then that's the item we dump
  789. //
  790. StructToDump = 0;
  791. Length = 0;
  792. StringStructToDump[0] = '\0';
  793. ret = sscanf(args,"%s %lx", StringStructToDump, &Length );
  794. if (!GetExpressionEx( StringStructToDump, &StructToDump, NULL )) {
  795. dprintf("unable to get expression %s\n",StringStructToDump);
  796. return;
  797. }
  798. CountClearBits( StructToDump, Length);
  799. }
  800. DECLARE_API( countdwords)
  801. {
  802. CHAR StringStructToDump[1024]; // See other kd routines for size
  803. UINT64 StructToDump;
  804. ULONG Length;
  805. ULONG Dword;
  806. LONG ret;
  807. //
  808. // If the caller specified an address then that's the item we dump
  809. //
  810. StructToDump = 0;
  811. Length = 0;
  812. StringStructToDump[0] = '\0';
  813. ret = sscanf(args,"%s %lx %lx", StringStructToDump, &Length, &Dword);
  814. if (!GetExpressionEx( StringStructToDump, &StructToDump, NULL)) {
  815. dprintf("unable to get expression %s\n",StringStructToDump);
  816. return;
  817. }
  818. CountDwords( StructToDump, Length, Dword);
  819. }
  820. DECLARE_API( dumpcclog)
  821. {
  822. CHAR StringStart[2048];
  823. UINT64 Start;
  824. ULONG Length;
  825. ULONG Dword;
  826. ULONG Current;
  827. ULONG Result;
  828. PULONG Buffer = (PULONG)StringStart;
  829. LONG ret;
  830. //
  831. // If the caller specified an address then that's the item we dump
  832. //
  833. Start = 0;
  834. Length = 0;
  835. StringStart[0] = '\0';
  836. ret = sscanf(args,"%s %lx", StringStart, &Length);
  837. if (!GetExpressionEx( StringStart, &Start, NULL)) {
  838. dprintf("unable to get expression %s\n", StringStart);
  839. return;
  840. }
  841. if ( !ReadMemory( (DWORD_PTR)Start, Buffer, sizeof( StringStart), &Result) ) {
  842. dprintf( "Unable to read %d bytes at %p\n", sizeof( StringStart), Start);
  843. return;
  844. }
  845. dprintf("\n");
  846. for ( Current = 0; Current < (Length >> 2); Current += 1) {
  847. switch( Buffer[Current]) {
  848. case -1:
  849. dprintf("FlushCache - Enter\n");
  850. break;
  851. case -2:
  852. dprintf("FlushCache - Leave\n");
  853. break;
  854. case -3:
  855. dprintf("PurgeCacheSection\n");
  856. break;
  857. default:
  858. dprintf("%d 0x%08x 0x%08x\n", Buffer[Current] & 3,
  859. Buffer[Current] & ~(ULONG)0xfff,
  860. ((Buffer[Current] >> 2) & 0x3ff)<<12);
  861. break;
  862. }
  863. }
  864. }
  865. DECLARE_API( splay)
  866. {
  867. UNREFERENCED_PARAMETER( dwCurrentPc );
  868. UNREFERENCED_PARAMETER( hCurrentProcess );
  869. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) SimpleSplay, dwProcessor, hCurrentThread );
  870. }