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.

1627 lines
49 KiB

  1. #include "pch.h"
  2. #include "udfskd.h"
  3. #include "fatkd.h"
  4. #include <ntddcdrm.h>
  5. #include <ntdddisk.h>
  6. #include <ntddscsi.h>
  7. #include "..\..\udfs\nodetype.h"
  8. #ifdef UDFS_RW_IN_BUILD
  9. #include "..\..\udfsrw\nodetype.h"
  10. #endif
  11. #include "..\..\udfs\udf.h"
  12. #include "..\..\udfs\udfstruc.h"
  13. #include "..\..\udfs\udfdata.h"
  14. //
  15. // 13346/UDF on disc note type codes and dump routines
  16. //
  17. DUMP_ROUTINE( DumpUdfOnDiscIcbFile);
  18. DUMP_ROUTINE( DumpUdfOnDiscFid);
  19. DUMP_ROUTINE( DumpUdfOnDiscFsd);
  20. DUMP_ROUTINE( DumpUdfOnDiscLvol);
  21. DUMP_ROUTINE( DumpUdfOnDiscPartDesc);
  22. DUMP_ROUTINE( DumpUdfOnDiscVdp);
  23. DUMP_ROUTINE( DumpUdfOnDiscAnchor);
  24. DUMP_ROUTINE( DumpUdfOnDiscPvd);
  25. DUMP_ROUTINE( DumpUdfOnDiscIcbExtFile);
  26. static NODE_TYPE_INFO_NEW UdfOnDiscTypeCodes[] = {
  27. { DESTAG_ID_NSR_PVD, "(3/10.1) PVD", NULL, DumpUdfOnDiscPvd },
  28. { DESTAG_ID_NSR_ANCHOR, "(3/10.2) AVDP", NULL, DumpUdfOnDiscAnchor },
  29. { DESTAG_ID_NSR_VDP, "(3/10.3) VDP", NULL, DumpUdfOnDiscVdp },
  30. { DESTAG_ID_NSR_IMPUSE, "(3/10.4) IUVD", NULL, NULL },
  31. { DESTAG_ID_NSR_PART, "(3/10.5) PD", NULL, DumpUdfOnDiscPartDesc },
  32. { DESTAG_ID_NSR_LVOL, "(3/10.6) LVD", NULL, DumpUdfOnDiscLvol },
  33. { DESTAG_ID_NSR_UASD, "(3/10.8) UASD", NULL, NULL },
  34. { DESTAG_ID_NSR_TERM, "(3/10.9) TD", NULL, NULL },
  35. { DESTAG_ID_NSR_LVINTEG, "(3/10.10) LVID", NULL, NULL },
  36. { DESTAG_ID_NSR_FSD, "(4/14.1) FSD", NULL, DumpUdfOnDiscFsd },
  37. { DESTAG_ID_NSR_FID, "(4/14.4) FID", NULL, DumpUdfOnDiscFid },
  38. { DESTAG_ID_NSR_ALLOC, "(4/14.5) AED", NULL, NULL },
  39. { DESTAG_ID_NSR_ICBIND, "(4/14.7) ICB Indirect", NULL, NULL },
  40. { DESTAG_ID_NSR_ICBTRM, "(4/14.8) ICB Terminal", NULL, NULL },
  41. { DESTAG_ID_NSR_FILE, "(4/14.9) FE", NULL, DumpUdfOnDiscIcbFile },
  42. { DESTAG_ID_NSR_EXT_FILE, "(4/14.17) EXT FE", NULL, DumpUdfOnDiscIcbExtFile },
  43. { DESTAG_ID_NSR_EA, "(4/14.10) EAH", NULL, NULL },
  44. { DESTAG_ID_NSR_UASE, "(4/14.11) USE", NULL, NULL },
  45. { DESTAG_ID_NSR_SBP, "(4/14.12) SBD", NULL, NULL },
  46. { DESTAG_ID_NSR_PINTEG, "(4/14.13) PI", NULL, NULL },
  47. { 0, "UNKNOWN/NotSpec", NULL }
  48. };
  49. static PCHAR IcbStrategies[] = {
  50. "NOTSPEC",
  51. "4/A.2 TREE",
  52. "4/A.3 MASTER",
  53. "4/A.4 BALTREE",
  54. "4/A.5 DIRECT"
  55. };
  56. #define MAX_VALID_ICB_STRAT 4
  57. static PCHAR IcbFileTypes[] = {
  58. "NOTSPEC",
  59. "UASPACE",
  60. "PINTEG",
  61. "INDIRECT",
  62. "DIRECTORY",
  63. "FILE",
  64. "BLOCKDEV",
  65. "CHARDEV",
  66. "XA",
  67. "FIFO",
  68. "SOCKET",
  69. "TERMINAL",
  70. "PATHLINK",
  71. "STREAMDIR"
  72. };
  73. #define MAX_VALID_ICB_TYPE 13
  74. static STATE UdfIcbTagFlags[] = {
  75. { ICBTAG_F_ALLOC_MASK, ICBTAG_F_ALLOC_SHORT, "ShortAlloc"},
  76. { ICBTAG_F_ALLOC_MASK, ICBTAG_F_ALLOC_LONG, "LongAlloc"},
  77. { ICBTAG_F_ALLOC_MASK, ICBTAG_F_ALLOC_EXTENDED, "ExtAlloc"},
  78. { ICBTAG_F_ALLOC_MASK, ICBTAG_F_ALLOC_IMMEDIATE, "ImmAlloc"},
  79. { ICBTAG_F_SORTED, ICBTAG_F_SORTED, "Sorted(4/8.6.1)"},
  80. { ICBTAG_F_NO_RELOCATE, ICBTAG_F_NO_RELOCATE, "Nonrelocatable"},
  81. { ICBTAG_F_ARCHIVE, ICBTAG_F_ARCHIVE, "Archive"},
  82. { ICBTAG_F_SETUID, ICBTAG_F_SETUID, "SetUid"},
  83. { ICBTAG_F_SETGID, ICBTAG_F_SETGID, "SetGid"},
  84. { ICBTAG_F_STICKY, ICBTAG_F_STICKY, "Sticky"},
  85. { ICBTAG_F_CONTIGUOUS, ICBTAG_F_CONTIGUOUS, "Contiguous"},
  86. { ICBTAG_F_SYSTEM, ICBTAG_F_SYSTEM, "System"},
  87. { ICBTAG_F_TRANSFORMED, ICBTAG_F_TRANSFORMED, "Transformed"},
  88. { ICBTAG_F_MULTIVERSIONS, ICBTAG_F_MULTIVERSIONS, "MultiVersions"},
  89. { 0}
  90. };
  91. static STATE UdfFidFlags[] = {
  92. { NSR_FID_F_HIDDEN, NSR_FID_F_HIDDEN, "Hidden"},
  93. { NSR_FID_F_DIRECTORY, NSR_FID_F_DIRECTORY, "Directory"},
  94. { NSR_FID_F_DELETED, NSR_FID_F_DELETED, "Deleted"},
  95. { NSR_FID_F_PARENT, NSR_FID_F_PARENT, "Parent"},
  96. { NSR_FID_F_META, NSR_FID_F_META, "MetadataStream"},
  97. { 0 }
  98. };
  99. // LCB summary dump used by F/Scb tree dump
  100. VOID
  101. UdfSummaryLcbDumpRoutine(
  102. IN ULONG64 RemoteAddress,
  103. IN LONG Options
  104. )
  105. {
  106. USHORT Type;
  107. ULONG64 Scb;
  108. ULONG Offset;
  109. ReadM( &Type, RemoteAddress, sizeof( Type));
  110. #ifdef UDFS_RW_IN_BUILD
  111. if (( UDFS_NTC_LCB != Type) && (UDFSRW_NTC_LCB != Type)) {
  112. #else
  113. if ( UDFS_NTC_LCB != Type) {
  114. #endif
  115. dprintf( "Not a UDF LCB @ %08x\n", RemoteAddress);
  116. return;
  117. }
  118. if (Options & 2) {
  119. DumpUdfLcb( RemoteAddress, (Options & 8) ? 1 : 0, &NewNodeTypeCodes[ TypeCodeInfoIndex( Type)]);
  120. }
  121. else {
  122. GetFieldValue( RemoteAddress,
  123. "udfs!_LCB",
  124. (UDFS_NTC_LCB != Type) ? "ChildScb" : "ChildFcb",
  125. Scb);
  126. dprintf( "\nUDF LCB @ %I64x Child F/Scb: %I64x ", RemoteAddress, Scb);
  127. GetFieldOffset( "udfs!_LCB", "FileName", &Offset);
  128. DumpStr( Offset, RemoteAddress + Offset, "FileName", FALSE, TRUE);
  129. }
  130. }
  131. // OK
  132. DUMP_ROUTINE( DumpUdfFcb)
  133. /*++
  134. Routine Description:
  135. Dump a specific fcb.
  136. Arguments:
  137. Address - Gives the address of the fcb to dump
  138. Return Value:
  139. None
  140. --*/
  141. {
  142. ULONG Result;
  143. UINT64 NonP;
  144. ULONG Flags, FcbState;
  145. ULONG Offset, Offsetb;
  146. ROE( GetFieldValue( Address, InfoNode->TypeName, "FcbState", FcbState));
  147. //
  148. // For R/O udfs, dump the FCB flags and common header flags. RW FCB
  149. // is less interesting, nothing to dump.
  150. //
  151. if (!NTC_IS_UDFS_RW( InfoNode->TypeCode)) {
  152. dprintf("[ Option flags: 1 = list children, 2 = List parent links, 4 = dump Mcb ]\n\n");
  153. dprintf("FcbState: ");
  154. PrintState( UdfFcbState, FcbState );
  155. ROE( GetFieldValue( Address, InfoNode->TypeName, "Flags", Flags));
  156. dprintf("\nHeader.Flags: ");
  157. PrintState( HeaderFlags, Flags );
  158. ROE( GetFieldValue( Address, InfoNode->TypeName, "Flags2", Flags)); // TODO:
  159. dprintf("\nHeader.Flags2: ");
  160. PrintState( HeaderFlags2, Flags );
  161. dprintf("\n");
  162. }
  163. //
  164. // Having established that this looks like an fcb, let's dump the
  165. // interesting parts.
  166. //
  167. Dt( InfoNode->TypeName, Address, 0, 0, NULL);
  168. // TODO: Does the above dump the union data/index part?
  169. dprintf("\n");
  170. //
  171. // Nonpaged portion
  172. //
  173. ROE( GetFieldValue( Address, InfoNode->TypeName, "FcbNonpaged", NonP));
  174. if (NonP) {
  175. dprintf("\nNonpaged portion @ %I64x\n\n",NonP);
  176. Dt( "Udfs!FCB_NONPAGED", NonP, 0, 0, NULL);
  177. }
  178. //
  179. // R/O UDFS: Dump all Fcb children
  180. //
  181. if (!NTC_IS_UDFS_RW( InfoNode->TypeCode)) {
  182. if (( Options & 1) && (UDFS_NTC_FCB_INDEX == InfoNode->TypeCode)) {
  183. dprintf("\nChild Lcb list\n");
  184. ROE( GetFieldOffset( "udfs!_FCB", "ChildLcbQueue", &Offset));
  185. ROE( GetFieldOffset( "udfs!_LCB", "ParentFcbLinks", &Offsetb));
  186. DumpList( Address + Offset,
  187. UdfSummaryLcbDumpRoutine,
  188. Offsetb,
  189. FALSE,
  190. 0 );
  191. }
  192. if (Options & 2) {
  193. dprintf("\nParent Lcb list\n");
  194. ROE( GetFieldOffset( "udfs!_FCB", "ParentLcbQueue", &Offset));
  195. ROE( GetFieldOffset( "udfs!_LCB", "ChildFcbLinks", &Offsetb));
  196. DumpList( Address + Offset,
  197. UdfSummaryLcbDumpRoutine,
  198. Offsetb,
  199. FALSE,
  200. 0 );
  201. }
  202. if (Options & 4) {
  203. if (FcbState & FCB_STATE_MCB_INITIALIZED) {
  204. ROE( GetFieldOffset( "udfs!_FCB", "Mcb", &Offset));
  205. dprintf("\nMcb\n");
  206. DumpLargeMcb( Address+Offset, 0, NULL);
  207. }
  208. }
  209. }
  210. else {
  211. //
  212. // TODO: RW UDFS - dump attached stream Scb list?
  213. //
  214. }
  215. dprintf( "\n" );
  216. }
  217. // OK
  218. DUMP_ROUTINE( DumpUdfLcb)
  219. {
  220. ULONG Flags;
  221. ULONG Ntc;
  222. ROE( GetFieldValue( Address, InfoNode->TypeName, "NodeTypeCode", Ntc));
  223. ROE( GetFieldValue( Address, InfoNode->TypeName, "Flags", Flags));
  224. dprintf("Lcb.Flags: ");
  225. PrintState( NTC_IS_UDFS_RW(Ntc) ? UdfRwLcbFlags : UdfLcbFlags, Flags );
  226. dprintf( "\n");
  227. Dt( InfoNode->TypeName, Address, Options, 0, NULL); // TODO: Expand parent list?
  228. if (Options >= 1) {
  229. ULONG64 Scb;
  230. dprintf("\n\nChild S/Fcb:\n");
  231. ROE( GetFieldValue( Scb,
  232. InfoNode->TypeName,
  233. (Ntc == UDFS_NTC_LCB) ? "ChildFcb" : "ChildScb",
  234. Scb));
  235. DumpAnyStruct( Scb, 0, NULL);
  236. }
  237. }
  238. // OK
  239. DUMP_ROUTINE( DumpUdfPcb)
  240. {
  241. ULONG Result;
  242. ULONG Offset;
  243. ULONG Current = 0;
  244. ULONG Partitions;
  245. ULONG Flags;
  246. ULONG Size;
  247. ROE( GetFieldValue( Address, InfoNode->TypeName, "Flags", Flags));
  248. dprintf( "\nPcb.Flags: ");
  249. PrintState( UdfPcbFlags, Flags);
  250. Dt( InfoNode->TypeName, Address, Options, 0, NULL);
  251. ROE( GetFieldValue( Address, InfoNode->TypeName, "Partitions", Partitions));
  252. if (Partitions > 5) {
  253. dprintf("Bogus partition count %d\n", Partitions);
  254. return;
  255. }
  256. ROE( GetFieldOffset( InfoNode->TypeName, "Partition", &Offset));
  257. Address += Offset;
  258. Size = GetTypeSize( "Udfs!PARTITION");
  259. for (Current = 0; Current < Partitions; ++Current) {
  260. dprintf("\nRef: %d\n", Current);
  261. Dt( "Udfs!PARTITION", Address, Options, 0, NULL);
  262. Address += Size;
  263. }
  264. }
  265. // OK
  266. DUMP_ROUTINE( DumpUdfCcb)
  267. {
  268. ULONG Flags;
  269. ULONG Ntc;
  270. ROE( GetFieldValue( Address, InfoNode->TypeName, "NodeTypeCode", Ntc));
  271. ROE( GetFieldValue( Address, InfoNode->TypeName, "Flags", Flags));
  272. dprintf( "Ccb.Flags: ");
  273. PrintState( NTC_IS_UDFS_RW(Ntc) ? UdfRwCcbFlags : UdfCcbFlags, Flags);
  274. dprintf( "\n");
  275. Dt( InfoNode->TypeName, Address, Options, 0, NULL);
  276. }
  277. // OK
  278. DUMP_ROUTINE( DumpUdfIrpContextLite)
  279. {
  280. Dt( InfoNode->TypeName, Address, Options, 0, NULL);
  281. // *** FIXME - dump delayed close queue
  282. }
  283. // OK
  284. DUMP_ROUTINE( DumpUdfIrpContext)
  285. {
  286. ULONG Flags;
  287. ULONG Ntc;
  288. ROE( GetFieldValue( Address, InfoNode->TypeName, "NodeTypeCode", Ntc));
  289. ROE( GetFieldValue( Address, InfoNode->TypeName, "Flags", Flags));
  290. dprintf("\nIrpContext Flags: ");
  291. PrintState( NTC_IS_UDFS_RW(Ntc) ? UdfRwIrpContextFlags : UdfIrpContextFlags, Flags );
  292. dprintf( "\n");
  293. Dt( InfoNode->TypeName, Address, Options, 0, NULL);
  294. }
  295. // OK
  296. DUMP_ROUTINE( DumpUdfIcbSearchContext)
  297. {
  298. Dt( "udfs!_ICB_SEARCH_CONTEXT", Address, 1, 0, NULL); // TODO: expand current/active only
  299. }
  300. // OK
  301. DUMP_ROUTINE( DumpLargeMcb)
  302. {
  303. ULONG PairCount = 0, EntryCount = 0, Result;
  304. ULONG64 Mapping;
  305. PMAPPING Mappings, Current;
  306. ULONG PrevVbn = 0;
  307. dprintf("\nLARGE MCB @ %I64X\n", Address);
  308. Dt( "udfs!LARGE_MCB", Address, 0,0, NULL);
  309. dprintf("\n");
  310. ROE( GetFieldValue( Address, "udfs!LARGE_MCB", "PairCount", PairCount));
  311. ROE( GetFieldValue( Address, "udfs!LARGE_MCB", "Mapping", Mapping));
  312. Mappings = calloc( PairCount, sizeof( MAPPING));
  313. if (NULL == Mappings) {
  314. dprintf("Failed to allocate space for %d mappings\n", PairCount);
  315. return;
  316. }
  317. if (!ReadMemory( Mapping, Mappings, sizeof( MAPPING)*PairCount, &Result )) {
  318. dprintf("Unable to read mapping info @ %08x", Mapping);
  319. return;
  320. }
  321. Current = Mappings;
  322. for ( Current = Mappings;
  323. EntryCount < PairCount;
  324. ++EntryCount, ++Current) {
  325. dprintf("(%08x,%08x) -> %08x\n", PrevVbn, Current->NextVbn - PrevVbn, Current->Lbn);
  326. PrevVbn = Current->NextVbn;
  327. }
  328. dprintf("\n");
  329. free( Mappings);
  330. }
  331. // OK
  332. DUMP_ROUTINE( DumpUdfVcb)
  333. {
  334. ULONG Flags;
  335. ULONG Ntc;
  336. FIELD_INFO Alloc[] = { //{ ".", NULL, 0, 0, 0, NULL},
  337. { "AllocSup.", NULL, 0, DBG_DUMP_FIELD_RECUR_ON_THIS,0, NULL}
  338. };
  339. ROE( GetFieldValue( Address, InfoNode->TypeName, "NodeTypeCode", Ntc));
  340. ROE( GetFieldValue( Address, InfoNode->TypeName, "VcbState", Flags));
  341. dprintf("VcbState: ");
  342. PrintState( NTC_IS_UDFS_RW(Ntc) ? UdfRwVcbStateFlags : UdfVcbStateFlags, Flags );
  343. dprintf("\n");
  344. Dt( InfoNode->TypeName, Address, Options, 0, NULL);
  345. dprintf("\n");
  346. //
  347. // For RW UDFS, expand some more fields.
  348. //
  349. if (NTC_IS_UDFS_RW( Ntc)) {
  350. Dt( InfoNode->TypeName, Address, Options, 1, Alloc);
  351. }
  352. }
  353. DUMP_ROUTINE( DumpUdfVdo)
  354. {
  355. USHORT Ntc;
  356. PUSHORT pNtc;
  357. ULONG Offset;
  358. ULONG Result;
  359. RM( Address, Ntc, pNtc, PUSHORT, Result );
  360. #ifndef UDFS_RW_IN_BUILD
  361. if (UDFS_NTC_VCB == Ntc) {
  362. #else
  363. if ((UDFS_NTC_VCB == Ntc) || (UDFSRW_NTC_VCB == Ntc)) {
  364. #endif
  365. //
  366. // Looks like we've been given a VCB pointer. Work back to the containing vdo.
  367. //
  368. dprintf("Backtracking to containing VDO from VCB...");
  369. ROE( GetFieldOffset( "udfs!VOLUME_DEVICE_OBJECT", "Vcb", &Offset));
  370. Address -= Offset;
  371. }
  372. dprintf( "\nUDFS Volume device object @ %08lx\n", Address );
  373. Dt( "Udfs!VOLUME_DEVICE_OBJECT", Address, Options, 0, NULL);
  374. }
  375. VOID
  376. DumpTreeLcb(
  377. IN ULONG64 Lcb,
  378. IN LONG RecurLevel
  379. );
  380. static UCHAR RecurDumpBuf[512];
  381. static ULONG __i;
  382. #define DoIndent(I) for ( __i = 0; __i < (I); ++__i) RecurDumpBuf[__i] = ' '; \
  383. RecurDumpBuf[ __i] = 0; \
  384. dprintf( RecurDumpBuf);
  385. static WCHAR RDumpNameBuf[512];
  386. //
  387. // Called from outside for "main" stream SCBs,
  388. // recursive for stream directories / stream Scbs
  389. //
  390. // OK
  391. static VOID
  392. DumpTreeRecur (
  393. IN ULONG64 Scb,
  394. IN ULONG RecurLevel
  395. )
  396. {
  397. ULONG64 Fcb, SdScb, Lcb;
  398. ULONG Ur, Cc, R, Offset, Offsetb, Error, Flags = 0;
  399. USHORT Type, Indent, Lc;
  400. UNICODE_STRING Name;
  401. PUCHAR TypeString = NULL;
  402. BOOLEAN Stream, Index, StreamDir, Data;
  403. if ((*ExtensionApis.lpCheckControlCRoutine)()) {
  404. dprintf("CTRL+C - aborting\n");
  405. // Raise out - could be looping in many levels...
  406. *((PULONG)(0)) = 0;
  407. return;
  408. }
  409. if (RecurLevel > 100) {
  410. dprintf("*** Recursed more than 100 deep - aborting ***\n");
  411. return;
  412. }
  413. //
  414. // dump S/Fcb vitals
  415. //
  416. Indent = ((USHORT)RecurLevel) << 1;
  417. if (0 == Scb) {
  418. DoIndent( Indent);
  419. dprintf("Called with NULL F/Scb\n");
  420. return;
  421. }
  422. ReadM( &Type, Scb, sizeof( Type));
  423. if (!NTC_IS_UDFS_RW( Type)) {
  424. Stream = StreamDir = FALSE;
  425. TypeString = "Udfs!FCB";
  426. Fcb = 0;
  427. Index = Type == UDFS_NTC_FCB_INDEX;
  428. Data = Type == UDFS_NTC_FCB_DATA;
  429. }
  430. else {
  431. #ifdef UDFS_RW_IN_BUILD
  432. TypeString = "Udfs!SCB";
  433. ROE( GetFieldValue( Scb, "udfs!_SCB", "ScbState", Flags));
  434. Stream = 0 != (Flags & 0x10); // scb_state_secondary_stream
  435. StreamDir = 0 != (Flags & 0x08); // stream_directory
  436. if ((Error = GetFieldValue( Scb, "udfs!_SCB", "Fcb", Fcb)) || (0 == Fcb)) {
  437. DoIndent( Indent);
  438. if (Error) {
  439. dprintf("Error reading Fcb from Scb %d\n", Error);
  440. }
  441. else {
  442. dprintf("<NULL Fcb ptr>\n");
  443. }
  444. }
  445. Index = NodeIsUdfsRwIndex( Type);
  446. Data = NodeIsUdfsRwData( Type);
  447. #else
  448. dprintf("This FSKD build does not support R/W UDFS structures\n");
  449. return;
  450. #endif
  451. }
  452. //
  453. // If this is a new file, as opposed to a stream of a file we've already dumped,
  454. // them dump out the FCB and follow the stream directory. For R/O UDFS there's
  455. // nothing to do here (No streams & F/Scb split)
  456. //
  457. #ifdef UDFS_RW_IN_BUILD
  458. if (!Stream && NTC_IS_UDFS_RW( Type)) {
  459. DoIndent( Indent);
  460. dprintf("FCB @ 0x%I64x\n", Fcb);
  461. if ((0 != Fcb) && !(Error = GetFieldValue( Fcb, "udfs!_FCB", "StreamDirectoryScb", SdScb)) &&
  462. (0 != SdScb)) {
  463. //
  464. // TODO: Count SCBs in chain, verify match scbs under streamdir?
  465. //
  466. ROE( GetFieldValue( SdScb, "udfs!_SCB", "NodeTypeCode", Type));
  467. if (NodeIsUdfsRwIndex(Type)) {
  468. //
  469. // Stream dir - dump details than trawl through LCBs
  470. //
  471. ROE( GetFieldValue( SdScb, "udfs!_SCB", "ScbUserReference", Ur)); // TODO: Don't bail here!
  472. ROE( GetFieldValue( SdScb, "udfs!_SCB", "ScbReference", R));
  473. ROE( GetFieldValue( SdScb, "udfs!_SCB", "ScbCleanup", Cc));
  474. DoIndent( Indent);
  475. dprintf("SCB @ 0x%I64X (%X,%X,%X) (-STREAMDIR-) \n", SdScb, Cc, Ur, R);
  476. //
  477. // Follow all Lcbs and recursively dump tree
  478. //
  479. ROE( GetFieldOffset( "udfs!_SCB", "ChildLcbQueue", &Offset));
  480. ROE( GetFieldOffset( "udfs!_LCB", "ParentScbLinks", &Offsetb));
  481. DumpList( SdScb + Offset,
  482. DumpTreeLcb,
  483. Offsetb,
  484. FALSE,
  485. RecurLevel + 1);
  486. }
  487. else {
  488. DoIndent( Indent);
  489. dprintf("Invalid StreamDir Scb nodetypecode %l\n", Type);
  490. }
  491. }
  492. else {
  493. DoIndent( Indent);
  494. if (Error) {
  495. dprintf("Error reading streamdirscb from fcb %d\n", Error);
  496. }
  497. else {
  498. dprintf("<NULL stream dir or Fcb>\n");
  499. }
  500. }
  501. }
  502. #endif
  503. if (!StreamDir) {
  504. // old (win2k) udfs didn't have this field. Ignore failure.
  505. Lc = 0xffff;
  506. GetFieldValue( Scb, TypeString, "LinkCount", Lc);
  507. if (NTC_IS_UDFS_RW( Type)) {
  508. #ifdef UDFS_RW_IN_BUILD
  509. ROE( GetFieldValue( Scb, TypeString, "ScbUserReference", Ur));
  510. ROE( GetFieldValue( Scb, TypeString, "ScbReference", R));
  511. ROE( GetFieldValue( Scb, TypeString, "ScbCleanup", Cc));
  512. #endif
  513. }
  514. else {
  515. ROE( GetFieldValue( Scb, TypeString, "FcbUserReference", Ur));
  516. ROE( GetFieldValue( Scb, TypeString, "FcbReference", R));
  517. ROE( GetFieldValue( Scb, TypeString, "FcbCleanup", Cc));
  518. }
  519. if (Index) {
  520. //
  521. // Index - dump details then trawl Lcbs
  522. //
  523. DoIndent( Indent);
  524. dprintf("F/SCB (-DIR-) @ 0x%I64X (%d,%d,%d - %d)\n", Scb, Cc, Ur, R, Lc);
  525. if (NTC_IS_UDFS_RW( Type) && (0 != Fcb)) {
  526. if (!GetFieldValue( Fcb, "udfs!_FCB", "DefaultStreamScb", SdScb)) {
  527. if (SdScb != Scb) {
  528. DoIndent(Indent);
  529. dprintf("INCONSISTENT - Scb->Fcb->DefaultStreamScb != Scb\n");
  530. }
  531. }
  532. }
  533. if (Stream) {
  534. DoIndent( Indent);
  535. dprintf("ILLEGAL - secondary stream is index\n");
  536. }
  537. //
  538. // Follow all Lcbs and recursively dump tree
  539. //
  540. ROE( GetFieldOffset( TypeString, "ChildLcbQueue", &Offset));
  541. ROE( GetFieldOffset( "udfs!_LCB",
  542. NTC_IS_UDFS_RW( Type) ? "ParentScbLinks" : "ParentFcbLinks",
  543. &Offsetb));
  544. DumpList( Scb + Offset,
  545. DumpTreeLcb,
  546. Offsetb,
  547. FALSE,
  548. RecurLevel + 1);
  549. }
  550. else if (Data) {
  551. //
  552. // File - dump details
  553. //
  554. DoIndent( Indent);
  555. dprintf("F/SCB (-DATA-) @ 0x%I64X (%d,%d,%d - %d)\n", Scb, Cc, Ur, R, Lc);
  556. }
  557. else {
  558. DoIndent( Indent);
  559. dprintf("Invalid F/Scb nodetypecode %d\n", Type);
  560. }
  561. }
  562. }
  563. //
  564. // Dump an LCB and all below it.
  565. //
  566. // OK
  567. VOID
  568. DumpTreeLcb(
  569. IN ULONG64 Lcb,
  570. IN LONG RecurLevel
  571. )
  572. {
  573. ULONG64 Scb;
  574. ULONG Offset;
  575. ULONG Ntc;
  576. ULONG Ref;
  577. ROE( GetFieldValue( Lcb, "udfs!_LCB", "NodeTypeCode", Ntc));
  578. #ifdef UDFS_RW_IN_BUILD
  579. if (( UDFS_NTC_LCB != Ntc) && (UDFSRW_NTC_LCB != Ntc)) {
  580. #else
  581. if ( UDFS_NTC_LCB != Ntc) {
  582. #endif
  583. dprintf( "Not a UDF LCB @ %I64x - list corrupt\n", Lcb);
  584. return;
  585. }
  586. GetFieldValue( Lcb,
  587. "udfs!_LCB",
  588. NTC_IS_UDFS_RW( Ntc) ? "ChildScb" : "ChildFcb",
  589. Scb);
  590. ROE( GetFieldValue( Lcb, "udfs!_LCB", "Reference", Ref));
  591. DoIndent( ((ULONG)RecurLevel) << 1);
  592. dprintf( "LCB @ %I64x (Ref: %d) Child F/Scb: %I64x ", Lcb, Ref, Scb);
  593. #ifdef UDFS_RW_IN_BUILD
  594. if (NTC_IS_UDFS_RW( Ntc)) {
  595. ROE( GetFieldValue( Lcb, "udfs!_LCB", "Flags", Ref));
  596. if (LcbDeleted( Ref)) {
  597. dprintf(" *DEL* ");
  598. }
  599. }
  600. #endif
  601. GetFieldOffset( "udfs!_LCB", "FileName", &Offset);
  602. DumpStr( Offset, Lcb+Offset, "Name", FALSE, TRUE);
  603. DumpTreeRecur( Scb, (ULONG)(RecurLevel + 1));
  604. }
  605. void
  606. DumpCloseQueue(
  607. IN ULONG64 Vcb
  608. )
  609. {
  610. ULONG64 UdfData;
  611. ULONG Offset;
  612. // ROE( GetFieldOffset( "udfs!", "UdfData", &Offset));
  613. // ROE( GetFieldValue( 0, "Udfs!UdfData", NULL, UdfData));
  614. dprintf("\nDelayed closes on Vcb %I64X\n", Vcb);
  615. dprintf("NOT IMPLEMENTED\n");
  616. }
  617. // OK
  618. VOID
  619. SummariseIrpContextLite(
  620. IN ULONG64 RemoteAddress,
  621. IN LONG Options
  622. )
  623. {
  624. ULONG64 Scb;
  625. USHORT Type;
  626. ReadM( &Type, RemoteAddress, sizeof( Type));
  627. ROE( GetFieldValue( RemoteAddress,
  628. "udfs!_IRP_CONTEXT_LITE",
  629. NTC_IS_UDFS_RW( Type) ? "Scb" : "Fcb", Scb));
  630. dprintf(" 0x%I64x\n", Scb);
  631. }
  632. // OK
  633. VOID
  634. SummariseIrpContext(
  635. IN ULONG64 RemoteAddress,
  636. IN LONG Options
  637. )
  638. {
  639. ULONG64 Irp;
  640. ROE( GetFieldValue( RemoteAddress, "udfs!_IRP_CONTEXT", "Irp", Irp));
  641. dprintf(" 0x%I64x\n", Irp);
  642. }
  643. // OK
  644. DUMP_ROUTINE( DumpUdfData)
  645. {
  646. ULONG Count, Offset, LinkOffset;
  647. Dt( "udfs!UDF_DATA", Address, Options, 0, NULL);
  648. ROE( GetFieldValue( Address, "udfs!_UDF_DATA", "DelayedCloseCount", Count));
  649. if (Count) {
  650. dprintf("\nSCBs on Delayed Close Queue (%d entries)\n", Count);
  651. ROE( GetFieldOffset( "udfs!_UDF_DATA", "DelayedCloseQueue", &Offset));
  652. ROE( GetFieldOffset( "udfs!_IRP_CONTEXT_LITE", "DelayedCloseLinks", &LinkOffset));
  653. DumpList( Address+Offset, SummariseIrpContextLite, LinkOffset, FALSE, 0);
  654. }
  655. dprintf(" \n");
  656. GetFieldValue( Address, "udfs!_UDF_DATA", "AsyncCloseCount", Count);
  657. if (Count) {
  658. dprintf("\nF/SCBs on Async Close Queue (%d entries)\n", Count);
  659. ROE( GetFieldOffset( "udfs!_UDF_DATA", "AsyncCloseQueue", &Offset));
  660. ROE( GetFieldOffset( "udfs!_IRP_CONTEXT", "WorkQueueItem.List", &LinkOffset));
  661. DumpList( Address+Offset, SummariseIrpContext, LinkOffset, FALSE, 0);
  662. }
  663. dprintf(" \n");
  664. }
  665. // OK
  666. DUMP_ROUTINE( DumpTreeSummary)
  667. {
  668. ULONG64 RootFcbAddr, Scb, Vcb = 0;
  669. ULONG Error;
  670. USHORT Type;
  671. ReadM( &Type, Address, sizeof( Type));
  672. #ifdef UDFS_RW_IN_BUILD
  673. if ((UDFS_NTC_VCB == Type) || (UDFSRW_NTC_VCB == Type) ) {
  674. #else
  675. if (UDFS_NTC_VCB == Type) {
  676. #endif
  677. Error = GetFieldValue( Address,
  678. "udfs!_VCB",
  679. NTC_IS_UDFS_RW( Type) ? "RootIndexScb" : "RootIndexFcb",
  680. Scb);
  681. if (Error) {
  682. dprintf( "Error %d reading rootindex f/scb addr\n", Error);
  683. return;
  684. }
  685. Vcb = Address;
  686. dprintf( "\nSummary tree for UDF Vcb @ %I64x Refs: (clean,userref,ref - linkcount)\n\n", Address );
  687. dprintf( "(1,0,0) handle\n(0,1,1) Outstanding FO / del.close / child lcb\n(0,0,1) Stream file\n(0,0,1) Stream directory\n\n");
  688. }
  689. else {
  690. //
  691. // Try and extract vcb from scb->fcb to dump delay close info
  692. //
  693. Scb = Address;
  694. }
  695. DumpTreeRecur( Scb, 0);
  696. //
  697. // Dump delayed close queue info
  698. //
  699. dprintf("\nDo !d Udfs!UdfData to display globals and dump the delayed close queue\n");
  700. dprintf( "\n" );
  701. }
  702. DECLARE_API( tree )
  703. {
  704. UNREFERENCED_PARAMETER( dwCurrentPc );
  705. UNREFERENCED_PARAMETER( hCurrentProcess );
  706. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpTreeSummary, dwProcessor, hCurrentThread );
  707. }
  708. DECLARE_API( udfvcb )
  709. {
  710. UNREFERENCED_PARAMETER( dwCurrentPc );
  711. UNREFERENCED_PARAMETER( hCurrentProcess );
  712. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfVcb, dwProcessor, hCurrentThread );
  713. }
  714. DECLARE_API( udficbsc )
  715. {
  716. UNREFERENCED_PARAMETER( dwCurrentPc );
  717. UNREFERENCED_PARAMETER( hCurrentProcess );
  718. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfIcbSearchContext, dwProcessor, hCurrentThread );
  719. }
  720. DECLARE_API( udfccb)
  721. {
  722. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfCcb, dwProcessor, hCurrentThread );
  723. }
  724. DECLARE_API( udffcb )
  725. {
  726. UNREFERENCED_PARAMETER( dwCurrentPc );
  727. UNREFERENCED_PARAMETER( hCurrentProcess );
  728. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfFcb, dwProcessor, hCurrentThread );
  729. }
  730. DECLARE_API( udfvdo )
  731. {
  732. UNREFERENCED_PARAMETER( dwCurrentPc );
  733. UNREFERENCED_PARAMETER( hCurrentProcess );
  734. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfVdo, dwProcessor, hCurrentThread );
  735. }
  736. DECLARE_API( udfirpcontext )
  737. {
  738. UNREFERENCED_PARAMETER( dwCurrentPc );
  739. UNREFERENCED_PARAMETER( hCurrentProcess );
  740. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfIrpContext, dwProcessor, hCurrentThread );
  741. }
  742. DECLARE_API( udfirpcontextlite )
  743. {
  744. UNREFERENCED_PARAMETER( dwCurrentPc );
  745. UNREFERENCED_PARAMETER( hCurrentProcess );
  746. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfIrpContextLite, dwProcessor, hCurrentThread );
  747. }
  748. DECLARE_API( udfmcb )
  749. {
  750. UNREFERENCED_PARAMETER( dwCurrentPc );
  751. UNREFERENCED_PARAMETER( hCurrentProcess );
  752. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpLargeMcb, dwProcessor, hCurrentThread );
  753. }
  754. DECLARE_API( lcb )
  755. {
  756. UNREFERENCED_PARAMETER( dwCurrentPc );
  757. UNREFERENCED_PARAMETER( hCurrentProcess );
  758. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfLcb, dwProcessor, hCurrentThread );
  759. }
  760. DECLARE_API( pcb )
  761. {
  762. UNREFERENCED_PARAMETER( dwCurrentPc );
  763. UNREFERENCED_PARAMETER( hCurrentProcess );
  764. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfPcb, dwProcessor, hCurrentThread );
  765. }
  766. //
  767. // RAW ON DISC STUCTURE DUMP ROUTINES FOLLOW....
  768. //
  769. #define UdfNodeTypeName( InfoIndex) (UdfOnDiscTypeCodes[ InfoIndex].Text)
  770. #define UdfNodeTypeDumpFunction( InfoIndex) (UdfOnDiscTypeCodes[ InfoIndex].DumpRoutine)
  771. #define UdfNodeTypeSize( InfoIndex) (UdfOnDiscTypeCodes[ InfoIndex].Size)
  772. #define DUMP_EXTN_AD( type, realaddress, structure, element, label) \
  773. dprintf( "\n(%03x) %08x -> %s (LSN %08x, LEN %08x)", \
  774. FIELD_OFFSET(type, element), \
  775. ((PUCHAR)realaddress) + FIELD_OFFSET(type, element), \
  776. label, \
  777. structure.element.Lsn, structure.element.Len)
  778. static UCHAR RegIdBuffer[ 33];
  779. #define DUMP_REGID( type, realaddress, structure, element, label) \
  780. strncpy( RegIdBuffer, structure.element.Identifier, 23); \
  781. strncpy( RegIdBuffer+24, structure.element.Suffix, 8); \
  782. RegIdBuffer[23] = '\0'; \
  783. RegIdBuffer[32] = '\0'; \
  784. dprintf( "\n(%03x) %08x -> %s (Flags %02x, '%s':'%s')", \
  785. FIELD_OFFSET(type, element), \
  786. ((PUCHAR)realaddress) + FIELD_OFFSET(type, element), \
  787. label, \
  788. structure.element.Flags, \
  789. RegIdBuffer, RegIdBuffer+24)
  790. #define DUMP_LONGAD( type, realaddress, structure, element, label) \
  791. dprintf( "\n(%03x) %08x -> %s (Len %1x:%08x, StartLba %04x:%08x)",\
  792. FIELD_OFFSET(type, element), \
  793. ((PUCHAR)realaddress) + FIELD_OFFSET(type, element), \
  794. label, \
  795. structure.element.Length.Type, \
  796. structure.element.Length.Length, \
  797. structure.element.Start.Partition, \
  798. structure.element.Start.Lbn)
  799. #define DUMP_NSRLBA( type, realaddress, structure, element, label) \
  800. dprintf( "\n(%03x) %08x -> %s (%04x:%08x)", \
  801. FIELD_OFFSET(type, element), \
  802. ((PUCHAR)realaddress) + FIELD_OFFSET(type, element), \
  803. label, \
  804. structure.element.Partition, \
  805. structure.element.Lbn)
  806. DUMP_ROUTINE( DumpUdfOnDiscStructure)
  807. {
  808. DESTAG Tag;
  809. PDESTAG pTag;
  810. ULONG Result, InfoIndex;
  811. STRUCT_DUMP_ROUTINE Routine;
  812. RM( Address, Tag, pTag, PDESTAG, Result );
  813. InfoIndex = SearchTypeCodeIndex( Tag.Ident, UdfOnDiscTypeCodes);
  814. Routine = UdfNodeTypeDumpFunction( InfoIndex);
  815. if ( NULL == Routine) {
  816. dprintf( "Udf/Iso node tag 0x%04x unknown.\n", Tag.Ident);
  817. return;
  818. }
  819. //
  820. // And call it...
  821. //
  822. dprintf( "\n%s @ %08x\n", UdfNodeTypeName(InfoIndex), Address);
  823. (Routine)(Address, Options, &UdfOnDiscTypeCodes[InfoIndex]);
  824. }
  825. DUMP_ROUTINE( DumpUdfOnDiscTag)
  826. {
  827. DESTAG Tag;
  828. PDESTAG pTag;
  829. ULONG Result, InfoIndex;
  830. STRUCT_DUMP_ROUTINE Routine;
  831. RM( Address, Tag, pTag, PDESTAG, Result );
  832. InfoIndex = SearchTypeCodeIndex( Tag.Ident, UdfOnDiscTypeCodes);
  833. Routine = UdfNodeTypeDumpFunction( InfoIndex);
  834. DUMP16_WITH_OFFSET( DESTAG, Tag, Ident, "Ident" );
  835. dprintf(" (== %s)", UdfNodeTypeName(InfoIndex));
  836. DUMP16_WITH_OFFSET( DESTAG, Tag, Version, "Version");
  837. DUMP8_WITH_OFFSET( DESTAG, Tag, Checksum, "Checksum");
  838. DUMP16_WITH_OFFSET( DESTAG, Tag, Serial, "Serial");
  839. DUMP16_WITH_OFFSET( DESTAG, Tag, CRC, "CRC");
  840. DUMP16_WITH_OFFSET( DESTAG, Tag, CRCLen, "CRCLen");
  841. DUMP_WITH_OFFSET( DESTAG, Tag, Lbn, "(TagLoc)Lbn");
  842. }
  843. DUMP_ROUTINE( DumpUdfOnDiscPvd)
  844. {
  845. NSR_PVD Pvd;
  846. PNSR_PVD pPvd;
  847. ULONG Result;
  848. RM( Address, Pvd, pPvd, PNSR_PVD, Result );
  849. DUMP_EMBW_OFFSET( NSR_PVD, Address, Destag, "Destag" );
  850. DUMP_WITH_OFFSET( NSR_PVD, Pvd, VolDescSeqNum, "VolDescSeqNum" );
  851. DUMP_WITH_OFFSET( NSR_PVD, Pvd, Number, "Number" );
  852. Pvd.VolumeID[ Pvd.VolumeID[ 31]] = '\0';
  853. DUMP_RAW_TERM_STRN_OFFSET( NSR_PVD, Pvd, Address, VolumeID, "VolumeID");
  854. DUMP16_WITH_OFFSET( NSR_PVD, Pvd, VolSetSeq, "VolSetSeq" );
  855. DUMP16_WITH_OFFSET( NSR_PVD, Pvd, VolSetSeqMax, "VolSetSeqMax" );
  856. DUMP16_WITH_OFFSET( NSR_PVD, Pvd, Level, "Level" );
  857. DUMP16_WITH_OFFSET( NSR_PVD, Pvd, LevelMax, "LevelMax" );
  858. Pvd.VolSetID[ Pvd.VolSetID[ 127]] = '\0';
  859. DUMP_RAW_TERM_STRN_OFFSET( NSR_PVD, Pvd, Address, VolSetID, "VolSetID");
  860. DUMP_EXTN_AD( NSR_PVD, Address, Pvd, Abstract, "Abstract");
  861. DUMP_EXTN_AD( NSR_PVD, Address, Pvd, Copyright, "Copyright");
  862. DUMP_REGID( NSR_PVD, Address, Pvd, ImpUseID, "ImpUseID");
  863. DUMP_WITH_OFFSET( NSR_PVD, Pvd, Predecessor, "Predecessor" );
  864. DUMP16_WITH_OFFSET( NSR_PVD, Pvd, Flags, "Flags" );
  865. }
  866. DUMP_ROUTINE( DumpUdfOnDiscAnchor)
  867. {
  868. NSR_ANCHOR Avd;
  869. PNSR_ANCHOR pAvd;
  870. ULONG Result;
  871. RM( Address, Avd, pAvd, PNSR_ANCHOR, Result );
  872. DUMP_EMBW_OFFSET( NSR_ANCHOR, Address, Destag, "Destag" );
  873. DUMP_EXTN_AD( NSR_ANCHOR, Address, Avd, Main, "Main");
  874. DUMP_EXTN_AD( NSR_ANCHOR, Address, Avd, Reserve, "Reserve");
  875. }
  876. DUMP_ROUTINE( DumpUdfOnDiscVdp)
  877. {
  878. NSR_VDP Vdp;
  879. PNSR_VDP pVdp;
  880. ULONG Result;
  881. RM( Address, Vdp, pVdp, PNSR_VDP, Result );
  882. DUMP_EMBW_OFFSET( NSR_VDP, Address, Destag, "Destag" );
  883. DUMP_WITH_OFFSET( NSR_VDP, Vdp, VolDescSeqNum, "VolDescSeqNum" );
  884. DUMP_EXTN_AD( NSR_VDP, Address, Vdp, Next, "Next");
  885. }
  886. DUMP_ROUTINE( DumpUdfOnDiscPartDesc)
  887. {
  888. NSR_PART Part;
  889. PNSR_PART pPart;
  890. ULONG Result;
  891. RM( Address, Part, pPart, PNSR_PART, Result );
  892. dprintf("\n(3/10.5)\n");
  893. DUMP_EMBW_OFFSET( NSR_PART, Address, Destag, "Destag" );
  894. DUMP_WITH_OFFSET( NSR_PART, Part, VolDescSeqNum, "VolDescSeqNum" );
  895. DUMP16_WITH_OFFSET( NSR_PART, Part, Flags, "Flags" );
  896. DUMP16_WITH_OFFSET( NSR_PART, Part, Number, "Number" );
  897. DUMP_REGID( NSR_PART, Address, Part, ContentsID, "ContentsID");
  898. DUMP_WITH_OFFSET( NSR_PART, Part, AccessType, "AccessType" );
  899. DUMP_WITH_OFFSET( NSR_PART, Part, Start, "Start" );
  900. DUMP_WITH_OFFSET( NSR_PART, Part, Length, "Length" );
  901. DUMP_REGID( NSR_PART, Address, Part, ImpUseID, "ImpUseID");
  902. }
  903. DUMP_ROUTINE( DumpUdfOnDiscLvol)
  904. {
  905. NSR_LVOL Lv;
  906. PNSR_LVOL pLv;
  907. ULONG Result;
  908. RM( Address, Lv, pLv, PNSR_LVOL, Result );
  909. DUMP_EMBW_OFFSET( NSR_LVOL, Address, Destag, "Destag" );
  910. DUMP_WITH_OFFSET( NSR_LVOL, Lv, VolDescSeqNum, "VolDescSeqNum" );
  911. Lv.VolumeID[ Lv.VolumeID[ 127]] = '\0';
  912. DUMP_RAW_TERM_STRN_OFFSET( NSR_LVOL, Lv, Address, VolumeID, "VolumeID");
  913. DUMP_WITH_OFFSET( NSR_LVOL, Lv, BlockSize, "BlockSize" );
  914. DUMP_REGID( NSR_LVOL, Address, Lv, DomainID, "DomainID");
  915. DUMP_LONGAD( NSR_LVOL, Address, Lv, FSD, "FSD");
  916. DUMP_WITH_OFFSET( NSR_LVOL, Lv, MapTableLength, "MapTableLength" );
  917. DUMP_WITH_OFFSET( NSR_LVOL, Lv, MapTableCount, "MapTableCount" );
  918. DUMP_REGID( NSR_LVOL, Address, Lv, ImpUseID, "ImpUseID");
  919. DUMP_EXTN_AD( NSR_LVOL, Address, Lv, Integrity, "Integrity");
  920. DUMP_EMBW_OFFSET( NSR_LVOL, Address, MapTable, "MapTable" );
  921. }
  922. DUMP_ROUTINE( DumpUdfOnDiscLvInteg)
  923. {
  924. }
  925. DUMP_ROUTINE( DumpUdfOnDiscFsd)
  926. {
  927. NSR_FSD Fsd;
  928. PNSR_FSD pFsd;
  929. ULONG Result;
  930. STRING Str;
  931. RM( Address, Fsd, pFsd, PNSR_FSD, Result );
  932. DUMP_EMBW_OFFSET( NSR_FSD, Address, Destag, "Destag" );
  933. DUMP_EMBW_OFFSET( NSR_FSD, Address, Time, "Time" );
  934. DUMP16_WITH_OFFSET( NSR_FSD, Fsd, Level, "Level" );
  935. DUMP16_WITH_OFFSET( NSR_FSD, Fsd, LevelMax, "LevelMax" );
  936. DUMP_WITH_OFFSET( NSR_FSD, Fsd, FileSet, "FileSet" );
  937. DUMP_WITH_OFFSET( NSR_FSD, Fsd, FileSetDesc, "FileSetDesc" );
  938. Fsd.VolID[ Fsd.VolID[ 127]] = '\0';
  939. DUMP_RAW_TERM_STRN_OFFSET( NSR_FSD, Fsd, Address, VolID, "VolID ");
  940. Fsd.FileSetID[ Fsd.FileSetID[ 127]] = '\0';
  941. DUMP_RAW_TERM_STRN_OFFSET( NSR_FSD, Fsd, Address, FileSetID, "FileSetID");
  942. DUMP_LONGAD( NSR_FSD, Address, Fsd, IcbRoot, "IcbRoot ");
  943. DUMP_REGID( NSR_FSD, Address, Fsd, DomainID, "DomainID ");
  944. DUMP_LONGAD( NSR_FSD, Address, Fsd, NextExtent, "NextExtent");
  945. dprintf("\n");
  946. }
  947. DUMP_ROUTINE( DumpUdfOnDiscFid)
  948. {
  949. NSR_FID Fid;
  950. PNSR_FID pFid;
  951. ULONG Result;
  952. UCHAR Buffer[512];
  953. RM( Address, Fid, pFid, PNSR_FID, Result );
  954. dprintf("\nFid.Flags: ");
  955. PrintState( UdfFidFlags, Fid.Flags);
  956. DUMP_EMBW_OFFSET( NSR_FID, Address, Destag, "Destag" );
  957. DUMP16_WITH_OFFSET( NSR_FID, Fid, Version, "Version" );
  958. DUMP8_WITH_OFFSET( NSR_FID, Fid, Flags, "Flags" );
  959. DUMP8_WITH_OFFSET( NSR_FID, Fid, FileIDLen, "FileIDLen" );
  960. DUMP_LONGAD( NSR_FID, Address, Fid, Icb, "Icb");
  961. DUMP16_WITH_OFFSET( NSR_FID, Fid, ImpUseLen, "ImpUseLen" );
  962. DUMP_EMBW_OFFSET( NSR_FID, Address, ImpUse, "ImpUse" );
  963. dprintf("\nFileID @ %08x\n", ((PUCHAR)Address) + FIELD_OFFSET( NSR_FID, ImpUse) + Fid.ImpUseLen);
  964. }
  965. DUMP_ROUTINE( DumpUdfOnDiscIcbFile)
  966. {
  967. ICBFILE Icb;
  968. PICBFILE pIcb;
  969. ULONG Result;
  970. USHORT AllocType;
  971. ULONG AllocLength = 0;
  972. DWORD_PTR AllocDescsRealAddr;
  973. RM( Address, Icb, pIcb, PICBFILE, Result );
  974. dprintf("\nIcb.IcbTag.Flags: ");
  975. PrintState( UdfIcbTagFlags, Icb.Icbtag.Flags);
  976. DUMP_EMBW_OFFSET( ICBFILE, Address, Destag, "Destag" );
  977. // IcbTag embedded structure
  978. DUMP_WITH_OFFSET( ICBFILE, Icb, Icbtag.PriorDirectCount, "Icbtag.PriorDirectCount" );
  979. DUMP16_WITH_OFFSET( ICBFILE, Icb, Icbtag.StratType, "Icbtag.StratType" );
  980. dprintf(" == %s", (Icb.Icbtag.StratType <= MAX_VALID_ICB_STRAT) ? IcbStrategies[ Icb.Icbtag.StratType ] : "INVALID");
  981. DUMP16_WITH_OFFSET( ICBFILE, Icb, Icbtag.StratParm, "Icbtag.StratParm" );
  982. DUMP16_WITH_OFFSET( ICBFILE, Icb, Icbtag.MaxEntries, "Icbtag.MaxEntries" );
  983. DUMP16_WITH_OFFSET( ICBFILE, Icb, Icbtag.FileType, "Icbtag.FileType" );
  984. dprintf(" == %s", (Icb.Icbtag.FileType <= MAX_VALID_ICB_TYPE) ? IcbFileTypes[ Icb.Icbtag.FileType ] : "INVALID");
  985. DUMP_NSRLBA( ICBFILE, Address, Icb, Icbtag.IcbParent, "IcbTag.IcbParent");
  986. DUMP16_WITH_OFFSET( ICBFILE, Icb, Icbtag.Flags, "Icbtag.Flags" );
  987. // end icbtag
  988. DUMP_WITH_OFFSET( ICBFILE, Icb, UID, "UID" );
  989. DUMP_WITH_OFFSET( ICBFILE, Icb, GID, "GID" );
  990. DUMP_WITH_OFFSET( ICBFILE, Icb, Permissions, "Permissions" );
  991. DUMP16_WITH_OFFSET( ICBFILE, Icb, LinkCount, "LinkCount" );
  992. DUMP8_WITH_OFFSET( ICBFILE, Icb, RecordFormat, "RecordFormat" );
  993. DUMP8_WITH_OFFSET( ICBFILE, Icb, RecordDisplay, "RecordDisplay" );
  994. DUMP_WITH_OFFSET( ICBFILE, Icb, RecordLength, "RecordLength" );
  995. DUMP64_WITH_OFFSET( ICBFILE, Icb, InfoLength, "InfoLength" );
  996. DUMP64_WITH_OFFSET( ICBFILE, Icb, BlocksRecorded, "BlocksRecorded" );
  997. DUMP_EMBW_OFFSET( ICBFILE, Address, AccessTime, "AccessTime" );
  998. DUMP_EMBW_OFFSET( ICBFILE, Address, ModifyTime, "ModifyTime" );
  999. DUMP_EMBW_OFFSET( ICBFILE, Address, AttributeTime, "AttributeTime" );
  1000. DUMP_WITH_OFFSET( ICBFILE, Icb, Checkpoint, "Checkpoint" );
  1001. DUMP_LONGAD( ICBFILE, Address, Icb, IcbEA, "IcbEA");
  1002. DUMP_REGID( ICBFILE, Address, Icb, ImpUseID, "ImpUseID");
  1003. DUMP64_WITH_OFFSET( ICBFILE, Icb, UniqueID, "UniqueID" );
  1004. DUMP_WITH_OFFSET( ICBFILE, Icb, EALength, "EALength" );
  1005. DUMP_WITH_OFFSET( ICBFILE, Icb, AllocLength, "AllocLength" );
  1006. // lazy! *** dump EA list
  1007. DUMP_EMBW_OFFSET( ICBFILE, Address, EAs, "EAs[]" );
  1008. AllocDescsRealAddr = ((ULONG)Address) + FIELD_OFFSET( ICBFILE, EAs) + Icb.EALength;
  1009. AllocType = (ICBTAG_F_ALLOC_MASK & Icb.Icbtag.Flags);
  1010. dprintf("\n\nAllocation descriptors @ %08x\n\n", AllocDescsRealAddr );
  1011. if ((Options & 1) && (ICBTAG_F_ALLOC_IMMEDIATE != AllocType)) {
  1012. UCHAR Buffer[4*1024];
  1013. PUCHAR CurrentDesc = Buffer;
  1014. ULONG Size;
  1015. if ( sizeof(Buffer) < Icb.AllocLength) {
  1016. dprintf("Buffer too small\n");
  1017. return;
  1018. }
  1019. //
  1020. // Dump allocation descriptors
  1021. //
  1022. if (!ReadMemory( AllocDescsRealAddr, Buffer, Icb.AllocLength, &Result)) {
  1023. dprintf( "Failed to read memory @%p\n", AllocDescsRealAddr);
  1024. return;
  1025. }
  1026. while ( AllocLength < Icb.AllocLength) {
  1027. switch (AllocType) {
  1028. case ICBTAG_F_ALLOC_SHORT:
  1029. dprintf( " %08x , %01x:%08x\n", ((PSHORTAD)CurrentDesc)->Start,
  1030. ((PSHORTAD)CurrentDesc)->Length.Type, ((PSHORTAD)CurrentDesc)->Length.Length);
  1031. Size = sizeof( SHORTAD);
  1032. break;
  1033. case ICBTAG_F_ALLOC_LONG: {
  1034. PLONGAD Ad = (PLONGAD)CurrentDesc;
  1035. dprintf( " %04x:%08x , %01x:%08x, ImpUse[6] @ %08x\n",
  1036. Ad->Start.Partition, Ad->Start.Lbn,
  1037. Ad->Length.Type, Ad->Length.Length,
  1038. AllocDescsRealAddr + AllocLength + FIELD_OFFSET( LONGAD, ImpUse));
  1039. Size = sizeof( LONGAD);
  1040. }
  1041. break;
  1042. case ICBTAG_F_ALLOC_EXTENDED: {
  1043. PEXTAD Ad = (PEXTAD)CurrentDesc;
  1044. dprintf( " %04x:%08x , EL: %01x:%08x, RL: %01x:%08x, InfoL: %08x, ImpUse[2] @ %08x\n",
  1045. Ad->Start.Partition, Ad->Start.Lbn,
  1046. Ad->ExtentLen.Type, Ad->ExtentLen.Length,
  1047. Ad->RecordedLen.Type, Ad->RecordedLen.Length,
  1048. Ad->InfoLen,
  1049. AllocDescsRealAddr + AllocLength + FIELD_OFFSET( EXTAD, ImpUse));
  1050. Size = sizeof( EXTAD);
  1051. }
  1052. break;
  1053. default:
  1054. dprintf("INVALID Allocdesc type %d\n", AllocType);
  1055. return;
  1056. }
  1057. AllocLength += Size;
  1058. CurrentDesc += Size;
  1059. }
  1060. }
  1061. }
  1062. DUMP_ROUTINE( DumpUdfOnDiscIcbExtFile)
  1063. {
  1064. ICBEXTFILE Icb;
  1065. PICBEXTFILE pIcb;
  1066. ULONG Result;
  1067. USHORT AllocType;
  1068. ULONG AllocLength = 0;
  1069. DWORD_PTR AllocDescsRealAddr;
  1070. RM( Address, Icb, pIcb, PICBEXTFILE, Result );
  1071. dprintf("\nIcb.IcbTag.Flags: ");
  1072. PrintState( UdfIcbTagFlags, Icb.Icbtag.Flags);
  1073. DUMP_EMBW_OFFSET( ICBFILE, Address, Destag, "Destag" );
  1074. // IcbTag embedded structure
  1075. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, Icbtag.PriorDirectCount, "Icbtag.PriorDirectCount" );
  1076. DUMP16_WITH_OFFSET( ICBEXTFILE, Icb, Icbtag.StratType, "Icbtag.StratType" );
  1077. dprintf(" == %s", (Icb.Icbtag.StratType <= MAX_VALID_ICB_STRAT) ? IcbStrategies[ Icb.Icbtag.StratType ] : "INVALID");
  1078. DUMP16_WITH_OFFSET( ICBEXTFILE, Icb, Icbtag.StratParm, "Icbtag.StratParm" );
  1079. DUMP16_WITH_OFFSET( ICBEXTFILE, Icb, Icbtag.MaxEntries, "Icbtag.MaxEntries" );
  1080. DUMP16_WITH_OFFSET( ICBEXTFILE, Icb, Icbtag.FileType, "Icbtag.FileType" );
  1081. dprintf(" == %s", (Icb.Icbtag.FileType <= MAX_VALID_ICB_TYPE) ? IcbFileTypes[ Icb.Icbtag.FileType ] : "INVALID");
  1082. DUMP_NSRLBA( ICBEXTFILE, Address, Icb, Icbtag.IcbParent, "IcbTag.IcbParent");
  1083. DUMP16_WITH_OFFSET( ICBEXTFILE, Icb, Icbtag.Flags, "Icbtag.Flags" );
  1084. // end icbtag
  1085. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, UID, "UID" );
  1086. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, GID, "GID" );
  1087. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, Permissions, "Permissions" );
  1088. DUMP16_WITH_OFFSET( ICBEXTFILE, Icb, LinkCount, "LinkCount" );
  1089. DUMP8_WITH_OFFSET( ICBEXTFILE, Icb, RecordFormat, "RecordFormat" );
  1090. DUMP8_WITH_OFFSET( ICBEXTFILE, Icb, RecordDisplay, "RecordDisplay" );
  1091. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, RecordLength, "RecordLength" );
  1092. DUMP64_WITH_OFFSET( ICBEXTFILE, Icb, InfoLength, "InfoLength" );
  1093. DUMP64_WITH_OFFSET( ICBEXTFILE, Icb, ObjectSize, "ObjectSize" );
  1094. DUMP64_WITH_OFFSET( ICBEXTFILE, Icb, BlocksRecorded, "BlocksRecorded" );
  1095. DUMP_EMBW_OFFSET( ICBEXTFILE, Address, AccessTime, "AccessTime" );
  1096. DUMP_EMBW_OFFSET( ICBEXTFILE, Address, ModifyTime, "ModifyTime" );
  1097. DUMP_EMBW_OFFSET( ICBEXTFILE, Address, AttributeTime, "AttributeTime" );
  1098. DUMP_EMBW_OFFSET( ICBEXTFILE, Address, CreationTime, "CreationTime" );
  1099. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, Checkpoint, "Checkpoint" );
  1100. DUMP_LONGAD( ICBEXTFILE, Address, Icb, IcbEA, "IcbEA");
  1101. DUMP_LONGAD( ICBEXTFILE, Address, Icb, IcbStream, "IcbStream");
  1102. DUMP_REGID( ICBEXTFILE, Address, Icb, ImpUseID, "ImpUseID");
  1103. DUMP64_WITH_OFFSET( ICBEXTFILE, Icb, UniqueID, "UniqueID" );
  1104. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, EALength, "EALength" );
  1105. DUMP_WITH_OFFSET( ICBEXTFILE, Icb, AllocLength, "AllocLength" );
  1106. // lazy! *** dump EA list
  1107. DUMP_EMBW_OFFSET( ICBEXTFILE, Address, EAs, "EAs[]" );
  1108. AllocDescsRealAddr = ((ULONG)Address) + FIELD_OFFSET( ICBEXTFILE, EAs) + Icb.EALength;
  1109. AllocType = (ICBTAG_F_ALLOC_MASK & Icb.Icbtag.Flags);
  1110. dprintf("\n\nAllocation descriptors @ %08x\n\n", AllocDescsRealAddr );
  1111. if ((Options & 1) && (ICBTAG_F_ALLOC_IMMEDIATE != AllocType)) {
  1112. UCHAR Buffer[4*1024];
  1113. PUCHAR CurrentDesc = Buffer;
  1114. ULONG Size;
  1115. if ( sizeof(Buffer) < Icb.AllocLength) {
  1116. dprintf("Buffer too small\n");
  1117. return;
  1118. }
  1119. //
  1120. // Dump allocation descriptors
  1121. //
  1122. if (!ReadMemory( AllocDescsRealAddr, Buffer, Icb.AllocLength, &Result)) {
  1123. dprintf( "Failed to read memory @%p\n", AllocDescsRealAddr);
  1124. return;
  1125. }
  1126. while ( AllocLength < Icb.AllocLength) {
  1127. switch (AllocType) {
  1128. case ICBTAG_F_ALLOC_SHORT:
  1129. dprintf( " %08x , %01x:%08x\n", ((PSHORTAD)CurrentDesc)->Start,
  1130. ((PSHORTAD)CurrentDesc)->Length.Type, ((PSHORTAD)CurrentDesc)->Length.Length);
  1131. Size = sizeof( SHORTAD);
  1132. break;
  1133. case ICBTAG_F_ALLOC_LONG: {
  1134. PLONGAD Ad = (PLONGAD)CurrentDesc;
  1135. dprintf( " %04x:%08x , %01x:%08x, ImpUse[6] @ %08x\n",
  1136. Ad->Start.Partition, Ad->Start.Lbn,
  1137. Ad->Length.Type, Ad->Length.Length,
  1138. AllocDescsRealAddr + AllocLength + FIELD_OFFSET( LONGAD, ImpUse));
  1139. Size = sizeof( LONGAD);
  1140. }
  1141. break;
  1142. case ICBTAG_F_ALLOC_EXTENDED: {
  1143. PEXTAD Ad = (PEXTAD)CurrentDesc;
  1144. dprintf( " %04x:%08x , EL: %01x:%08x, RL: %01x:%08x, InfoL: %08x, ImpUse[2] @ %08x\n",
  1145. Ad->Start.Partition, Ad->Start.Lbn,
  1146. Ad->ExtentLen.Type, Ad->ExtentLen.Length,
  1147. Ad->RecordedLen.Type, Ad->RecordedLen.Length,
  1148. Ad->InfoLen,
  1149. AllocDescsRealAddr + AllocLength + FIELD_OFFSET( EXTAD, ImpUse));
  1150. Size = sizeof( EXTAD);
  1151. }
  1152. break;
  1153. default:
  1154. dprintf("INVALID Allocdesc type %d\n", AllocType);
  1155. return;
  1156. }
  1157. AllocLength += Size;
  1158. CurrentDesc += Size;
  1159. }
  1160. }
  1161. }
  1162. DECLARE_API( udftag )
  1163. {
  1164. UNREFERENCED_PARAMETER( dwCurrentPc );
  1165. UNREFERENCED_PARAMETER( hCurrentProcess );
  1166. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfOnDiscTag, dwProcessor, hCurrentThread );
  1167. }
  1168. DECLARE_API( ud )
  1169. {
  1170. UNREFERENCED_PARAMETER( dwCurrentPc );
  1171. UNREFERENCED_PARAMETER( hCurrentProcess );
  1172. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpUdfOnDiscStructure, dwProcessor, hCurrentThread );
  1173. }