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.

821 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: DfsDump.c
  6. //
  7. // Contents: DFS driver debugging dump.
  8. //
  9. // Classes:
  10. //
  11. // Functions: main
  12. // Usage
  13. // DfsReadAndPrintString - Print a string in a dfs structure
  14. // DumpPkt - Dump PKT, entries and services
  15. // DumpDevs - Dump device structures
  16. // DumpFcbs - Dump FCB hash table and all FCBs
  17. //
  18. // History: 03 Jan 92 Alanw Created.
  19. //
  20. //--------------------------------------------------------------------------
  21. #include <ntos.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <tdi.h>
  25. #include <windows.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <lmcons.h>
  29. #include "nodetype.h"
  30. #include "dfsmrshl.h"
  31. #include "dfsfsctl.h"
  32. #include "pkt.h"
  33. #include "dsstruc.h"
  34. #include "fcbsup.h"
  35. #include "dsfsctl.h"
  36. #include "attach.h"
  37. #include "testsup.h"
  38. #define START_OF_NONPAGED_MEM 0x0ff000000
  39. VOID
  40. Usage(
  41. char* progname
  42. );
  43. NTSTATUS
  44. DfsReadAndPrintString(
  45. PUNICODE_STRING pStr
  46. );
  47. VOID
  48. DfsDump(
  49. PVOID Ptr
  50. );
  51. VOID
  52. DfsDumpDfsService( PDFS_SERVICE Ptr);
  53. VOID
  54. DfsDumpDSMachine( PDS_MACHINE Ptr);
  55. VOID
  56. DfsDumpDSTransport( PDS_TRANSPORT Ptr);
  57. VOID
  58. DumpPkt( void );
  59. VOID
  60. DumpDevs( void );
  61. VOID
  62. DumpFcbs( void );
  63. #define MemUsage(ptr, size) { \
  64. if (((ULONG) (ptr))>START_OF_NONPAGED_MEM) { \
  65. NonPagedMem = NonPagedMem + size; \
  66. } else { \
  67. PagedMem = PagedMem + size; \
  68. } \
  69. }
  70. #define MemUsageStr(str) MemUsage((str).Buffer, (str).MaximumLength)
  71. ULONG NonPagedMem, PagedMem;
  72. DS_DATA DfsData, *pDfsData;
  73. VCB Vcb;
  74. BOOLEAN Dflag = FALSE; // dump device objects
  75. BOOLEAN Fflag = FALSE; // dump FCB hash table and FCBs
  76. BOOLEAN Pflag = FALSE; // dump PKT and services
  77. BOOLEAN Vflag = FALSE; // verbose - dump all fields
  78. PWSTR gpwszServer = NULL;
  79. __cdecl main(argc, argv)
  80. int argc;
  81. char **argv;
  82. {
  83. FILE_DFS_READ_STRUCT_PARAM RsParam;
  84. PLIST_ENTRY Link;
  85. char* progname;
  86. NTSTATUS Stat;
  87. VCB *pVcb;
  88. WCHAR wszServer[CNLEN + 1];
  89. BOOL fInvalidArg = FALSE;
  90. printf("\n");
  91. progname = argv[0];
  92. // if (argc >= 3) {
  93. // Usage(progname);
  94. // return 3;
  95. // }
  96. while (argc > 1 && *argv[1] == '-') {
  97. char *pszFlags = &argv[1][1];
  98. while (*pszFlags) {
  99. switch (*pszFlags++) {
  100. case 'a':
  101. Dflag = Fflag = Pflag = TRUE;
  102. break;
  103. case 'd':
  104. Dflag = TRUE;
  105. break;
  106. case 'f':
  107. Fflag = TRUE;
  108. break;
  109. case 'p':
  110. Pflag = TRUE;
  111. break;
  112. case 'v':
  113. Vflag = TRUE;
  114. break;
  115. case 's':
  116. if(*pszFlags != ':' || strlen(pszFlags) > CNLEN ||
  117. strlen(pszFlags) < 2) {
  118. Usage(progname);
  119. fInvalidArg = TRUE;
  120. break;
  121. }
  122. pszFlags++;
  123. mbstowcs(wszServer,pszFlags, strlen(pszFlags) + 1);
  124. gpwszServer = wszServer;
  125. pszFlags += strlen(pszFlags);
  126. break;
  127. default:
  128. Usage(progname);
  129. fInvalidArg = TRUE;
  130. }
  131. }
  132. argv++;
  133. argc--;
  134. }
  135. if(fInvalidArg)
  136. return 3;
  137. if (!Dflag && !Fflag && !Pflag) {
  138. Pflag = TRUE;
  139. }
  140. //
  141. // Dump out the data structures of the DFS driver.
  142. //
  143. RsParam.StructKey = (ULONG)NULL;
  144. RsParam.TypeCode = DSFS_NTC_DATA_HEADER;
  145. RsParam.ByteCount = sizeof DfsData;
  146. Stat = DsfsReadStruct(&RsParam, (PUCHAR)&DfsData);
  147. if (!NT_SUCCESS(Stat)) {
  148. printf("%s: DsfsReadStruct for DfsData returned %08x\n", progname, Stat);
  149. return 3;
  150. }
  151. Link = DfsData.VcbQueue.Flink;
  152. pVcb = CONTAINING_RECORD(Link, VCB, VcbLinks);
  153. RsParam.StructKey = (ULONG) pVcb;
  154. RsParam.TypeCode = DSFS_NTC_VCB;
  155. RsParam.ByteCount = sizeof Vcb;
  156. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &Vcb);
  157. if (!NT_SUCCESS(Stat)) {
  158. return 3;
  159. }
  160. pDfsData = CONTAINING_RECORD((Vcb.VcbLinks.Blink), DS_DATA, VcbQueue);
  161. MemUsage(pDfsData, RsParam.ByteCount);
  162. MemUsageStr(DfsData.LogRootDevName);
  163. if (Vflag) {
  164. printf("DfsData @ %08x:\t", pDfsData);
  165. DfsDump(&DfsData);
  166. printf("\n");
  167. } else {
  168. printf("DfsData @ %08x:\n\n", pDfsData);
  169. }
  170. if (Dflag) {
  171. DumpDevs();
  172. }
  173. if (Fflag) {
  174. DumpFcbs();
  175. }
  176. if (Pflag) {
  177. DumpPkt();
  178. }
  179. printf("Total Paged Mem Used: %d\n", PagedMem);
  180. printf("Total NonPaged Mem Used: %d\n", NonPagedMem);
  181. return 0;
  182. }
  183. VOID
  184. Usage(
  185. char* progname
  186. ) {
  187. printf("Usage: %s [-vdfp] [-s:server]\n", progname);
  188. printf(" -v\tVerbose\n");
  189. printf(" -d\tDump device structures\n");
  190. printf(" -f\tDump FCB structures\n");
  191. printf(" -p\tDump PKT structures(default)\n");
  192. printf(" -s:server\tDump the PKT on the indicated Cairo server\n");
  193. exit (1);
  194. }
  195. NTSTATUS
  196. DfsReadAndPrintString(
  197. PUNICODE_STRING pStr
  198. ) {
  199. FILE_DFS_READ_STRUCT_PARAM RsParam;
  200. UCHAR Buf[500];
  201. UNICODE_STRING Str;
  202. NTSTATUS Stat;
  203. if (pStr->Buffer == NULL) {
  204. printf("*NULL*");
  205. return STATUS_SUCCESS;
  206. }
  207. if (pStr->Length > sizeof Buf) {
  208. printf("*StringTooLong*");
  209. return STATUS_SUCCESS;
  210. }
  211. RsParam.StructKey = (ULONG) pStr->Buffer;
  212. RsParam.TypeCode = 0;
  213. RsParam.ByteCount = pStr->Length;
  214. if (! NT_SUCCESS( Stat = DsfsReadStruct(&RsParam, Buf)))
  215. return Stat;
  216. // MemUsage(RsParam.StructKey, RsParam.ByteCount);
  217. Str = *pStr;
  218. Str.Buffer = (WCHAR *)Buf;
  219. printf("%wZ", &Str);
  220. return STATUS_SUCCESS;
  221. }
  222. //+-------------------------------------------------------------------
  223. //
  224. // Function: DumpPkt, local
  225. //
  226. // Synopsis: This routine will dump the contents of the PKT and
  227. // all the associated data.
  228. //
  229. // Arguments: None
  230. //
  231. // Returns: None
  232. //
  233. // Requires: DfsData must have previously been loaded into memory.
  234. //
  235. //--------------------------------------------------------------------
  236. VOID
  237. DumpPkt( void )
  238. {
  239. FILE_DFS_READ_STRUCT_PARAM RsParam;
  240. PLIST_ENTRY Link, Sentinel = NULL;
  241. DFS_PKT_ENTRY PktEntry, *pPktEntry;
  242. DFS_SERVICE Service;
  243. PDS_TRANSPORT pTransport;
  244. DFS_MACHINE_ENTRY MachEntry;
  245. PDS_MACHINE pMachine;
  246. NTSTATUS Stat;
  247. ULONG i, j, k;
  248. char* pszMsg;
  249. pTransport = (PDS_TRANSPORT) malloc ( sizeof(DS_TRANSPORT)+512*sizeof(UCHAR) );
  250. pMachine = (PDS_MACHINE) malloc ( sizeof(DS_MACHINE)+512*sizeof(PVOID) );
  251. //
  252. // Now we take care of the Pkt dump.
  253. //
  254. if (Vflag)
  255. {
  256. printf("Pkt @ %08x:\t", &(pDfsData->Pkt));
  257. DfsDump(&(DfsData.Pkt));
  258. printf("\n");
  259. }
  260. else
  261. {
  262. //
  263. // In here place whatever needs to be dumped from Pkt.
  264. //
  265. printf("Pkt @ %08x:\n", &(pDfsData->Pkt));
  266. printf("\tDomainPktEntry @ %08x\n", DfsData.Pkt.DomainPktEntry);
  267. printf("\n");
  268. }
  269. //
  270. // We now work with the Pkt Entries in the Pkt.
  271. //
  272. Link = DfsData.Pkt.EntryList.Flink;
  273. for (i=0; i<DfsData.Pkt.EntryCount; i++)
  274. {
  275. pPktEntry = CONTAINING_RECORD(Link, DFS_PKT_ENTRY, Link);
  276. RsParam.StructKey = (ULONG) pPktEntry;
  277. RsParam.TypeCode = DSFS_NTC_PKT_ENTRY;
  278. RsParam.ByteCount = sizeof(DFS_PKT_ENTRY);
  279. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &PktEntry);
  280. if (!NT_SUCCESS(Stat))
  281. {
  282. exit(3);
  283. }
  284. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  285. MemUsageStr(PktEntry.Id.Prefix);
  286. if (Vflag)
  287. {
  288. printf("\nPktEntry @ %08x:\t",pPktEntry);
  289. DfsDump(&PktEntry);
  290. printf("\n");
  291. }
  292. else
  293. {
  294. //
  295. // Place any other fields from PktEntry that need to
  296. // be dumped out here.
  297. //
  298. printf("\tPktEntry @ %08x:\t",pPktEntry);
  299. printf("EntryId.Prefix: ");
  300. Stat = DfsReadAndPrintString(&(PktEntry.Id.Prefix));
  301. printf("\n");
  302. }
  303. //
  304. // We now need to deal with the local service
  305. // in the Pkt entry.
  306. //
  307. if (PktEntry.LocalService)
  308. {
  309. RsParam.StructKey = (ULONG) PktEntry.LocalService;
  310. RsParam.TypeCode = 0;
  311. RsParam.ByteCount = sizeof(DFS_SERVICE);
  312. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &Service);
  313. if (!NT_SUCCESS(Stat))
  314. {
  315. exit(3);
  316. }
  317. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  318. MemUsageStr(Service.Name);
  319. MemUsageStr(Service.Address);
  320. if (Vflag)
  321. {
  322. printf("\nLOCAL_SERVICE:\n");
  323. DfsDumpDfsService(&Service);
  324. }
  325. else
  326. {
  327. printf("\t\tLocalService: ");
  328. DfsReadAndPrintString((PUNICODE_STRING)&(Service.Address));
  329. printf("\n");
  330. }
  331. }
  332. //
  333. // We now need to dump the service list in the EntryInfo
  334. // structure in the PktEntry above.
  335. //
  336. for (j=0; j<PktEntry.Info.ServiceCount; j++)
  337. {
  338. RsParam.StructKey = (ULONG) (PktEntry.Info.ServiceList
  339. + j);
  340. RsParam.TypeCode = 0;
  341. RsParam.ByteCount = sizeof(DFS_SERVICE);
  342. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &Service);
  343. if (!NT_SUCCESS(Stat))
  344. {
  345. exit(3);
  346. }
  347. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  348. MemUsageStr(Service.Name);
  349. MemUsageStr(Service.Address);
  350. if (PktEntry.Info.ServiceList + j == PktEntry.ActiveService)
  351. {
  352. pszMsg = " (active)";
  353. }
  354. else
  355. {
  356. pszMsg = "";
  357. }
  358. if (Vflag)
  359. {
  360. printf("\nSERVICE# %d%s:\n", j, pszMsg);
  361. DfsDumpDfsService(&Service);
  362. //
  363. // Now we need to dump the MACHINE_ADDR structure as well.
  364. //
  365. RsParam.StructKey = (ULONG) (Service.pMachEntry);
  366. RsParam.TypeCode = 0;
  367. RsParam.ByteCount = sizeof(DFS_MACHINE_ENTRY);
  368. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &MachEntry);
  369. if (!NT_SUCCESS(Stat))
  370. {
  371. printf("Failed to read pDFS_MACHINE_ENTRY address %08lx\n", Stat);
  372. exit(3);
  373. }
  374. RsParam.StructKey = (ULONG) MachEntry.pMachine;
  375. RsParam.TypeCode = 0;
  376. RsParam.ByteCount = sizeof(DS_MACHINE);
  377. Stat = DsfsReadStruct(&RsParam, (PUCHAR) pMachine);
  378. if (!NT_SUCCESS(Stat))
  379. {
  380. exit(3);
  381. }
  382. if (pMachine->cTransports != 0)
  383. {
  384. RsParam.StructKey = (ULONG) (((CHAR *) MachEntry.pMachine) + DS_MACHINE_SIZE);
  385. RsParam.TypeCode = 0;
  386. RsParam.ByteCount = (USHORT) pMachine->cTransports*sizeof(PDS_TRANSPORT);
  387. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &pMachine->rpTrans[0]);
  388. if (!NT_SUCCESS(Stat))
  389. {
  390. exit(3);
  391. }
  392. }
  393. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  394. DfsDumpDSMachine(pMachine);
  395. //
  396. // We really need to read the PrincipalName also but lets skip
  397. // for now.
  398. //
  399. for (k=0; k<pMachine->cTransports; k++)
  400. {
  401. RsParam.StructKey = (ULONG) (pMachine->rpTrans[k]);
  402. RsParam.ByteCount = DS_TRANSPORT_SIZE;
  403. RsParam.TypeCode = 0;
  404. Stat = DsfsReadStruct(&RsParam, (PUCHAR) pTransport);
  405. if (!NT_SUCCESS(Stat))
  406. exit(3);
  407. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  408. //
  409. // Now we need to read the actual address buffer in.
  410. //
  411. if (pTransport->taddr.AddressLength != 0)
  412. {
  413. RsParam.StructKey = (ULONG) (((CHAR *) (pMachine->rpTrans[k])) + DS_TRANSPORT_SIZE);
  414. RsParam.ByteCount = pTransport->taddr.AddressLength;
  415. RsParam.TypeCode = 0;
  416. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &pTransport->taddr.Address[0]);
  417. if (!NT_SUCCESS(Stat))
  418. exit(3);
  419. }
  420. DfsDumpDSTransport(pTransport);
  421. }
  422. }
  423. else
  424. {
  425. printf("\t\tService#%d%s: ", j, pszMsg);
  426. DfsReadAndPrintString((PUNICODE_STRING) &(Service.Address));
  427. printf("\n");
  428. }
  429. }
  430. printf("\n");
  431. Link = PktEntry.Link.Flink;
  432. }
  433. free(pTransport);
  434. free(pMachine);
  435. }
  436. //+-------------------------------------------------------------------
  437. //
  438. // Function: DumpDevs, local
  439. //
  440. // Synopsis: This routine will dump the contents of the devices
  441. // associated with the DFS FSD.
  442. //
  443. // Arguments: None
  444. //
  445. // Returns: None
  446. //
  447. // Requires: DfsData must have previously been loaded into memory.
  448. //
  449. //--------------------------------------------------------------------
  450. VOID
  451. DumpDevs( void )
  452. {
  453. FILE_DFS_READ_STRUCT_PARAM RsParam;
  454. PLIST_ENTRY Link, Sentinel = NULL;
  455. PROVIDER_DEF Provider;
  456. DFS_VOLUME_OBJECT DfsVdo, *pDfsVdo;
  457. LOGICAL_ROOT_DEVICE_OBJECT DfsLrdo, *pDfsLrdo;
  458. NTSTATUS Stat;
  459. ULONG i;
  460. //
  461. // Now we dump the Provider list.
  462. //
  463. if (DfsData.pProvider)
  464. {
  465. for (i=0; i<(ULONG)DfsData.cProvider; i++)
  466. {
  467. RsParam.StructKey = (ULONG) (DfsData.pProvider+i);
  468. RsParam.TypeCode = DSFS_NTC_PROVIDER;
  469. RsParam.ByteCount = sizeof(PROVIDER_DEF);
  470. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &Provider);
  471. if (NT_SUCCESS(Stat))
  472. {
  473. break;
  474. }
  475. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  476. MemUsageStr(Provider.DeviceName);
  477. printf("Provider#%d @ %08x:\t", i, RsParam.StructKey);
  478. if (Vflag)
  479. {
  480. DfsDump(&Provider);
  481. }
  482. else
  483. {
  484. printf("Device Name: ");
  485. DfsReadAndPrintString(&(Provider.DeviceName));
  486. }
  487. printf("\n");
  488. }
  489. printf("\n");
  490. }
  491. //
  492. // Dump the file system device object
  493. //
  494. if (Vflag)
  495. {
  496. DEVICE_OBJECT Fsdo, *pFsdo;
  497. pFsdo = DfsData.FileSysDeviceObject;
  498. RsParam.StructKey = (ULONG) pFsdo;
  499. RsParam.TypeCode = IO_TYPE_DEVICE;
  500. RsParam.ByteCount = sizeof Fsdo;
  501. Stat = DsfsReadStruct(&RsParam, (PUCHAR) &Fsdo);
  502. if (NT_SUCCESS(Stat))
  503. {
  504. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  505. printf("FileSysDeviceObject @ %08x:\t", pFsdo);
  506. DfsDump(&Fsdo);
  507. printf("\n");
  508. }
  509. }
  510. else
  511. MemUsage(DfsData.FileSysDeviceObject, sizeof (DEVICE_OBJECT));
  512. //
  513. // Now we look at the volume device objects
  514. //
  515. for (Link = DfsData.AVdoQueue.Flink;
  516. Link != Sentinel;
  517. Link = DfsVdo.VdoLinks.Flink) {
  518. pDfsVdo = CONTAINING_RECORD( Link, DFS_VOLUME_OBJECT, VdoLinks );
  519. RsParam.StructKey = (ULONG) pDfsVdo;
  520. RsParam.TypeCode = IO_TYPE_DEVICE;
  521. RsParam.ByteCount = sizeof DfsVdo;
  522. if (! NT_SUCCESS( Stat = DsfsReadStruct(&RsParam, (PUCHAR)&DfsVdo)))
  523. exit(3);
  524. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  525. MemUsageStr(DfsVdo.Provider.DeviceName);
  526. if (Link == DfsData.AVdoQueue.Flink)
  527. Sentinel = DfsVdo.VdoLinks.Blink;
  528. if (Vflag) {
  529. printf("DfsVdo @ %08x:\t", pDfsVdo);
  530. DfsDump(&DfsVdo);
  531. printf("\n");
  532. } else {
  533. printf("DfsVdo @ %08x:\t", pDfsVdo);
  534. Stat = DfsReadAndPrintString(&DfsVdo.Provider.DeviceName);
  535. printf("\n");
  536. }
  537. }
  538. //
  539. // Now we look at the Vcbs (logical root device object extensions).
  540. //
  541. for (Link = DfsData.VcbQueue.Flink;
  542. Link != Sentinel;
  543. Link = DfsLrdo.Vcb.VcbLinks.Flink) {
  544. pDfsLrdo = CONTAINING_RECORD( Link, LOGICAL_ROOT_DEVICE_OBJECT, Vcb.VcbLinks );
  545. RsParam.StructKey = (ULONG) pDfsLrdo;
  546. RsParam.TypeCode = IO_TYPE_DEVICE;
  547. RsParam.ByteCount = sizeof DfsLrdo;
  548. if (! NT_SUCCESS( Stat = DsfsReadStruct(&RsParam, (PUCHAR)&DfsLrdo)))
  549. exit(3);
  550. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  551. MemUsageStr(DfsLrdo.Vcb.LogicalRoot);
  552. MemUsageStr(DfsLrdo.Vcb.LogRootPrefix);
  553. if (Link == DfsData.VcbQueue.Flink)
  554. Sentinel = DfsLrdo.Vcb.VcbLinks.Blink;
  555. if (Vflag) {
  556. printf("DfsLrdo @ %08x:\t", pDfsLrdo);
  557. DfsDump(&DfsLrdo);
  558. printf("\n");
  559. } else {
  560. printf("DfsLrdo @ %08x:\t", pDfsLrdo);
  561. Stat = DfsReadAndPrintString(&DfsLrdo.Vcb.LogicalRoot);
  562. if (! NT_SUCCESS(Stat))
  563. exit(3);
  564. printf("\n\tPrefix =\t");
  565. Stat = DfsReadAndPrintString(&DfsLrdo.Vcb.LogRootPrefix);
  566. if (! NT_SUCCESS(Stat) )
  567. exit(3);
  568. printf("\n");
  569. }
  570. }
  571. }
  572. //+-------------------------------------------------------------------
  573. //
  574. // Function: DumpFcbs, local
  575. //
  576. // Synopsis: This routine will dump the contents of the FCB hash
  577. // table, and all the associated FCBs.
  578. //
  579. // Arguments: None
  580. //
  581. // Returns: None
  582. //
  583. // Requires: DfsData must have previously been loaded into memory.
  584. //
  585. //--------------------------------------------------------------------
  586. VOID
  587. DumpFcbs( void )
  588. {
  589. FILE_DFS_READ_STRUCT_PARAM RsParam;
  590. struct _FCB_HASH{
  591. FCB_HASH_TABLE FcbHash;
  592. LIST_ENTRY FcbHashBuckets2[127];
  593. } FcbHashTab, *pFcbHashTab;
  594. FCB Fcb, *pFcb;
  595. NTSTATUS Stat;
  596. ULONG i;
  597. RsParam.StructKey = (ULONG) (pFcbHashTab =
  598. (struct _FCB_HASH *)DfsData.FcbHashTable);
  599. RsParam.TypeCode = 0;
  600. RsParam.ByteCount = sizeof (NODE_TYPE_CODE) + sizeof (NODE_BYTE_SIZE);
  601. if (! NT_SUCCESS( Stat = DsfsReadStruct(&RsParam, (PUCHAR) &FcbHashTab))) {
  602. printf("Error accessing DfsData.FcbHashTable\n");
  603. exit(4);
  604. }
  605. RsParam.StructKey = (ULONG) DfsData.FcbHashTable;
  606. RsParam.TypeCode = FcbHashTab.FcbHash.NodeTypeCode;
  607. RsParam.ByteCount = FcbHashTab.FcbHash.NodeByteSize;
  608. if (! NT_SUCCESS( Stat = DsfsReadStruct(&RsParam, (PUCHAR) &FcbHashTab))) {
  609. printf("Error accessing DfsData.FcbHashTable\n");
  610. exit(4);
  611. }
  612. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  613. if (Vflag) {
  614. printf("\nFcbHashTable @ %08x:\t", DfsData.FcbHashTable);
  615. DfsDump(&FcbHashTab);
  616. } else {
  617. printf("FcbHashTable @ %08x\n", DfsData.FcbHashTable);
  618. }
  619. //
  620. // Now we look at the FCBs.
  621. //
  622. for (i = 0; i <= FcbHashTab.FcbHash.HashMask; i++) {
  623. PLIST_ENTRY ListHead, Link, Sentinel = NULL;
  624. ListHead = &FcbHashTab.FcbHash.HashBuckets[i];
  625. if (ListHead->Flink == NULL) // Never initialized
  626. continue;
  627. if ((PUCHAR) ListHead->Flink ==
  628. ((PUCHAR)ListHead - (PUCHAR) &FcbHashTab) + (PUCHAR)pFcbHashTab) {
  629. printf(" HashBucket[%2d] ==> <empty>\n", i);
  630. continue;
  631. }
  632. printf(" HashBucket[%2d] ==> ", i);
  633. for (Link = ListHead->Flink;
  634. Link != Sentinel;
  635. Link = Fcb.HashChain.Flink) {
  636. pFcb = CONTAINING_RECORD( Link, FCB, HashChain );
  637. RsParam.StructKey = (ULONG) pFcb;
  638. RsParam.TypeCode = DSFS_NTC_FCB;
  639. RsParam.ByteCount = sizeof Fcb;
  640. if (! NT_SUCCESS( Stat = DsfsReadStruct(&RsParam, (PUCHAR)&Fcb))) {
  641. printf("Error accessing Fcb\n");
  642. exit(4);
  643. }
  644. MemUsage(RsParam.StructKey, RsParam.ByteCount);
  645. if (Link == ListHead->Flink)
  646. Sentinel = Fcb.HashChain.Blink;
  647. if (Vflag) {
  648. printf("Fcb @ %08x:\t", pFcb);
  649. DfsDump(&Fcb);
  650. printf("\n");
  651. } else {
  652. printf("%08x ", pFcb);
  653. }
  654. }
  655. printf("\n");
  656. }
  657. printf("\n");
  658. }