Windows NT 4.0 source code leak
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.

1411 lines
30 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Ntfs.c
  5. Abstract:
  6. WinDbg Extension Api for examining Ntfs specific data structures
  7. Author:
  8. Keith Kaplan [KeithKa] 24-Apr-96
  9. Portions by Jeff Havens
  10. Environment:
  11. User Mode.
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #include <nodetype.h>
  16. #include <ntfs.h>
  17. #include <ntfsstru.h>
  18. #include "gentable.h"
  19. #pragma hdrstop
  20. #define DUMP_WITH_OFFSET(t,s,e,l) dprintf("\n %s %8x offset %3x", l, s.e, FIELD_OFFSET(t,e))
  21. typedef struct _STATE {
  22. ULONG mask;
  23. ULONG value;
  24. CHAR *pszname;
  25. } STATE;
  26. STATE VcbState[] = {
  27. { VCB_STATE_VOLUME_MOUNTED, VCB_STATE_VOLUME_MOUNTED, "Mounted" },
  28. { VCB_STATE_LOCKED, VCB_STATE_LOCKED, "Locked" },
  29. { VCB_STATE_REMOVABLE_MEDIA, VCB_STATE_REMOVABLE_MEDIA, "RemovableMedia" },
  30. { VCB_STATE_VOLUME_MOUNTED_DIRTY, VCB_STATE_VOLUME_MOUNTED_DIRTY, "MountedDirty" },
  31. { VCB_STATE_RESTART_IN_PROGRESS, VCB_STATE_RESTART_IN_PROGRESS, "RestartInProgress" },
  32. { VCB_STATE_FLAG_SHUTDOWN, VCB_STATE_FLAG_SHUTDOWN, "FlagShutdown" },
  33. { VCB_STATE_NO_SECONDARY_AVAILABLE, VCB_STATE_NO_SECONDARY_AVAILABLE, "NoSecondaryAvailable" },
  34. { VCB_STATE_RELOAD_FREE_CLUSTERS, VCB_STATE_RELOAD_FREE_CLUSTERS, "ReloadFreeClusters" },
  35. { VCB_STATE_ALREADY_BALANCED, VCB_STATE_ALREADY_BALANCED, "AlreadyBalanced" },
  36. { VCB_STATE_VOL_PURGE_IN_PROGRESS, VCB_STATE_VOL_PURGE_IN_PROGRESS, "VolPurgeInProgress" },
  37. { VCB_STATE_TEMP_VPB, VCB_STATE_TEMP_VPB, "TempVpb" },
  38. { VCB_STATE_PERFORMED_DISMOUNT, VCB_STATE_PERFORMED_DISMOUNT, "PerformedDismount" },
  39. { VCB_STATE_VALID_LOG_HANDLE, VCB_STATE_VALID_LOG_HANDLE, "ValidLogHandle" },
  40. { VCB_STATE_DELETE_UNDERWAY, VCB_STATE_DELETE_UNDERWAY, "DeleteUnderway" },
  41. { VCB_STATE_REDUCED_MFT, VCB_STATE_REDUCED_MFT, "ReducedMft" },
  42. { 0 }
  43. };
  44. STATE FcbState[] = {
  45. { FCB_STATE_FILE_DELETED, FCB_STATE_FILE_DELETED, "FileDeleted" },
  46. { FCB_STATE_NONPAGED, FCB_STATE_NONPAGED, "Nonpaged" },
  47. { FCB_STATE_PAGING_FILE, FCB_STATE_PAGING_FILE, "PagingFile" },
  48. { FCB_STATE_DUP_INITIALIZED, FCB_STATE_DUP_INITIALIZED, "DupInitialized" },
  49. { FCB_STATE_UPDATE_STD_INFO, FCB_STATE_UPDATE_STD_INFO, "UpdateStdInfo" },
  50. { FCB_STATE_PRIMARY_LINK_DELETED, FCB_STATE_PRIMARY_LINK_DELETED, "PrimaryLinkDeleted" },
  51. { FCB_STATE_IN_FCB_TABLE, FCB_STATE_IN_FCB_TABLE, "InFcbTable" },
  52. { FCB_STATE_SYSTEM_FILE, FCB_STATE_SYSTEM_FILE, "SystemFile" },
  53. { FCB_STATE_COMPOUND_DATA, FCB_STATE_COMPOUND_DATA, "CompoundData" },
  54. { FCB_STATE_COMPOUND_INDEX, FCB_STATE_COMPOUND_INDEX, "CompoundIndex" },
  55. { FCB_STATE_LARGE_STD_INFO, FCB_STATE_LARGE_STD_INFO, "LargeStdInfo" },
  56. { 0 }
  57. };
  58. STATE CcbState[] = {
  59. { CCB_FLAG_IGNORE_CASE, CCB_FLAG_IGNORE_CASE, "IgnoreCase" },
  60. { CCB_FLAG_OPEN_AS_FILE, CCB_FLAG_OPEN_AS_FILE, "OpenAsFile" },
  61. { CCB_FLAG_WILDCARD_IN_EXPRESSION, CCB_FLAG_WILDCARD_IN_EXPRESSION, "WildcardInExpression" },
  62. { CCB_FLAG_OPEN_BY_FILE_ID, CCB_FLAG_OPEN_BY_FILE_ID, "OpenByFileId" },
  63. { CCB_FLAG_USER_SET_LAST_MOD_TIME, CCB_FLAG_USER_SET_LAST_MOD_TIME, "SetLastModTime" },
  64. { CCB_FLAG_USER_SET_LAST_CHANGE_TIME, CCB_FLAG_USER_SET_LAST_CHANGE_TIME, "SetLastChangeTime" },
  65. { CCB_FLAG_USER_SET_LAST_ACCESS_TIME, CCB_FLAG_USER_SET_LAST_ACCESS_TIME, "SetLastAccessTime" },
  66. { CCB_FLAG_TRAVERSE_CHECK, CCB_FLAG_TRAVERSE_CHECK, "TraverseCheck" },
  67. { CCB_FLAG_RETURN_DOT, CCB_FLAG_RETURN_DOT, "ReturnDot" },
  68. { CCB_FLAG_RETURN_DOTDOT, CCB_FLAG_RETURN_DOTDOT, "ReturnDotDot" },
  69. { CCB_FLAG_DOT_RETURNED, CCB_FLAG_DOT_RETURNED, "DotReturned" },
  70. { CCB_FLAG_DOTDOT_RETURNED, CCB_FLAG_DOTDOT_RETURNED, "DotDotReturned" },
  71. { CCB_FLAG_DELETE_FILE, CCB_FLAG_DELETE_FILE, "DeleteFile" },
  72. { CCB_FLAG_DENY_DELETE, CCB_FLAG_DENY_DELETE, "DenyDelete" },
  73. { CCB_FLAG_ALLOCATED_FILE_NAME, CCB_FLAG_ALLOCATED_FILE_NAME, "AllocatedFileName" },
  74. { CCB_FLAG_CLEANUP, CCB_FLAG_CLEANUP, "Cleanup" },
  75. { CCB_FLAG_SYSTEM_HIVE, CCB_FLAG_SYSTEM_HIVE, "SystemHive" },
  76. { CCB_FLAG_PARENT_HAS_DOS_COMPONENT, CCB_FLAG_PARENT_HAS_DOS_COMPONENT, "ParentHasDosComponent" },
  77. { CCB_FLAG_DELETE_ON_CLOSE, CCB_FLAG_DELETE_ON_CLOSE, "DeleteOnClose" },
  78. { CCB_FLAG_CLOSE, CCB_FLAG_CLOSE, "Close" },
  79. { CCB_FLAG_UPDATE_LAST_MODIFY, CCB_FLAG_UPDATE_LAST_MODIFY, "UpdateLastModify" },
  80. { CCB_FLAG_UPDATE_LAST_CHANGE, CCB_FLAG_UPDATE_LAST_CHANGE, "UpdateLastChange" },
  81. { CCB_FLAG_SET_ARCHIVE, CCB_FLAG_SET_ARCHIVE, "SetArchive" },
  82. { CCB_FLAG_DIR_NOTIFY, CCB_FLAG_DIR_NOTIFY, "DirNotify" },
  83. { CCB_FLAG_ALLOW_XTENDED_DASD_IO, CCB_FLAG_ALLOW_XTENDED_DASD_IO, "AllowExtendedDasdIo" },
  84. { 0 }
  85. };
  86. VOID
  87. PrintState(STATE *ps, ULONG state)
  88. {
  89. ULONG ul = 0;
  90. while (ps->mask != 0)
  91. {
  92. ul |= ps->mask;
  93. if ((state & ps->mask) == ps->value)
  94. {
  95. dprintf(" %s", ps->pszname);
  96. }
  97. ps++;
  98. }
  99. state &= ~ul;
  100. if (state != 0)
  101. {
  102. dprintf(" +%lx!!", state);
  103. }
  104. dprintf("\n");
  105. }
  106. typedef PVOID (*STRUCT_DUMP_ROUTINE)(
  107. IN ULONG Address,
  108. IN ULONG Options
  109. );
  110. VOID
  111. DumpVcb (
  112. IN ULONG Address,
  113. IN ULONG Options
  114. );
  115. VOID
  116. DumpLcb (
  117. IN ULONG Address,
  118. IN ULONG Options
  119. );
  120. VOID
  121. DumpFileObjectFromIrp (
  122. IN ULONG Address,
  123. IN ULONG Options
  124. );
  125. VOID
  126. DumpIrpContext (
  127. IN ULONG Address,
  128. IN ULONG Options
  129. );
  130. VOID
  131. DumpFcb (
  132. IN ULONG Address,
  133. IN ULONG Options
  134. );
  135. VOID
  136. DumpCcb (
  137. IN ULONG Address,
  138. IN ULONG Options
  139. );
  140. VOID
  141. DumpNtfsData (
  142. IN ULONG Address,
  143. IN ULONG Options
  144. )
  145. /*++
  146. Routine Description:
  147. Dump the list of Vcbs for the global NtfsData.
  148. Arguments:
  149. Address - Gives the address of the NtfsData to dump
  150. Options - If 1, we recurse into the Vcbs and dump them
  151. Return Value:
  152. None
  153. --*/
  154. {
  155. PLIST_ENTRY Head;
  156. ULONG Result;
  157. LIST_ENTRY ListEntry;
  158. PLIST_ENTRY Next;
  159. PNTFS_DATA pNtfsData;
  160. NTFS_DATA NtfsData;
  161. PVCB pVcb;
  162. dprintf( "\n NtfsData @ %08lx", Address );
  163. pNtfsData = (PNTFS_DATA) Address;
  164. if ( !ReadMemory( (DWORD) pNtfsData,
  165. &NtfsData,
  166. sizeof( NtfsData ),
  167. &Result) ) {
  168. dprintf( "%08lx: Unable to read pNtfsData\n", pNtfsData );
  169. return;
  170. }
  171. if (NtfsData.NodeTypeCode != NTFS_NTC_DATA_HEADER) {
  172. dprintf( "\nNtfsData signature does not match, probably not an NtfsData" );
  173. return;
  174. }
  175. if ( !ReadMemory( (DWORD) &(pNtfsData->VcbQueue),
  176. &ListEntry,
  177. sizeof( ListEntry ),
  178. &Result) ) {
  179. dprintf( "%08lx: Unable to read pNtfsData->VcbQueue\n", pNtfsData->VcbQueue );
  180. return;
  181. }
  182. dprintf( "\n Mounted volumes:" );
  183. Head = &(pNtfsData->VcbQueue);
  184. Next = ListEntry.Flink;
  185. while (Next != Head) {
  186. if ( !ReadMemory( (DWORD)Next,
  187. &ListEntry,
  188. sizeof( ListEntry ),
  189. &Result) ) {
  190. dprintf( "%08lx: Unable to read list\n", Next );
  191. return;
  192. }
  193. pVcb = CONTAINING_RECORD( Next, VCB, VcbLinks );
  194. if (Options >= 1) {
  195. DumpVcb( (ULONG) pVcb, Options - 1 );
  196. } else {
  197. dprintf( "\n Vcb: %08lx", (DWORD) pVcb );
  198. }
  199. if (CheckControlC()) {
  200. return;
  201. }
  202. Next = ListEntry.Flink;
  203. }
  204. dprintf( "\n" );
  205. return;
  206. }
  207. VOID
  208. DumpVcb (
  209. IN ULONG Address,
  210. IN ULONG Options
  211. )
  212. /*++
  213. Routine Description:
  214. Dump a Vcb.
  215. Arguments:
  216. Address - Gives the address of the Vcb to dump
  217. Options - If 1, we also dump the root Lcb and the Fcb table
  218. If 2, we dump everything for option 1, and also dump the Fcbs in the Fcb table
  219. Return Value:
  220. None
  221. --*/
  222. {
  223. ULONG Result;
  224. PVCB pVcb;
  225. VCB Vcb;
  226. PFCB pFcb;
  227. FCB_TABLE_ELEMENT FcbTableElement;
  228. PFCB_TABLE_ELEMENT pFcbTableElement;
  229. RTL_GENERIC_TABLE FcbTable;
  230. PRTL_GENERIC_TABLE pFcbTable;
  231. PVOID RestartKey;
  232. dprintf( "\n Vcb @ %08lx", Address );
  233. pVcb = (PVCB) Address;
  234. if ( !ReadMemory( (DWORD) pVcb,
  235. &Vcb,
  236. sizeof( Vcb ),
  237. &Result) ) {
  238. dprintf( "%08lx: Unable to read pVcb\n", pVcb );
  239. return;
  240. }
  241. if (Vcb.NodeTypeCode != NTFS_NTC_VCB) {
  242. dprintf( "\nVCB signature does not match, probably not a VCB" );
  243. return;
  244. }
  245. PrintState( VcbState, Vcb.VcbState );
  246. DUMP_WITH_OFFSET( VCB, Vcb, CleanupCount, "CleanupCount: " );
  247. DUMP_WITH_OFFSET( VCB, Vcb, CloseCount, "CloseCount: " );
  248. DUMP_WITH_OFFSET( VCB, Vcb, ReadOnlyCloseCount, "ReadOnlyCloseCount: " );
  249. DUMP_WITH_OFFSET( VCB, Vcb, SystemFileCloseCount, "SystemFileCloseCount:" );
  250. DUMP_WITH_OFFSET( VCB, Vcb, MftScb, "MftScb: " );
  251. DUMP_WITH_OFFSET( VCB, Vcb, Mft2Scb, "Mft2Scb: " );
  252. DUMP_WITH_OFFSET( VCB, Vcb, LogFileScb, "LogFileScb: " );
  253. DUMP_WITH_OFFSET( VCB, Vcb, VolumeDasdScb, "VolumeDasdScb: " );
  254. DUMP_WITH_OFFSET( VCB, Vcb, RootIndexScb, "RootIndexScb: " );
  255. DUMP_WITH_OFFSET( VCB, Vcb, BitmapScb, "BitmapScb: " );
  256. DUMP_WITH_OFFSET( VCB, Vcb, AttributeDefTableScb, "AttributeDefTableScb:" );
  257. DUMP_WITH_OFFSET( VCB, Vcb, UpcaseTableScb, "UpcaseTableScb: " );
  258. DUMP_WITH_OFFSET( VCB, Vcb, BadClusterFileScb, "BadClusterFileScb: " );
  259. DUMP_WITH_OFFSET( VCB, Vcb, QuotaTableScb, "QuotaTableScb: " );
  260. DUMP_WITH_OFFSET( VCB, Vcb, OwnerIdTableScb, "OwnerIdTableScb: " );
  261. DUMP_WITH_OFFSET( VCB, Vcb, MftBitmapScb, "MftBitmapScb: " );
  262. if (Options >= 1) {
  263. DumpLcb( (ULONG) Vcb.RootLcb, 0 );
  264. } else {
  265. DUMP_WITH_OFFSET( VCB, Vcb, RootLcb, "RootLcb: " );
  266. }
  267. //
  268. // Dump the FcbTable
  269. //
  270. if (Options >= 1) {
  271. pFcbTable = &(pVcb->FcbTable);
  272. if ( !ReadMemory( (DWORD) pFcbTable,
  273. &FcbTable,
  274. sizeof( FcbTable ),
  275. &Result) ) {
  276. dprintf( "%08lx: Unable to read pFcbTable\n", pFcbTable );
  277. return;
  278. }
  279. dprintf( "\n FcbTable @ %08lx", (DWORD) pFcbTable );
  280. dprintf( "\n FcbTable has %x elements", RtlNumberGenericTableElements( (PRTL_GENERIC_TABLE) &FcbTable ) );
  281. RestartKey = NULL;
  282. for (pFcbTableElement = (PFCB_TABLE_ELEMENT) KdEnumerateGenericTableWithoutSplaying(pFcbTable, &RestartKey);
  283. pFcbTableElement != NULL;
  284. pFcbTableElement = (PFCB_TABLE_ELEMENT) KdEnumerateGenericTableWithoutSplaying(pFcbTable, &RestartKey)) {
  285. if ( !ReadMemory( (DWORD) pFcbTableElement,
  286. &FcbTableElement,
  287. sizeof( FcbTableElement ),
  288. &Result) ) {
  289. dprintf( "%08lx: Unable to read pFcbTableElement\n", pFcbTableElement );
  290. return;
  291. }
  292. if (Options >= 2) {
  293. DumpFcb( (ULONG) FcbTableElement.Fcb, Options - 2 );
  294. } else {
  295. dprintf( "\n Fcb @ %08lx for FileReference(%x,%x) ",
  296. (DWORD) FcbTableElement.Fcb,
  297. FcbTableElement.FileReference.SegmentNumberHighPart,
  298. FcbTableElement.FileReference.SegmentNumberLowPart );
  299. }
  300. }
  301. }
  302. dprintf( "\n" );
  303. return;
  304. }
  305. VOID
  306. DumpScb (
  307. IN ULONG Address,
  308. IN ULONG Options
  309. )
  310. /*++
  311. Routine Description:
  312. Dump an Scb.
  313. Arguments:
  314. Address - Gives the address of the Scb to dump
  315. Options - If 1, we dump the Fcb & Vcb for this Scb
  316. Return Value:
  317. None
  318. --*/
  319. {
  320. ULONG Result;
  321. PSCB pScb;
  322. SCB Scb;
  323. PSCB_INDEX pScbIndex;
  324. dprintf( "\n Scb @ %08lx", Address );
  325. pScb = (PSCB) Address;
  326. if ( !ReadMemory( (DWORD) pScb,
  327. &Scb,
  328. sizeof( Scb ),
  329. &Result) ) {
  330. dprintf( "%08lx: Unable to read pScb\n", pScb );
  331. return;
  332. }
  333. dprintf( "\n ScbType: " );
  334. switch ( Scb.Header.NodeTypeCode ) {
  335. case NTFS_NTC_SCB_INDEX:
  336. dprintf( "Index" );
  337. break;
  338. case NTFS_NTC_SCB_ROOT_INDEX:
  339. dprintf( "RootIndex" );
  340. break;
  341. case NTFS_NTC_SCB_DATA:
  342. dprintf( "Data" );
  343. break;
  344. case NTFS_NTC_SCB_MFT:
  345. dprintf( "Mft" );
  346. break;
  347. case NTFS_NTC_SCB_NONPAGED:
  348. dprintf( "Nonpaged" );
  349. break;
  350. default:
  351. dprintf( "!!!UNKNOWN SCBTYPE!!!" );
  352. break;
  353. }
  354. if (Options >= 1) {
  355. DumpFcb( (ULONG) Scb.Fcb, Options - 1 );
  356. DumpVcb( (ULONG) Scb.Vcb, Options - 1 );
  357. } else {
  358. dprintf( "\n Fcb: %08lx", (DWORD) Scb.Fcb );
  359. dprintf( "\n Vcb: %08lx", (DWORD) Scb.Vcb );
  360. }
  361. dprintf( "\n" );
  362. return;
  363. }
  364. VOID
  365. DumpLcb (
  366. IN ULONG Address,
  367. IN ULONG Options
  368. )
  369. /*++
  370. Routine Description:
  371. Dump an Lcb.
  372. Arguments:
  373. Address - Gives the address of the Lcb to dump
  374. Return Value:
  375. None
  376. --*/
  377. {
  378. ULONG Result;
  379. PLCB pLcb;
  380. LCB Lcb;
  381. OVERLAY_LCB OverlayLcb;
  382. WCHAR FileName[32];
  383. dprintf( "\n Lcb @ %08lx", Address );
  384. pLcb = (PLCB) Address;
  385. if ( !ReadMemory( (DWORD) pLcb,
  386. &Lcb,
  387. sizeof( Lcb ),
  388. &Result) ) {
  389. dprintf( "%08lx: Unable to read pLcb\n", pLcb );
  390. return;
  391. }
  392. if (Lcb.NodeTypeCode != NTFS_NTC_LCB) {
  393. dprintf( "\nLCB signature does not match, probably not an LCB" );
  394. return;
  395. }
  396. dprintf( "\n Case preserved file name @ %08lx", (DWORD) pLcb->FileName );
  397. if ( !ReadMemory( (DWORD) pLcb->FileName,
  398. &FileName,
  399. sizeof( FileName ),
  400. &Result) ) {
  401. dprintf( "%08lx: Unable to read pLcb->FileName\n", (DWORD) pLcb->FileName );
  402. return;
  403. }
  404. dprintf( " is:%S", FileName );
  405. dprintf( "\n" );
  406. return;
  407. }
  408. VOID
  409. DumpIrpContext (
  410. IN ULONG Address,
  411. IN ULONG Options
  412. )
  413. /*++
  414. Routine Description:
  415. Dump an IrpContext.
  416. Arguments:
  417. Address - Gives the address of the IrpContext to dump
  418. Return Value:
  419. None
  420. --*/
  421. {
  422. ULONG Result;
  423. PIRP_CONTEXT pIrpContext;
  424. IRP_CONTEXT IrpContext;
  425. dprintf( "\n IrpContext @ %08lx", Address );
  426. pIrpContext = (PIRP_CONTEXT) Address;
  427. if ( !ReadMemory( (DWORD) pIrpContext,
  428. &IrpContext,
  429. sizeof( IrpContext ),
  430. &Result) ) {
  431. dprintf( "%08lx: Unable to read pIrpContext\n", pIrpContext );
  432. return;
  433. }
  434. if (IrpContext.NodeTypeCode != NTFS_NTC_IRP_CONTEXT) {
  435. dprintf( "\nIRP_CONTEXT signature does not match, probably not an IRP_CONTEXT" );
  436. return;
  437. }
  438. if (Options >= 1) {
  439. DumpFileObjectFromIrp( (ULONG) IrpContext.OriginatingIrp, Options - 1 );
  440. }
  441. dprintf( "\n" );
  442. return;
  443. }
  444. VOID
  445. DumpFcb (
  446. IN ULONG Address,
  447. IN ULONG Options
  448. )
  449. /*++
  450. Routine Description:
  451. Dump a specific fcb.
  452. Arguments:
  453. Address - Gives the address of the fcb to dump
  454. Return Value:
  455. None
  456. --*/
  457. {
  458. PLIST_ENTRY Head;
  459. LIST_ENTRY ListEntry;
  460. PLIST_ENTRY Next;
  461. ULONG Result;
  462. PFCB pFcb;
  463. FCB Fcb;
  464. PFCB_DATA pFcbData;
  465. FCB_DATA FcbData;
  466. PSCB pScb;
  467. PLCB pLcb;
  468. dprintf( "\n Fcb @ %08lx", Address );
  469. pFcb = (PFCB) Address;
  470. if ( !ReadMemory( (DWORD) pFcb,
  471. &Fcb,
  472. sizeof( Fcb ),
  473. &Result) ) {
  474. dprintf( "%08lx: Unable to read pFcb\n", pFcb );
  475. return;
  476. }
  477. //
  478. // Before we get into too much trouble, make sure this looks like an fcb.
  479. //
  480. //
  481. // Type of an fcb record must be NTFS_NTC_FCB
  482. //
  483. if (Fcb.NodeTypeCode != NTFS_NTC_FCB) {
  484. dprintf( "\nFCB signature does not match, probably not an FCB" );
  485. return;
  486. }
  487. //
  488. // Having established that this looks like an fcb, let's dump the
  489. // interesting parts.
  490. //
  491. PrintState( FcbState, Fcb.FcbState );
  492. DUMP_WITH_OFFSET( FCB, Fcb, CleanupCount, "CleanupCount: " );
  493. DUMP_WITH_OFFSET( FCB, Fcb, CloseCount, "CloseCount: " );
  494. DUMP_WITH_OFFSET( FCB, Fcb, ReferenceCount, "ReferenceCount: " );
  495. DUMP_WITH_OFFSET( FCB, Fcb, FcbState, "FcbState: " );
  496. DUMP_WITH_OFFSET( FCB, Fcb, FcbDenyDelete, "FcbDenyDelete: " );
  497. DUMP_WITH_OFFSET( FCB, Fcb, FcbDeleteFile, "FcbDeleteFile: " );
  498. DUMP_WITH_OFFSET( FCB, Fcb, BaseExclusiveCount, "BaseExclusiveCount: " );
  499. DUMP_WITH_OFFSET( FCB, Fcb, EaModificationCount, "EaModificationCount:" );
  500. DUMP_WITH_OFFSET( FCB, Fcb, InfoFlags, "InfoFlags: " );
  501. DUMP_WITH_OFFSET( FCB, Fcb, LinkCount, "LinkCount: " );
  502. DUMP_WITH_OFFSET( FCB, Fcb, TotalLinks, "TotalLinks: " );
  503. DUMP_WITH_OFFSET( FCB, Fcb, CurrentLastAccess, "CurrentLastAccess: " );
  504. DUMP_WITH_OFFSET( FCB, Fcb, CreateSecurityCount, "CreateSecurityCount:" );
  505. DUMP_WITH_OFFSET( FCB, Fcb, DelayedCloseCount, "DelayedCloseCount: " );
  506. //
  507. // walk the queue of links for this file
  508. //
  509. if ( !ReadMemory( (DWORD) &(pFcb->LcbQueue),
  510. &ListEntry,
  511. sizeof( ListEntry ),
  512. &Result) ) {
  513. dprintf( "%08lx: Unable to read pFcb->LcbQueue\n", pFcb->LcbQueue );
  514. return;
  515. }
  516. dprintf( "\n Links:" );
  517. Head = &(pFcb->LcbQueue);
  518. Next = ListEntry.Flink;
  519. while (Next != Head) {
  520. if ( !ReadMemory( (DWORD)Next,
  521. &ListEntry,
  522. sizeof( ListEntry ),
  523. &Result) ) {
  524. dprintf( "%08lx: Unable to read list\n", Next );
  525. return;
  526. }
  527. pLcb = CONTAINING_RECORD( Next, LCB, FcbLinks );
  528. if (Options >= 1) {
  529. DumpLcb( (ULONG) pLcb, Options - 1 );
  530. }
  531. else {
  532. dprintf( "\n Lcb: %08lx", (DWORD) pLcb );
  533. }
  534. if (CheckControlC()) {
  535. return;
  536. }
  537. Next = ListEntry.Flink;
  538. }
  539. dprintf( "\n" );
  540. //
  541. // Walk the queue of streams for this file.
  542. //
  543. if ( !ReadMemory( (DWORD) &(pFcb->ScbQueue),
  544. &ListEntry,
  545. sizeof( ListEntry ),
  546. &Result) ) {
  547. dprintf( "%08lx: Unable to read pFcb->ScbQueue\n", pFcb->ScbQueue );
  548. return;
  549. }
  550. dprintf( "\n Streams:" );
  551. Head = &(pFcb->ScbQueue);
  552. Next = ListEntry.Flink;
  553. while (Next != Head) {
  554. if ( !ReadMemory( (DWORD)Next,
  555. &ListEntry,
  556. sizeof( ListEntry ),
  557. &Result) ) {
  558. dprintf( "%08lx: Unable to read list\n", Next );
  559. return;
  560. }
  561. pScb = CONTAINING_RECORD( Next, SCB, FcbLinks );
  562. if (Options >= 1) {
  563. DumpScb( (ULONG) pScb, Options - 1 );
  564. } else {
  565. dprintf( "\n Scb: %08lx", (DWORD) pScb );
  566. }
  567. if (CheckControlC()) {
  568. return;
  569. }
  570. Next = ListEntry.Flink;
  571. }
  572. dprintf( "\n" );
  573. return;
  574. }
  575. VOID
  576. DumpCcb (
  577. IN ULONG Address,
  578. IN ULONG Options
  579. )
  580. /*++
  581. Routine Description:
  582. Dump a specific ccb.
  583. Arguments:
  584. Address - Gives the address of the fcb to dump
  585. Return Value:
  586. None
  587. --*/
  588. {
  589. ULONG Result;
  590. PCCB pCcb;
  591. CCB Ccb;
  592. WCHAR FullFileName[32];
  593. dprintf( "\n Ccb @ %08lx", Address );
  594. pCcb = (PCCB) Address;
  595. if ( !ReadMemory( (DWORD) pCcb,
  596. &Ccb,
  597. sizeof( Ccb ),
  598. &Result) ) {
  599. dprintf( "%08lx: Unable to read pCcb\n", pCcb );
  600. return;
  601. }
  602. //
  603. // Before we get into too much trouble, make sure this looks like a ccb.
  604. //
  605. //
  606. // Type of an fcb record must be NTFS_NTC_CCB_DATA or NTFS_NTC_CCB_INDEX
  607. //
  608. if (Ccb.NodeTypeCode != NTFS_NTC_CCB_DATA &&
  609. Ccb.NodeTypeCode != NTFS_NTC_CCB_INDEX) {
  610. dprintf( "\nCCB signature does not match, probably not a CCB" );
  611. return;
  612. }
  613. //
  614. // Having established that this looks like a ccb, let's dump the
  615. // interesting parts.
  616. //
  617. PrintState( CcbState, Ccb.Flags );
  618. DUMP_WITH_OFFSET( CCB, Ccb, Flags, "Flags: " );
  619. if ( !ReadMemory( (DWORD) Ccb.FullFileName.Buffer,
  620. &FullFileName,
  621. sizeof( FullFileName ),
  622. &Result) ) {
  623. dprintf( "%08lx: Unable to read Ccb.FullFileName.Buffer\n", (DWORD) Ccb.FullFileName.Buffer );
  624. return;
  625. }
  626. dprintf( "\n FullFileName: %S length %x offset %3x",
  627. FullFileName,
  628. Ccb.FullFileName.Length,
  629. FIELD_OFFSET(CCB, FullFileName) );
  630. DUMP_WITH_OFFSET( CCB, Ccb, LastFileNameOffset, "LastFileNameOffset: " );
  631. DUMP_WITH_OFFSET( CCB, Ccb, EaModificationCount, "EaModificationCount:" );
  632. DUMP_WITH_OFFSET( CCB, Ccb, NextEaOffset, "NextEaOffset: " );
  633. DUMP_WITH_OFFSET( CCB, Ccb, Lcb, "Lcb: " );
  634. DUMP_WITH_OFFSET( CCB, Ccb, TypeOfOpen, "TypeOfOpen: " );
  635. DUMP_WITH_OFFSET( CCB, Ccb, IndexContext, "IndexContext: " );
  636. DUMP_WITH_OFFSET( CCB, Ccb, QueryLength, "QueryLength: " );
  637. DUMP_WITH_OFFSET( CCB, Ccb, QueryBuffer, "QueryBuffer: " );
  638. DUMP_WITH_OFFSET( CCB, Ccb, IndexEntryLength, "IndexEntryLength: " );
  639. DUMP_WITH_OFFSET( CCB, Ccb, IndexEntry, "IndexEntry: " );
  640. dprintf( "\n LongValue: %I64x", Ccb.FcbToAcquire.LongValue );
  641. dprintf( "\n" );
  642. return;
  643. }
  644. VOID
  645. DumpFileObject (
  646. IN ULONG Address,
  647. IN ULONG Options
  648. )
  649. /*++
  650. Routine Description:
  651. Dump a File_Object.
  652. Arguments:
  653. Address - Gives the address of the File_Object to dump
  654. Return Value:
  655. None
  656. --*/
  657. {
  658. ULONG Result;
  659. FILE_OBJECT File_Object;
  660. PFILE_OBJECT pFile_Object;
  661. DWORD FsContextLowBits;
  662. dprintf( "\n File_Object @ %08lx", Address );
  663. pFile_Object = (PFILE_OBJECT) Address;
  664. if ( !ReadMemory( (DWORD) pFile_Object,
  665. &File_Object,
  666. sizeof( File_Object ),
  667. &Result) ) {
  668. dprintf( "%08lx: Unable to read pFile_Object\n", pFile_Object );
  669. return;
  670. }
  671. if (File_Object.FsContext) {
  672. dprintf( "\n OpenType: " );
  673. FsContextLowBits = ( ((DWORD) File_Object.FsContext) & 0x3);
  674. switch (FsContextLowBits) {
  675. case 0:
  676. if (File_Object.FsContext2) {
  677. dprintf( "UserFileOpen" );
  678. } else {
  679. dprintf( "StreamFileOpen" );
  680. }
  681. break;
  682. case 1:
  683. dprintf( "UserDirectoryOpen" );
  684. break;
  685. case 2:
  686. dprintf( "UserVolumeOpen" );
  687. break;
  688. }
  689. DumpScb( (ULONG) File_Object.FsContext, 1 );
  690. DumpCcb( (ULONG) File_Object.FsContext2, 1 );
  691. }
  692. dprintf( "\n" );
  693. return;
  694. }
  695. VOID
  696. DumpIrpContextFromThread (
  697. IN ULONG Thread,
  698. IN ULONG Options
  699. )
  700. /*++
  701. Routine Description:
  702. Dump an IrpContext given a Thread.
  703. Arguments:
  704. Address - Gives the address of the Thread where the IrpContext can be found
  705. Return Value:
  706. None
  707. --*/
  708. {
  709. ULONG Result;
  710. ULONG OurStackAddress;
  711. PIRP_CONTEXT pIrpContext;
  712. dprintf( "\n Thread @ %08lx", Thread );
  713. if (!ReadMemory( (DWORD) (Thread + 0x214),
  714. &OurStackAddress,
  715. sizeof(OurStackAddress),
  716. &Result)) {
  717. dprintf( "%08lx: Could not read Thread + 0x214\n", Thread + 0x214 );
  718. return;
  719. }
  720. dprintf( "\n Our stack @ %08lx", OurStackAddress );
  721. if (!ReadMemory( (DWORD) (OurStackAddress + 0x18),
  722. &pIrpContext,
  723. sizeof(pIrpContext),
  724. &Result)) {
  725. dprintf( "%08lx: Could not read OurStackAddress + 0x18\n", OurStackAddress + 0x18 );
  726. return;
  727. }
  728. DumpIrpContext( (ULONG) pIrpContext, Options );
  729. dprintf( "\n" );
  730. return;
  731. }
  732. VOID
  733. DumpFileObjectFromIrp (
  734. IN ULONG Address,
  735. IN ULONG Options
  736. )
  737. /*++
  738. Routine Description:
  739. Dump a File_Object given an Irp.
  740. Arguments:
  741. Address - Gives the address of the Irp where the File_Object can be found
  742. Return Value:
  743. None
  744. --*/
  745. {
  746. ULONG Result;
  747. ULONG IrpStackAddress;
  748. IO_STACK_LOCATION IrpStack;
  749. IRP Irp;
  750. PIRP pIrp;
  751. CCHAR IrpStackIndex;
  752. dprintf( "\n Irp @ %08lx", Address );
  753. pIrp = (PIRP) Address;
  754. if (!ReadMemory( (DWORD) pIrp,
  755. &Irp,
  756. sizeof(Irp),
  757. &Result)) {
  758. dprintf( "%08lx: Could not read Irp\n", pIrp );
  759. return;
  760. }
  761. if (Irp.Type != IO_TYPE_IRP) {
  762. dprintf( "IRP signature does not match, probably not an IRP\n" );
  763. return;
  764. }
  765. //
  766. // only the current irp stack is worth dumping
  767. // the - 1 is there because irp.CurrentLocation is 1 based
  768. //
  769. IrpStackAddress = (ULONG) pIrp + sizeof(Irp) + (sizeof(IrpStack) * (Irp.CurrentLocation - 1));
  770. if ( !ReadMemory( (DWORD) IrpStackAddress,
  771. &IrpStack,
  772. sizeof(IrpStack),
  773. &Result) ) {
  774. dprintf("%08lx: Could not read IrpStack\n", IrpStackAddress);
  775. return;
  776. }
  777. DumpFileObject( (ULONG) (IrpStack.FileObject), Options );
  778. dprintf( "\n" );
  779. return;
  780. }
  781. //
  782. // Entry points, parameter parsers, etc. below
  783. //
  784. VOID
  785. ParseAndDump (
  786. IN PCHAR args,
  787. IN STRUCT_DUMP_ROUTINE DumpFunction
  788. )
  789. /*++
  790. Routine Description:
  791. Dump an ntfs structure.
  792. Arguments:
  793. Address - Gives the address of the File_Object to dump
  794. Return Value:
  795. None
  796. --*/
  797. {
  798. ULONG StructToDump;
  799. ULONG Options;
  800. //
  801. // If the caller specified an address then that's the item we dump
  802. //
  803. StructToDump = 0;
  804. Options = 0;
  805. sscanf(args,"%lx %lx", &StructToDump, &Options );
  806. if (StructToDump != 0) {
  807. (*DumpFunction) ( StructToDump, Options );
  808. }
  809. dprintf( "\n" );
  810. return;
  811. }
  812. DECLARE_API( ntfsdata )
  813. /*++
  814. Routine Description:
  815. Dump NtfsData struct
  816. Arguments:
  817. arg - [Address] [options]
  818. Return Value:
  819. None
  820. --*/
  821. {
  822. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpNtfsData );
  823. return;
  824. }
  825. DECLARE_API( vcb )
  826. /*++
  827. Routine Description:
  828. Dump Vcb struct
  829. Arguments:
  830. arg - [Address] [options]
  831. Return Value:
  832. None
  833. --*/
  834. {
  835. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpVcb );
  836. return;
  837. }
  838. DECLARE_API( scb )
  839. /*++
  840. Routine Description:
  841. Dump Scb struct
  842. Arguments:
  843. arg - [Address] [options]
  844. Return Value:
  845. None
  846. --*/
  847. {
  848. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpScb );
  849. return;
  850. }
  851. DECLARE_API( fcb )
  852. /*++
  853. Routine Description:
  854. Dump fcb struct
  855. Arguments:
  856. arg - [Address] [options]
  857. Return Value:
  858. None
  859. --*/
  860. {
  861. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpFcb );
  862. return;
  863. }
  864. DECLARE_API( ccb )
  865. /*++
  866. Routine Description:
  867. Dump ccb struct
  868. Arguments:
  869. arg - [Address] [options]
  870. Return Value:
  871. None
  872. --*/
  873. {
  874. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpCcb );
  875. return;
  876. }
  877. DECLARE_API( lcb )
  878. /*++
  879. Routine Description:
  880. Dump lcb struct
  881. Arguments:
  882. arg - [Address] [options]
  883. Return Value:
  884. None
  885. --*/
  886. {
  887. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpLcb );
  888. return;
  889. }
  890. DECLARE_API( irpcontext )
  891. /*++
  892. Routine Description:
  893. Dump IrpContext
  894. Arguments:
  895. arg - [Address] [options]
  896. Return Value:
  897. None
  898. --*/
  899. {
  900. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpIrpContext );
  901. return;
  902. }
  903. DECLARE_API( icthread )
  904. /*++
  905. Routine Description:
  906. Dump IrpContext struct, given a Thread
  907. Arguments:
  908. arg - [Address] [options]
  909. Return Value:
  910. None
  911. --*/
  912. {
  913. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpIrpContextFromThread );
  914. return;
  915. }
  916. DECLARE_API( foirp )
  917. /*++
  918. Routine Description:
  919. Dump File_Object struct, given an irp
  920. Arguments:
  921. arg - [Address] [options]
  922. Return Value:
  923. None
  924. --*/
  925. {
  926. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpFileObjectFromIrp );
  927. return;
  928. }
  929. DECLARE_API( file )
  930. /*++
  931. Routine Description:
  932. Dump File_Object struct
  933. Arguments:
  934. arg - [Address] [options]
  935. Return Value:
  936. None
  937. --*/
  938. {
  939. ParseAndDump( (PCHAR) args, (STRUCT_DUMP_ROUTINE) DumpFileObject );
  940. return;
  941. }