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.

693 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. fsinfo.c
  5. Abstract:
  6. This file contains code for commands that affect
  7. information specific to the file system.
  8. Author:
  9. Wesley Witt [wesw] 1-March-2000
  10. Revision History:
  11. --*/
  12. #include <precomp.h>
  13. INT
  14. FsInfoHelp(
  15. IN INT argc,
  16. IN PWSTR argv[]
  17. )
  18. {
  19. DisplayMsg( MSG_USAGE_FSINFO );
  20. return EXIT_CODE_SUCCESS;
  21. }
  22. typedef struct _NTFS_FILE_SYSTEM_STATISTICS {
  23. FILESYSTEM_STATISTICS Common;
  24. NTFS_STATISTICS Ntfs;
  25. UCHAR Pad[64-(sizeof(FILESYSTEM_STATISTICS)+sizeof(NTFS_STATISTICS))%64];
  26. } NTFS_FILE_SYSTEM_STATISTICS, *PNTFS_FILE_SYSTEM_STATISTICS;
  27. typedef struct _FAT_FILE_SYSTEM_STATISTICS {
  28. FILESYSTEM_STATISTICS Common;
  29. FAT_STATISTICS Fat;
  30. UCHAR Pad[64-(sizeof(FILESYSTEM_STATISTICS)+sizeof(NTFS_STATISTICS))%64];
  31. } FAT_FILE_SYSTEM_STATISTICS, *PFAT_FILE_SYSTEM_STATISTICS;
  32. ULONGLONG
  33. FsStat(
  34. IN PVOID FsStats,
  35. IN ULONG FsSize,
  36. IN ULONG Offset,
  37. IN ULONG NumProcs
  38. )
  39. /*++
  40. Routine Description:
  41. This routine iterates through the file system statistics structure
  42. and accumulates a total amount for a given statistic field.
  43. Note: This function assumes that the width of the field being accumulated
  44. is a ULONG. If this assumption is invalidated then a width argument
  45. should be added to this function.
  46. Arguments:
  47. FsStats - Pointer to an array of file system statistics structures
  48. FsSize - Size of the individual file system statistics structures in the array
  49. Offset - Offset of the desired field from the beginning of the file system statistics structure
  50. NumProcs - Number of processors on the machine where the stats were gathered
  51. Return Value:
  52. Accumulated total.
  53. --*/
  54. {
  55. ULONG i;
  56. ULONGLONG Total = 0;
  57. for (i=0; i<NumProcs; i++) {
  58. Total += *(PULONG)((PUCHAR)FsStats + Offset);
  59. FsStats = (PVOID)((PUCHAR)FsStats + FsSize);
  60. }
  61. return Total;
  62. }
  63. INT
  64. ListDrives(
  65. IN INT argc,
  66. IN PWSTR argv[]
  67. )
  68. /*++
  69. Routine Description:
  70. This routine lists all the drive names in the system.
  71. Arguments:
  72. argc - The argument count
  73. argv - Array of Strings of the form : 'fscutl lsdrv'.
  74. Return Value:
  75. None
  76. --*/
  77. {
  78. DWORD nBufferLen = MAX_PATH;
  79. DWORD Length;
  80. LPWSTR lpBuffer = NULL;
  81. WORD Index;
  82. INT ExitCode = EXIT_CODE_SUCCESS;
  83. try {
  84. if (argc != 0) {
  85. DisplayMsg( MSG_LISTDRIVES_USAGE );
  86. ExitCode = EXIT_CODE_FAILURE;
  87. leave;
  88. }
  89. lpBuffer = (LPWSTR) malloc( nBufferLen * sizeof(WCHAR) );
  90. if (!lpBuffer) {
  91. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  92. ExitCode = EXIT_CODE_FAILURE;
  93. leave;
  94. }
  95. Length = GetLogicalDriveStrings( nBufferLen, lpBuffer );
  96. if (!Length) {
  97. DisplayError();
  98. ExitCode = EXIT_CODE_FAILURE;
  99. leave;
  100. }
  101. wprintf( L"\n" );
  102. DisplayMsg( MSG_DRIVES );
  103. for ( Index = 0 ; Index < Length; Index ++ ) {
  104. wprintf( L"%c", lpBuffer[Index] );
  105. }
  106. wprintf( L"\n" );
  107. } finally {
  108. if (lpBuffer) {
  109. free( lpBuffer );
  110. }
  111. }
  112. return ExitCode;
  113. }
  114. INT
  115. DriveType(
  116. IN INT argc,
  117. IN PWSTR argv[]
  118. )
  119. /*++
  120. Routine Description:
  121. This routine describes the drive type of the drive passed in.
  122. Arguments:
  123. argc - The argument count
  124. argv - Array of Strings of the form :
  125. 'fscutl dt <drive name>' or
  126. 'fscutl drivetype <drive name>'
  127. Return Value:
  128. None
  129. --*/
  130. {
  131. if (argc != 1) {
  132. DisplayMsg( MSG_USAGE_DRIVETYPE );
  133. if (argc != 0) {
  134. return EXIT_CODE_FAILURE;
  135. } else {
  136. return EXIT_CODE_SUCCESS;
  137. }
  138. }
  139. DisplayMsg( GetDriveType( argv[0] ) + MSG_DRIVE_UNKNOWN, argv[0] );
  140. return EXIT_CODE_SUCCESS;
  141. }
  142. INT
  143. VolumeInfo(
  144. IN INT argc,
  145. IN PWSTR argv[]
  146. )
  147. /*++
  148. Routine Description:
  149. This routine provides the information about the Volume.
  150. Arguments:
  151. argc - The argument count
  152. argv - Array of Strings of the form :
  153. 'fscutl infov <root pathname>'.
  154. Return Value:
  155. None
  156. --*/
  157. {
  158. LPWSTR lpVolumeNameBuffer = NULL; // address of name of the volume
  159. DWORD nVolumeNameSize; // length of lpVolumeNameBuffer
  160. LPDWORD lpVolumeSerialNumber = NULL; // address of volume serial number
  161. LPDWORD lpMaximumComponentLength = NULL; // address of system's maximum
  162. // filename length
  163. LPDWORD lpFileSystemFlags = NULL; // address of file system flags
  164. LPWSTR lpFileSystemNameBuffer = NULL; // address of name of file system
  165. DWORD nFileSystemNameSize; // length of lpFileSystemNameBuffer
  166. BOOL Status; // return status
  167. DWORD dwMask; // FileSystem Flag Mask
  168. DWORD Index;
  169. DWORD FsFlag;
  170. INT ExitCode = EXIT_CODE_SUCCESS;
  171. try {
  172. if (argc != 1) {
  173. DisplayMsg( MSG_USAGE_INFOV );
  174. if (argc != 0) {
  175. ExitCode = EXIT_CODE_FAILURE;
  176. }
  177. leave ;
  178. }
  179. nVolumeNameSize = MAX_PATH;
  180. lpVolumeNameBuffer = (LPWSTR) malloc ( MAX_PATH * sizeof(WCHAR) );
  181. if (lpVolumeNameBuffer == NULL) {
  182. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  183. ExitCode = EXIT_CODE_FAILURE;
  184. leave;
  185. }
  186. lpVolumeSerialNumber = (LPDWORD) malloc( sizeof(DWORD) );
  187. if (lpVolumeSerialNumber == NULL) {
  188. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  189. ExitCode = EXIT_CODE_FAILURE;
  190. leave;
  191. }
  192. lpFileSystemFlags = (LPDWORD) malloc ( sizeof(DWORD) );
  193. if (lpFileSystemFlags == NULL) {
  194. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  195. ExitCode = EXIT_CODE_FAILURE;
  196. leave;
  197. }
  198. lpMaximumComponentLength = (LPDWORD) malloc ( sizeof(DWORD) );
  199. if (lpMaximumComponentLength == NULL) {
  200. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  201. ExitCode = EXIT_CODE_FAILURE;
  202. leave;
  203. }
  204. nFileSystemNameSize = MAX_PATH;
  205. lpFileSystemNameBuffer = (LPWSTR) malloc ( MAX_PATH * sizeof(WCHAR) );
  206. if (lpFileSystemNameBuffer == NULL) {
  207. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  208. ExitCode = EXIT_CODE_FAILURE;
  209. leave;
  210. }
  211. Status = GetVolumeInformation (
  212. argv[0],
  213. lpVolumeNameBuffer,
  214. nVolumeNameSize,
  215. lpVolumeSerialNumber,
  216. lpMaximumComponentLength,
  217. lpFileSystemFlags,
  218. lpFileSystemNameBuffer,
  219. nFileSystemNameSize
  220. );
  221. if (!Status) {
  222. DisplayError();
  223. ExitCode = EXIT_CODE_FAILURE;
  224. leave;
  225. }
  226. DisplayMsg( MSG_VOLNAME, lpVolumeNameBuffer );
  227. DisplayMsg( MSG_SERIALNO, *lpVolumeSerialNumber );
  228. DisplayMsg( MSG_MAX_COMP_LEN, *lpMaximumComponentLength );
  229. DisplayMsg( MSG_FS_NAME, lpFileSystemNameBuffer );
  230. dwMask = 1 ;
  231. FsFlag = *lpFileSystemFlags;
  232. for ( Index=0 ; Index<32 ; Index++ ) {
  233. switch (FsFlag & dwMask) {
  234. case FILE_CASE_SENSITIVE_SEARCH:
  235. DisplayMsg( MSG_FILE_CASE_SENSITIVE_SEARCH );
  236. break;
  237. case FILE_CASE_PRESERVED_NAMES:
  238. DisplayMsg( MSG_FILE_CASE_PRESERVED_NAMES );
  239. break;
  240. case FILE_UNICODE_ON_DISK:
  241. DisplayMsg( MSG_FILE_UNICODE_ON_DISK );
  242. break;
  243. case FILE_PERSISTENT_ACLS:
  244. DisplayMsg( MSG_FILE_PERSISTENT_ACLS );
  245. break;
  246. case FILE_FILE_COMPRESSION:
  247. DisplayMsg( MSG_FILE_FILE_COMPRESSION );
  248. break;
  249. case FILE_VOLUME_QUOTAS:
  250. DisplayMsg( MSG_FILE_VOLUME_QUOTAS );
  251. break;
  252. case FILE_SUPPORTS_SPARSE_FILES:
  253. DisplayMsg( MSG_FILE_SUPPORTS_SPARSE_FILES );
  254. break;
  255. case FILE_SUPPORTS_REPARSE_POINTS:
  256. DisplayMsg( MSG_FILE_SUPPORTS_REPARSE_POINTS );
  257. break;
  258. case FILE_SUPPORTS_REMOTE_STORAGE:
  259. DisplayMsg( MSG_FILE_SUPPORTS_REMOTE_STORAGE );
  260. break;
  261. case FILE_VOLUME_IS_COMPRESSED:
  262. DisplayMsg( MSG_FILE_VOLUME_IS_COMPRESSED );
  263. break;
  264. case FILE_SUPPORTS_OBJECT_IDS:
  265. DisplayMsg( MSG_FILE_SUPPORTS_OBJECT_IDS );
  266. break;
  267. case FILE_SUPPORTS_ENCRYPTION:
  268. DisplayMsg( MSG_FILE_SUPPORTS_ENCRYPTION );
  269. break;
  270. case FILE_NAMED_STREAMS:
  271. DisplayMsg( MSG_FILE_NAMED_STREAMS );
  272. break;
  273. }
  274. dwMask <<= 1;
  275. }
  276. } finally {
  277. free( lpVolumeNameBuffer );
  278. free( lpVolumeSerialNumber );
  279. free( lpFileSystemFlags );
  280. free( lpMaximumComponentLength );
  281. free( lpFileSystemNameBuffer );
  282. }
  283. return ExitCode;
  284. }
  285. INT
  286. GetNtfsVolumeData(
  287. IN INT argc,
  288. IN PWSTR argv[]
  289. )
  290. /*++
  291. Routine Description:
  292. This routine gets the NTFS volume data for the volume
  293. specified.
  294. Arguments:
  295. argc - The argument count.
  296. argv - Array of Strings of the form :
  297. ' fscutl getntfsdv <volume pathname>'.
  298. Return Value:
  299. None
  300. --*/
  301. {
  302. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  303. WCHAR FileName[MAX_PATH];
  304. BOOL Status;
  305. BYTE Buffer[sizeof( NTFS_VOLUME_DATA_BUFFER ) + sizeof( NTFS_EXTENDED_VOLUME_DATA )];
  306. PNTFS_VOLUME_DATA_BUFFER pvdb = (PNTFS_VOLUME_DATA_BUFFER)Buffer;
  307. PNTFS_EXTENDED_VOLUME_DATA pevd = (PNTFS_EXTENDED_VOLUME_DATA)(pvdb + 1);
  308. DWORD BytesReturned;
  309. INT ExitCode = EXIT_CODE_SUCCESS;
  310. try {
  311. if (argc != 1) {
  312. DisplayMsg( MSG_USAGE_NTFSINFO );
  313. if (argc != 0) {
  314. ExitCode = EXIT_CODE_FAILURE;
  315. }
  316. leave;
  317. }
  318. if (!IsVolumeLocalNTFS( argv[0][0] )) {
  319. DisplayMsg( MSG_NTFS_REQUIRED );
  320. ExitCode = EXIT_CODE_FAILURE;
  321. leave;
  322. }
  323. wcscpy( FileName, L"\\\\.\\" );
  324. wcscat( FileName, argv[0] );
  325. FileHandle = CreateFile(
  326. FileName,
  327. GENERIC_READ,
  328. FILE_SHARE_READ | FILE_SHARE_WRITE,
  329. NULL,
  330. OPEN_EXISTING,
  331. FILE_ATTRIBUTE_NORMAL,
  332. NULL
  333. );
  334. if (FileHandle == INVALID_HANDLE_VALUE) {
  335. DisplayError();
  336. ExitCode = EXIT_CODE_FAILURE;
  337. leave;
  338. }
  339. Status = DeviceIoControl(
  340. FileHandle,
  341. FSCTL_GET_NTFS_VOLUME_DATA,
  342. NULL,
  343. 0,
  344. pvdb,
  345. sizeof( Buffer ),
  346. &BytesReturned,
  347. (LPOVERLAPPED)NULL
  348. );
  349. if (!Status) {
  350. DisplayError();
  351. ExitCode = EXIT_CODE_FAILURE;
  352. leave;
  353. }
  354. DisplayMsg(
  355. MSG_NTFSINFO_STATS,
  356. QuadToPaddedHexText( pvdb->VolumeSerialNumber.QuadPart ), // Serial number in hex
  357. pevd->MajorVersion,
  358. pevd->MinorVersion,
  359. QuadToPaddedHexText( pvdb->NumberSectors.QuadPart ),
  360. QuadToPaddedHexText( pvdb->TotalClusters.QuadPart ),
  361. QuadToPaddedHexText( pvdb->FreeClusters.QuadPart ),
  362. QuadToPaddedHexText( pvdb->TotalReserved.QuadPart ),
  363. pvdb->BytesPerSector,
  364. pvdb->BytesPerCluster,
  365. pvdb->BytesPerFileRecordSegment,
  366. pvdb->ClustersPerFileRecordSegment,
  367. QuadToPaddedHexText( pvdb->MftValidDataLength.QuadPart ),
  368. QuadToPaddedHexText( pvdb->MftStartLcn.QuadPart ),
  369. QuadToPaddedHexText( pvdb->Mft2StartLcn.QuadPart ),
  370. QuadToPaddedHexText( pvdb->MftZoneStart.QuadPart ),
  371. QuadToPaddedHexText( pvdb->MftZoneEnd.QuadPart )
  372. );
  373. } finally {
  374. if (FileHandle != INVALID_HANDLE_VALUE) {
  375. CloseHandle( FileHandle );
  376. }
  377. }
  378. return ExitCode;
  379. }
  380. INT
  381. GetFileSystemStatistics(
  382. IN INT argc,
  383. IN PWSTR argv[]
  384. )
  385. /*++
  386. Routine Description:
  387. This routine gets the file system statistics for the volume
  388. specified.
  389. Arguments:
  390. argc - The argument count.
  391. argv - Array of Strings of the form :
  392. ' fscutl getfss <volume pathname>'.
  393. Return Value:
  394. None
  395. --*/
  396. {
  397. #define FS_STAT(_f) FsStat( FsStats, StrucSize, offsetof(FILESYSTEM_STATISTICS,_f), SysInfo.dwNumberOfProcessors )
  398. #define FAT_STAT(_f) FsStat( FatFsStats, StrucSize, offsetof(FAT_FILE_SYSTEM_STATISTICS,_f), SysInfo.dwNumberOfProcessors )
  399. #define NTFS_STAT(_f) FsStat( NtfsFsStats, StrucSize, offsetof(NTFS_FILE_SYSTEM_STATISTICS,_f), SysInfo.dwNumberOfProcessors )
  400. BOOL Status;
  401. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  402. WCHAR FileName[MAX_PATH];
  403. PFILESYSTEM_STATISTICS FsStats = NULL;
  404. DWORD OutBufferSize;
  405. DWORD BytesReturned;
  406. SYSTEM_INFO SysInfo;
  407. PNTFS_FILE_SYSTEM_STATISTICS NtfsFsStats = NULL;
  408. PFAT_FILE_SYSTEM_STATISTICS FatFsStats = NULL;
  409. ULONG StrucSize;
  410. INT ExitCode = EXIT_CODE_SUCCESS;
  411. try {
  412. if (argc != 1) {
  413. DisplayMsg( MSG_USAGE_GETFSS );
  414. if (argc != 0) {
  415. ExitCode = EXIT_CODE_FAILURE;
  416. }
  417. leave;
  418. }
  419. if (!IsVolumeLocalNTFS( argv[0][0] )) {
  420. DisplayMsg( MSG_NTFS_REQUIRED );
  421. ExitCode = EXIT_CODE_FAILURE;
  422. leave;
  423. }
  424. wcscpy( FileName, L"\\\\.\\" );
  425. wcsncat( FileName, argv[0], (sizeof(FileName)/sizeof(WCHAR))-wcslen(FileName) );
  426. FileHandle = CreateFile(
  427. FileName,
  428. GENERIC_READ,
  429. FILE_SHARE_READ | FILE_SHARE_WRITE,
  430. NULL,
  431. OPEN_EXISTING,
  432. FILE_ATTRIBUTE_NORMAL,
  433. NULL
  434. );
  435. if (FileHandle == INVALID_HANDLE_VALUE) {
  436. DisplayError();
  437. ExitCode = EXIT_CODE_FAILURE;
  438. leave;
  439. }
  440. GetSystemInfo( &SysInfo );
  441. OutBufferSize = max(sizeof(NTFS_FILE_SYSTEM_STATISTICS),sizeof(FAT_FILE_SYSTEM_STATISTICS)) * SysInfo.dwNumberOfProcessors;
  442. FsStats = (PFILESYSTEM_STATISTICS) malloc ( OutBufferSize );
  443. if (FsStats == NULL) {
  444. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  445. ExitCode = EXIT_CODE_FAILURE;
  446. leave;
  447. }
  448. Status = DeviceIoControl(
  449. FileHandle,
  450. FSCTL_FILESYSTEM_GET_STATISTICS,
  451. NULL,
  452. 0,
  453. FsStats,
  454. OutBufferSize,
  455. &BytesReturned,
  456. (LPOVERLAPPED)NULL
  457. );
  458. if (!Status) {
  459. DisplayError();
  460. ExitCode = EXIT_CODE_FAILURE;
  461. leave;
  462. }
  463. switch (FsStats->FileSystemType) {
  464. case FILESYSTEM_STATISTICS_TYPE_NTFS:
  465. DisplayMsg( MSG_FSTYPE_NTFS );
  466. NtfsFsStats = (PNTFS_FILE_SYSTEM_STATISTICS) FsStats;
  467. StrucSize = sizeof(NTFS_FILE_SYSTEM_STATISTICS);
  468. break;
  469. case FILESYSTEM_STATISTICS_TYPE_FAT:
  470. DisplayMsg( MSG_FSTYPE_FAT );
  471. FatFsStats = (PFAT_FILE_SYSTEM_STATISTICS) FsStats;
  472. StrucSize = sizeof(FAT_FILE_SYSTEM_STATISTICS);
  473. break;
  474. }
  475. DisplayMsg(
  476. MSG_GENERAL_FSSTAT,
  477. QuadToDecimalText( FS_STAT(UserFileReads)),
  478. QuadToDecimalText( FS_STAT(UserFileReadBytes)),
  479. QuadToDecimalText( FS_STAT(UserDiskReads)),
  480. QuadToDecimalText( FS_STAT(UserFileWrites)),
  481. QuadToDecimalText( FS_STAT(UserFileWriteBytes)),
  482. QuadToDecimalText( FS_STAT(UserDiskWrites)),
  483. QuadToDecimalText( FS_STAT(MetaDataReads)),
  484. QuadToDecimalText( FS_STAT(MetaDataReadBytes)),
  485. QuadToDecimalText( FS_STAT(MetaDataDiskReads)),
  486. QuadToDecimalText( FS_STAT(MetaDataWrites)),
  487. QuadToDecimalText( FS_STAT(MetaDataWriteBytes)),
  488. QuadToDecimalText( FS_STAT(MetaDataDiskWrites))
  489. );
  490. //
  491. // Print FileSystem specific data
  492. //
  493. switch (FsStats->FileSystemType) {
  494. case FILESYSTEM_STATISTICS_TYPE_FAT:
  495. DisplayMsg(
  496. MSG_FAT_FSSTA,
  497. QuadToDecimalText( FAT_STAT(Fat.CreateHits)),
  498. QuadToDecimalText( FAT_STAT(Fat.SuccessfulCreates)),
  499. QuadToDecimalText( FAT_STAT(Fat.FailedCreates)),
  500. QuadToDecimalText( FAT_STAT(Fat.NonCachedReads)),
  501. QuadToDecimalText( FAT_STAT(Fat.NonCachedReadBytes)),
  502. QuadToDecimalText( FAT_STAT(Fat.NonCachedWrites)),
  503. QuadToDecimalText( FAT_STAT(Fat.NonCachedWriteBytes)),
  504. QuadToDecimalText( FAT_STAT(Fat.NonCachedDiskReads)),
  505. QuadToDecimalText( FAT_STAT(Fat.NonCachedDiskWrites))
  506. );
  507. break;
  508. case FILESYSTEM_STATISTICS_TYPE_NTFS:
  509. DisplayMsg(
  510. MSG_NTFS_FSSTA,
  511. QuadToDecimalText( NTFS_STAT(Ntfs.MftReads)),
  512. QuadToDecimalText( NTFS_STAT(Ntfs.MftReadBytes)),
  513. QuadToDecimalText( NTFS_STAT(Ntfs.MftWrites)),
  514. QuadToDecimalText( NTFS_STAT(Ntfs.MftWriteBytes)),
  515. QuadToDecimalText( NTFS_STAT(Ntfs.Mft2Writes)),
  516. QuadToDecimalText( NTFS_STAT(Ntfs.Mft2WriteBytes)),
  517. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexReads)),
  518. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexReadBytes)),
  519. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexWrites)),
  520. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexWriteBytes)),
  521. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapReads)),
  522. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapReadBytes)),
  523. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapWrites)),
  524. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapWriteBytes)),
  525. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapReads)),
  526. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapReadBytes)),
  527. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapWrites)),
  528. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapWriteBytes)),
  529. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexReads)),
  530. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexReadBytes)),
  531. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexWrites)),
  532. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexWriteBytes)),
  533. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileReads)),
  534. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileReadBytes)),
  535. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileWrites)),
  536. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileWriteBytes))
  537. );
  538. //
  539. // Still some more fields left
  540. //
  541. break;
  542. }
  543. } finally {
  544. if (FileHandle != INVALID_HANDLE_VALUE) {
  545. CloseHandle( FileHandle );
  546. }
  547. if (FsStats) {
  548. free( FsStats );
  549. }
  550. }
  551. return ExitCode;
  552. }