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.

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