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.

730 lines
21 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. int 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. OutputMessage( L"\r\n" );
  102. DisplayMsg( MSG_DRIVES );
  103. Index = 0;
  104. while ((Length = wcslen( &lpBuffer[Index] )) != 0) {
  105. OutputMessageLength( &lpBuffer[Index], Length );
  106. OutputMessage( L" " );
  107. Index += Length + 1;
  108. }
  109. OutputMessage( L"\r\n" );
  110. } finally {
  111. if (lpBuffer) {
  112. free( lpBuffer );
  113. }
  114. }
  115. return ExitCode;
  116. }
  117. INT
  118. DriveType(
  119. IN INT argc,
  120. IN PWSTR argv[]
  121. )
  122. /*++
  123. Routine Description:
  124. This routine describes the drive type of the drive passed in.
  125. Arguments:
  126. argc - The argument count
  127. argv - Array of Strings of the form :
  128. 'fscutl dt <drive name>' or
  129. 'fscutl drivetype <drive name>'
  130. Return Value:
  131. None
  132. --*/
  133. {
  134. if (argc != 1) {
  135. DisplayMsg( MSG_USAGE_DRIVETYPE );
  136. if (argc != 0) {
  137. return EXIT_CODE_FAILURE;
  138. } else {
  139. return EXIT_CODE_SUCCESS;
  140. }
  141. }
  142. switch (GetDriveType( argv[0] )) {
  143. case DRIVE_NO_ROOT_DIR:
  144. DisplayMsg( MSG_DRIVE_NO_ROOT_DIR, argv[0] );
  145. break;
  146. case DRIVE_REMOVABLE:
  147. DisplayMsg( MSG_DRIVE_REMOVABLE, argv[0] );
  148. break;
  149. case DRIVE_FIXED:
  150. DisplayMsg( MSG_DRIVE_FIXED, argv[0] );
  151. break;
  152. case DRIVE_REMOTE:
  153. DisplayMsg( MSG_DRIVE_REMOTE, argv[0] );
  154. break;
  155. case DRIVE_CDROM:
  156. DisplayMsg( MSG_DRIVE_CDROM, argv[0] );
  157. break;
  158. case DRIVE_RAMDISK:
  159. DisplayMsg( MSG_DRIVE_RAMDISK, argv[0] );
  160. break;
  161. case DRIVE_UNKNOWN:
  162. default:
  163. DisplayMsg( MSG_DRIVE_UNKNOWN, argv[0] );
  164. break;
  165. }
  166. return EXIT_CODE_SUCCESS;
  167. }
  168. INT
  169. VolumeInfo(
  170. IN INT argc,
  171. IN PWSTR argv[]
  172. )
  173. /*++
  174. Routine Description:
  175. This routine provides the information about the Volume.
  176. Arguments:
  177. argc - The argument count
  178. argv - Array of Strings of the form :
  179. 'fscutl infov <root pathname>'.
  180. Return Value:
  181. None
  182. --*/
  183. {
  184. LPWSTR lpVolumeNameBuffer = NULL; // address of name of the volume
  185. DWORD nVolumeNameSize; // length of lpVolumeNameBuffer
  186. LPDWORD lpVolumeSerialNumber = NULL; // address of volume serial number
  187. LPDWORD lpMaximumComponentLength = NULL; // address of system's maximum
  188. // filename length
  189. LPDWORD lpFileSystemFlags = NULL; // address of file system flags
  190. LPWSTR lpFileSystemNameBuffer = NULL; // address of name of file system
  191. DWORD nFileSystemNameSize; // length of lpFileSystemNameBuffer
  192. BOOL Status; // return status
  193. DWORD dwMask; // FileSystem Flag Mask
  194. DWORD Index;
  195. DWORD FsFlag;
  196. INT ExitCode = EXIT_CODE_SUCCESS;
  197. try {
  198. if (argc != 1) {
  199. DisplayMsg( MSG_USAGE_INFOV );
  200. if (argc != 0) {
  201. ExitCode = EXIT_CODE_FAILURE;
  202. }
  203. leave ;
  204. }
  205. nVolumeNameSize = MAX_PATH;
  206. lpVolumeNameBuffer = (LPWSTR) malloc ( MAX_PATH * sizeof(WCHAR) );
  207. if (lpVolumeNameBuffer == NULL) {
  208. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  209. ExitCode = EXIT_CODE_FAILURE;
  210. leave;
  211. }
  212. lpVolumeSerialNumber = (LPDWORD) malloc( sizeof(DWORD) );
  213. if (lpVolumeSerialNumber == NULL) {
  214. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  215. ExitCode = EXIT_CODE_FAILURE;
  216. leave;
  217. }
  218. lpFileSystemFlags = (LPDWORD) malloc ( sizeof(DWORD) );
  219. if (lpFileSystemFlags == NULL) {
  220. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  221. ExitCode = EXIT_CODE_FAILURE;
  222. leave;
  223. }
  224. lpMaximumComponentLength = (LPDWORD) malloc ( sizeof(DWORD) );
  225. if (lpMaximumComponentLength == NULL) {
  226. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  227. ExitCode = EXIT_CODE_FAILURE;
  228. leave;
  229. }
  230. nFileSystemNameSize = MAX_PATH;
  231. lpFileSystemNameBuffer = (LPWSTR) malloc ( MAX_PATH * sizeof(WCHAR) );
  232. if (lpFileSystemNameBuffer == NULL) {
  233. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  234. ExitCode = EXIT_CODE_FAILURE;
  235. leave;
  236. }
  237. Status = GetVolumeInformation (
  238. argv[0],
  239. lpVolumeNameBuffer,
  240. nVolumeNameSize,
  241. lpVolumeSerialNumber,
  242. lpMaximumComponentLength,
  243. lpFileSystemFlags,
  244. lpFileSystemNameBuffer,
  245. nFileSystemNameSize
  246. );
  247. if (!Status) {
  248. DisplayError();
  249. ExitCode = EXIT_CODE_FAILURE;
  250. leave;
  251. }
  252. DisplayMsg( MSG_VOLNAME, lpVolumeNameBuffer );
  253. DisplayMsg( MSG_SERIALNO, *lpVolumeSerialNumber );
  254. DisplayMsg( MSG_MAX_COMP_LEN, *lpMaximumComponentLength );
  255. DisplayMsg( MSG_FS_NAME, lpFileSystemNameBuffer );
  256. dwMask = 1 ;
  257. FsFlag = *lpFileSystemFlags;
  258. for ( Index=0 ; Index<32 ; Index++ ) {
  259. switch (FsFlag & dwMask) {
  260. case FILE_CASE_SENSITIVE_SEARCH:
  261. DisplayMsg( MSG_FILE_CASE_SENSITIVE_SEARCH );
  262. break;
  263. case FILE_CASE_PRESERVED_NAMES:
  264. DisplayMsg( MSG_FILE_CASE_PRESERVED_NAMES );
  265. break;
  266. case FILE_UNICODE_ON_DISK:
  267. DisplayMsg( MSG_FILE_UNICODE_ON_DISK );
  268. break;
  269. case FILE_PERSISTENT_ACLS:
  270. DisplayMsg( MSG_FILE_PERSISTENT_ACLS );
  271. break;
  272. case FILE_FILE_COMPRESSION:
  273. DisplayMsg( MSG_FILE_FILE_COMPRESSION );
  274. break;
  275. case FILE_VOLUME_QUOTAS:
  276. DisplayMsg( MSG_FILE_VOLUME_QUOTAS );
  277. break;
  278. case FILE_SUPPORTS_SPARSE_FILES:
  279. DisplayMsg( MSG_FILE_SUPPORTS_SPARSE_FILES );
  280. break;
  281. case FILE_SUPPORTS_REPARSE_POINTS:
  282. DisplayMsg( MSG_FILE_SUPPORTS_REPARSE_POINTS );
  283. break;
  284. case FILE_SUPPORTS_REMOTE_STORAGE:
  285. DisplayMsg( MSG_FILE_SUPPORTS_REMOTE_STORAGE );
  286. break;
  287. case FILE_VOLUME_IS_COMPRESSED:
  288. DisplayMsg( MSG_FILE_VOLUME_IS_COMPRESSED );
  289. break;
  290. case FILE_SUPPORTS_OBJECT_IDS:
  291. DisplayMsg( MSG_FILE_SUPPORTS_OBJECT_IDS );
  292. break;
  293. case FILE_SUPPORTS_ENCRYPTION:
  294. DisplayMsg( MSG_FILE_SUPPORTS_ENCRYPTION );
  295. break;
  296. case FILE_NAMED_STREAMS:
  297. DisplayMsg( MSG_FILE_NAMED_STREAMS );
  298. break;
  299. }
  300. dwMask <<= 1;
  301. }
  302. } finally {
  303. free( lpVolumeNameBuffer );
  304. free( lpVolumeSerialNumber );
  305. free( lpFileSystemFlags );
  306. free( lpMaximumComponentLength );
  307. free( lpFileSystemNameBuffer );
  308. }
  309. return ExitCode;
  310. }
  311. INT
  312. GetNtfsVolumeData(
  313. IN INT argc,
  314. IN PWSTR argv[]
  315. )
  316. /*++
  317. Routine Description:
  318. This routine gets the NTFS volume data for the volume
  319. specified.
  320. Arguments:
  321. argc - The argument count.
  322. argv - Array of Strings of the form :
  323. ' fscutl getntfsdv <volume pathname>'.
  324. Return Value:
  325. None
  326. --*/
  327. {
  328. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  329. WCHAR FileName[MAX_PATH];
  330. BOOL Status;
  331. BYTE Buffer[sizeof( NTFS_VOLUME_DATA_BUFFER ) + sizeof( NTFS_EXTENDED_VOLUME_DATA )];
  332. PNTFS_VOLUME_DATA_BUFFER pvdb = (PNTFS_VOLUME_DATA_BUFFER)Buffer;
  333. PNTFS_EXTENDED_VOLUME_DATA pevd = (PNTFS_EXTENDED_VOLUME_DATA)(pvdb + 1);
  334. DWORD BytesReturned;
  335. INT ExitCode = EXIT_CODE_SUCCESS;
  336. try {
  337. if (argc != 1) {
  338. DisplayMsg( MSG_USAGE_NTFSINFO );
  339. if (argc != 0) {
  340. ExitCode = EXIT_CODE_FAILURE;
  341. }
  342. leave;
  343. }
  344. if (!IsVolumeLocalNTFS( argv[0][0] )) {
  345. DisplayMsg( MSG_NTFS_REQUIRED );
  346. ExitCode = EXIT_CODE_FAILURE;
  347. leave;
  348. }
  349. if (wcslen( DotPrefix ) + wcslen( argv[0] ) + 1 > MAX_PATH) {
  350. DisplayMsg( MSG_FILENAME_TOO_LONG );
  351. ExitCode = EXIT_CODE_FAILURE;
  352. leave;
  353. }
  354. wcscpy( FileName, DotPrefix );
  355. wcscat( FileName, argv[0] );
  356. FileHandle = CreateFile(
  357. FileName,
  358. GENERIC_READ,
  359. FILE_SHARE_READ | FILE_SHARE_WRITE,
  360. NULL,
  361. OPEN_EXISTING,
  362. FILE_ATTRIBUTE_NORMAL,
  363. NULL
  364. );
  365. if (FileHandle == INVALID_HANDLE_VALUE) {
  366. DisplayError();
  367. ExitCode = EXIT_CODE_FAILURE;
  368. leave;
  369. }
  370. Status = DeviceIoControl(
  371. FileHandle,
  372. FSCTL_GET_NTFS_VOLUME_DATA,
  373. NULL,
  374. 0,
  375. pvdb,
  376. sizeof( Buffer ),
  377. &BytesReturned,
  378. (LPOVERLAPPED)NULL
  379. );
  380. if (!Status) {
  381. DisplayError();
  382. ExitCode = EXIT_CODE_FAILURE;
  383. leave;
  384. }
  385. DisplayMsg(
  386. MSG_NTFSINFO_STATS,
  387. QuadToPaddedHexText( pvdb->VolumeSerialNumber.QuadPart ), // Serial number in hex
  388. pevd->MajorVersion,
  389. pevd->MinorVersion,
  390. QuadToPaddedHexText( pvdb->NumberSectors.QuadPart ),
  391. QuadToPaddedHexText( pvdb->TotalClusters.QuadPart ),
  392. QuadToPaddedHexText( pvdb->FreeClusters.QuadPart ),
  393. QuadToPaddedHexText( pvdb->TotalReserved.QuadPart ),
  394. pvdb->BytesPerSector,
  395. pvdb->BytesPerCluster,
  396. pvdb->BytesPerFileRecordSegment,
  397. pvdb->ClustersPerFileRecordSegment,
  398. QuadToPaddedHexText( pvdb->MftValidDataLength.QuadPart ),
  399. QuadToPaddedHexText( pvdb->MftStartLcn.QuadPart ),
  400. QuadToPaddedHexText( pvdb->Mft2StartLcn.QuadPart ),
  401. QuadToPaddedHexText( pvdb->MftZoneStart.QuadPart ),
  402. QuadToPaddedHexText( pvdb->MftZoneEnd.QuadPart )
  403. );
  404. } finally {
  405. if (FileHandle != INVALID_HANDLE_VALUE) {
  406. CloseHandle( FileHandle );
  407. }
  408. }
  409. return ExitCode;
  410. }
  411. INT
  412. GetFileSystemStatistics(
  413. IN INT argc,
  414. IN PWSTR argv[]
  415. )
  416. /*++
  417. Routine Description:
  418. This routine gets the file system statistics for the volume
  419. specified.
  420. Arguments:
  421. argc - The argument count.
  422. argv - Array of Strings of the form :
  423. ' fscutl getfss <volume pathname>'.
  424. Return Value:
  425. None
  426. --*/
  427. {
  428. #define FS_STAT(_f) FsStat( FsStats, StrucSize, offsetof(FILESYSTEM_STATISTICS,_f), SysInfo.dwNumberOfProcessors )
  429. #define FAT_STAT(_f) FsStat( FatFsStats, StrucSize, offsetof(FAT_FILE_SYSTEM_STATISTICS,_f), SysInfo.dwNumberOfProcessors )
  430. #define NTFS_STAT(_f) FsStat( NtfsFsStats, StrucSize, offsetof(NTFS_FILE_SYSTEM_STATISTICS,_f), SysInfo.dwNumberOfProcessors )
  431. BOOL Status;
  432. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  433. WCHAR FileName[MAX_PATH];
  434. PFILESYSTEM_STATISTICS FsStats = NULL;
  435. DWORD OutBufferSize;
  436. DWORD BytesReturned;
  437. SYSTEM_INFO SysInfo;
  438. PNTFS_FILE_SYSTEM_STATISTICS NtfsFsStats = NULL;
  439. PFAT_FILE_SYSTEM_STATISTICS FatFsStats = NULL;
  440. ULONG StrucSize;
  441. INT ExitCode = EXIT_CODE_SUCCESS;
  442. try {
  443. if (argc != 1) {
  444. DisplayMsg( MSG_USAGE_GETFSS );
  445. if (argc != 0) {
  446. ExitCode = EXIT_CODE_FAILURE;
  447. }
  448. leave;
  449. }
  450. if (!IsVolumeLocalNTFS( argv[0][0] )) {
  451. DisplayMsg( MSG_NTFS_REQUIRED );
  452. ExitCode = EXIT_CODE_FAILURE;
  453. leave;
  454. }
  455. if (wcslen( DotPrefix ) + wcslen( argv[0] ) + 1 > MAX_PATH) {
  456. DisplayMsg( MSG_FILENAME_TOO_LONG );
  457. ExitCode = EXIT_CODE_FAILURE;
  458. leave;
  459. }
  460. wcscpy( FileName, DotPrefix );
  461. wcscat( FileName, argv[0] );
  462. FileHandle = CreateFile(
  463. FileName,
  464. GENERIC_READ,
  465. FILE_SHARE_READ | FILE_SHARE_WRITE,
  466. NULL,
  467. OPEN_EXISTING,
  468. FILE_ATTRIBUTE_NORMAL,
  469. NULL
  470. );
  471. if (FileHandle == INVALID_HANDLE_VALUE) {
  472. DisplayError();
  473. ExitCode = EXIT_CODE_FAILURE;
  474. leave;
  475. }
  476. GetSystemInfo( &SysInfo );
  477. OutBufferSize = max(sizeof(NTFS_FILE_SYSTEM_STATISTICS),sizeof(FAT_FILE_SYSTEM_STATISTICS)) * SysInfo.dwNumberOfProcessors;
  478. FsStats = (PFILESYSTEM_STATISTICS) malloc ( OutBufferSize );
  479. if (FsStats == NULL) {
  480. DisplayErrorMsg( ERROR_NOT_ENOUGH_MEMORY );
  481. ExitCode = EXIT_CODE_FAILURE;
  482. leave;
  483. }
  484. Status = DeviceIoControl(
  485. FileHandle,
  486. FSCTL_FILESYSTEM_GET_STATISTICS,
  487. NULL,
  488. 0,
  489. FsStats,
  490. OutBufferSize,
  491. &BytesReturned,
  492. (LPOVERLAPPED)NULL
  493. );
  494. if (!Status) {
  495. DisplayError();
  496. ExitCode = EXIT_CODE_FAILURE;
  497. leave;
  498. }
  499. switch (FsStats->FileSystemType) {
  500. case FILESYSTEM_STATISTICS_TYPE_NTFS:
  501. DisplayMsg( MSG_FSTYPE_NTFS );
  502. NtfsFsStats = (PNTFS_FILE_SYSTEM_STATISTICS) FsStats;
  503. StrucSize = sizeof(NTFS_FILE_SYSTEM_STATISTICS);
  504. break;
  505. case FILESYSTEM_STATISTICS_TYPE_FAT:
  506. DisplayMsg( MSG_FSTYPE_FAT );
  507. FatFsStats = (PFAT_FILE_SYSTEM_STATISTICS) FsStats;
  508. StrucSize = sizeof(FAT_FILE_SYSTEM_STATISTICS);
  509. break;
  510. }
  511. DisplayMsg(
  512. MSG_GENERAL_FSSTAT,
  513. QuadToDecimalText( FS_STAT(UserFileReads)),
  514. QuadToDecimalText( FS_STAT(UserFileReadBytes)),
  515. QuadToDecimalText( FS_STAT(UserDiskReads)),
  516. QuadToDecimalText( FS_STAT(UserFileWrites)),
  517. QuadToDecimalText( FS_STAT(UserFileWriteBytes)),
  518. QuadToDecimalText( FS_STAT(UserDiskWrites)),
  519. QuadToDecimalText( FS_STAT(MetaDataReads)),
  520. QuadToDecimalText( FS_STAT(MetaDataReadBytes)),
  521. QuadToDecimalText( FS_STAT(MetaDataDiskReads)),
  522. QuadToDecimalText( FS_STAT(MetaDataWrites)),
  523. QuadToDecimalText( FS_STAT(MetaDataWriteBytes)),
  524. QuadToDecimalText( FS_STAT(MetaDataDiskWrites))
  525. );
  526. //
  527. // Print FileSystem specific data
  528. //
  529. switch (FsStats->FileSystemType) {
  530. case FILESYSTEM_STATISTICS_TYPE_FAT:
  531. DisplayMsg(
  532. MSG_FAT_FSSTA,
  533. QuadToDecimalText( FAT_STAT(Fat.CreateHits)),
  534. QuadToDecimalText( FAT_STAT(Fat.SuccessfulCreates)),
  535. QuadToDecimalText( FAT_STAT(Fat.FailedCreates)),
  536. QuadToDecimalText( FAT_STAT(Fat.NonCachedReads)),
  537. QuadToDecimalText( FAT_STAT(Fat.NonCachedReadBytes)),
  538. QuadToDecimalText( FAT_STAT(Fat.NonCachedWrites)),
  539. QuadToDecimalText( FAT_STAT(Fat.NonCachedWriteBytes)),
  540. QuadToDecimalText( FAT_STAT(Fat.NonCachedDiskReads)),
  541. QuadToDecimalText( FAT_STAT(Fat.NonCachedDiskWrites))
  542. );
  543. break;
  544. case FILESYSTEM_STATISTICS_TYPE_NTFS:
  545. DisplayMsg(
  546. MSG_NTFS_FSSTA,
  547. QuadToDecimalText( NTFS_STAT(Ntfs.MftReads)),
  548. QuadToDecimalText( NTFS_STAT(Ntfs.MftReadBytes)),
  549. QuadToDecimalText( NTFS_STAT(Ntfs.MftWrites)),
  550. QuadToDecimalText( NTFS_STAT(Ntfs.MftWriteBytes)),
  551. QuadToDecimalText( NTFS_STAT(Ntfs.Mft2Writes)),
  552. QuadToDecimalText( NTFS_STAT(Ntfs.Mft2WriteBytes)),
  553. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexReads)),
  554. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexReadBytes)),
  555. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexWrites)),
  556. QuadToDecimalText( NTFS_STAT(Ntfs.RootIndexWriteBytes)),
  557. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapReads)),
  558. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapReadBytes)),
  559. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapWrites)),
  560. QuadToDecimalText( NTFS_STAT(Ntfs.BitmapWriteBytes)),
  561. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapReads)),
  562. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapReadBytes)),
  563. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapWrites)),
  564. QuadToDecimalText( NTFS_STAT(Ntfs.MftBitmapWriteBytes)),
  565. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexReads)),
  566. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexReadBytes)),
  567. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexWrites)),
  568. QuadToDecimalText( NTFS_STAT(Ntfs.UserIndexWriteBytes)),
  569. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileReads)),
  570. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileReadBytes)),
  571. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileWrites)),
  572. QuadToDecimalText( NTFS_STAT(Ntfs.LogFileWriteBytes))
  573. );
  574. //
  575. // Still some more fields left
  576. //
  577. break;
  578. }
  579. } finally {
  580. if (FileHandle != INVALID_HANDLE_VALUE) {
  581. CloseHandle( FileHandle );
  582. }
  583. if (FsStats) {
  584. free( FsStats );
  585. }
  586. }
  587. return ExitCode;
  588. }