ReactOS  0.4.12-dev-102-g4b7f1e0
fsinfo.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS FS utility tool
4  * FILE: base/applications/cmdutils/fsinfo.c
5  * PURPOSE: FSutil file systems information
6  * PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
7  */
8 
9 #include "fsutil.h"
10 
11 /* Add handlers here for subcommands */
18 {
19  /* Proc, name, help */
20  { DrivesMain, _T("drives"), _T("Enumerates the drives") },
21  { DriveTypeMain, _T("drivetype"), _T("Provides the type of a drive") },
22  { VolumeInfoMain, _T("volumeinfo"), _T("Provides informations about a volume") },
23  { NtfsInfoMain, _T("ntfsinfo"), _T("Displays informations about a NTFS volume") },
24  { StatisticsMain, _T("statistics"), _T("Displays volume statistics") },
25 };
26 
27 static int
28 DrivesMain(int argc, const TCHAR *argv[])
29 {
30  UINT i;
31  DWORD Drives;
32 
33  /* Get the drives bitmap */
34  Drives = GetLogicalDrives();
35  if (Drives == 0)
36  {
38  return 1;
39  }
40 
41  /* And output any found drive */
42  _ftprintf(stdout, _T("Drives:"));
43  for (i = 0; i < 26; i++)
44  {
45  if (Drives & (1 << i))
46  {
47  _ftprintf(stdout, _T(" %c:\\"), 'A' + i);
48  }
49  }
50  _ftprintf(stdout, _T("\n"));
51 
52  return 0;
53 }
54 
55 static int
56 DriveTypeMain(int argc, const TCHAR *argv[])
57 {
58  UINT Type;
59 
60  /* We need a volume (letter) */
61  if (argc < 2)
62  {
63  _ftprintf(stderr, _T("Usage: fsutil fsinfo drivetype <volume>\n"));
64  _ftprintf(stderr, _T("\tFor example: fsutil fsinfo drivetype c:\n"));
65  return 1;
66  }
67 
68  /* Get its drive type and make it readable */
69  Type = GetDriveType(argv[1]);
70  switch (Type)
71  {
72  case DRIVE_UNKNOWN:
73  _ftprintf(stdout, _T("%s - unknown drive type\n"), argv[1]);
74  break;
75 
76  case DRIVE_NO_ROOT_DIR:
77  _ftprintf(stdout, _T("%s - not a root directory\n"), argv[1]);
78  break;
79 
80  case DRIVE_REMOVABLE:
81  _ftprintf(stdout, _T("%s - removable drive\n"), argv[1]);
82  break;
83 
84  case DRIVE_FIXED:
85  _ftprintf(stdout, _T("%s - fixed drive\n"), argv[1]);
86  break;
87 
88  case DRIVE_REMOTE:
89  _ftprintf(stdout, _T("%s - remote or network drive\n"), argv[1]);
90  break;
91 
92  case DRIVE_CDROM:
93  _ftprintf(stdout, _T("%s - CD-ROM drive\n"), argv[1]);
94  break;
95 
96  case DRIVE_RAMDISK:
97  _ftprintf(stdout, _T("%s - RAM disk drive\n"), argv[1]);
98  break;
99  }
100 
101  return 0;
102 }
103 
104 static int
106 {
107  DWORD Serial, MaxComponentLen, Flags;
109 
110 #define HANDLE_FLAG(Flags, Flag, Desc) \
111  if (Flags & Flag) \
112  _ftprintf(stdout, Desc)
113 
114  /* We need a volume (path) */
115  if (argc < 2)
116  {
117  _ftprintf(stderr, _T("Usage: fsutil fsinfo volumeinfo <volume_path>\n"));
118  _ftprintf(stderr, _T("\tFor example: fsutil fsinfo volumeinfo c:\\\n"));
119  return 1;
120  }
121 
122  /* Gather information */
123  if (!GetVolumeInformation(argv[1], VolumeName, MAX_PATH + 1, &Serial,
124  &MaxComponentLen, &Flags, FileSystem, MAX_PATH + 1))
125  {
127  return 1;
128  }
129 
130  /* Display general information */
131  _ftprintf(stdout, _T("Volume name: %s\n"), VolumeName);
132  _ftprintf(stdout, _T("Volume serial number: 0x%x\n"), Serial);
133  _ftprintf(stdout, _T("Maximum component length: %u\n"), MaxComponentLen);
134  _ftprintf(stdout, _T("File system name: %s\n"), FileSystem);
135 
136  /* Display specific flags */
137  HANDLE_FLAG(Flags, FILE_CASE_SENSITIVE_SEARCH, _T("Supports case-sensitive file names\n"));
138  HANDLE_FLAG(Flags, FILE_CASE_PRESERVED_NAMES, _T("Supports preserved case of file names\n"));
139  HANDLE_FLAG(Flags, FILE_UNICODE_ON_DISK, _T("Supports unicode file names\n"));
140  HANDLE_FLAG(Flags, FILE_PERSISTENT_ACLS, _T("Preserves and applies ACLs\n"));
141  HANDLE_FLAG(Flags, FILE_FILE_COMPRESSION, _T("Supports compression per file\n"));
142  HANDLE_FLAG(Flags, FILE_VOLUME_QUOTAS, _T("Supports disk quotas\n"));
143  HANDLE_FLAG(Flags, FILE_SUPPORTS_SPARSE_FILES, _T("Supports sparse files\n"));
144  HANDLE_FLAG(Flags, FILE_SUPPORTS_REPARSE_POINTS, _T("Supports reparse points\n"));
145  HANDLE_FLAG(Flags, FILE_VOLUME_IS_COMPRESSED, _T("Is a compressed volume\n"));
146  HANDLE_FLAG(Flags, FILE_SUPPORTS_OBJECT_IDS, _T("Supports object identifiers\n"));
147  HANDLE_FLAG(Flags, FILE_SUPPORTS_ENCRYPTION, _T("Supports the Encrypted File System (EFS)\n"));
148  HANDLE_FLAG(Flags, FILE_NAMED_STREAMS, _T("Supports named streams\n"));
149  HANDLE_FLAG(Flags, FILE_READ_ONLY_VOLUME, _T("Is a read-only volume\n"));
150  HANDLE_FLAG(Flags, FILE_SEQUENTIAL_WRITE_ONCE, _T("Supports a single sequential write\n"));
151  HANDLE_FLAG(Flags, FILE_SUPPORTS_TRANSACTIONS, _T("Supports transactions\n"));
152  HANDLE_FLAG(Flags, FILE_SUPPORTS_HARD_LINKS, _T("Supports hard links\n"));
153  HANDLE_FLAG(Flags, FILE_SUPPORTS_EXTENDED_ATTRIBUTES, _T("Supports extended attributes\n"));
154  HANDLE_FLAG(Flags, FILE_SUPPORTS_OPEN_BY_FILE_ID, _T("Supports opening files per file identifier\n"));
155  HANDLE_FLAG(Flags, FILE_SUPPORTS_USN_JOURNAL, _T("Supports Update Sequence Number (USN) journals\n"));
156  HANDLE_FLAG(Flags, FILE_DAX_VOLUME, _T("Is a direct access volume\n"));
157 
158 #undef HANDLE_FLAGS
159 
160  return 0;
161 }
162 
163 static int
164 NtfsInfoMain(int argc, const TCHAR *argv[])
165 {
166  HANDLE Volume;
168  struct
169  {
172  } Data;
173 
174  /* We need a volume (letter or GUID) */
175  if (argc < 2)
176  {
177  _ftprintf(stderr, _T("Usage: fsutil fsinfo ntfsinfo <volume>\n"));
178  _ftprintf(stderr, _T("\tFor example: fsutil fsinfo ntfsinfo c:\n"));
179  return 1;
180  }
181 
182  /* Get a handle for the volume */
183  Volume = OpenVolume(argv[1], FALSE, TRUE);
184  if (Volume == INVALID_HANDLE_VALUE)
185  {
186  return 1;
187  }
188 
189  /* And query the NTFS data */
191  sizeof(Data), &BytesRead, NULL) == FALSE)
192  {
194  CloseHandle(Volume);
195  return 1;
196  }
197 
198  /* We no longer need the volume */
199  CloseHandle(Volume);
200 
201  /* Dump data */
202  _ftprintf(stdout, _T("NTFS volume serial number:\t\t0x%0.16I64x\n"), Data.VolumeSerialNumber.QuadPart);
203  /* Only print version if extended structure was returned */
204  if (BytesRead > sizeof(NTFS_VOLUME_DATA_BUFFER))
205  {
206  _ftprintf(stdout, _T("Version:\t\t\t\t%u.%u\n"), Data.MajorVersion, Data.MinorVersion);
207  }
208  _ftprintf(stdout, _T("Number of sectors:\t\t\t0x%0.16I64x\n"), Data.NumberSectors.QuadPart);
209  _ftprintf(stdout, _T("Total number of clusters:\t\t0x%0.16I64x\n"), Data.TotalClusters.QuadPart);
210  _ftprintf(stdout, _T("Free clusters:\t\t\t\t0x%0.16I64x\n"), Data.FreeClusters.QuadPart);
211  _ftprintf(stdout, _T("Total number of reserved clusters:\t0x%0.16I64x\n"), Data.TotalReserved.QuadPart);
212  _ftprintf(stdout, _T("Bytes per sector:\t\t\t%d\n"), Data.BytesPerSector);
213  _ftprintf(stdout, _T("Bytes per cluster:\t\t\t%d\n"), Data.BytesPerCluster);
214  _ftprintf(stdout, _T("Bytes per file record segment:\t\t%d\n"), Data.BytesPerFileRecordSegment);
215  _ftprintf(stdout, _T("Clusters per file record segment:\t%d\n"), Data.ClustersPerFileRecordSegment);
216  _ftprintf(stdout, _T("MFT valid data length:\t\t\t0x%0.16I64x\n"), Data.MftValidDataLength.QuadPart);
217  _ftprintf(stdout, _T("MFT start LCN:\t\t\t\t0x%0.16I64x\n"), Data.MftStartLcn.QuadPart);
218  _ftprintf(stdout, _T("MFT2 start LCN:\t\t\t\t0x%0.16I64x\n"), Data.Mft2StartLcn.QuadPart);
219  _ftprintf(stdout, _T("MFT zone start:\t\t\t\t0x%0.16I64x\n"), Data.MftZoneStart.QuadPart);
220  _ftprintf(stdout, _T("MFT zone end:\t\t\t\t0x%0.16I64x\n"), Data.MftZoneEnd.QuadPart);
221 
222  return 0;
223 }
224 
225 #define DUMP_VALUE(stats, value) fprintf(stdout, "%s: %lu\n", #value, stats->value)
226 
227 static void
229 {
230  /* Print FS name */
231  _ftprintf(stdout, _T("File system type: %s\n\n"), Name);
232 
233  /* And then, dump any base stat */
234  DUMP_VALUE(Base, UserFileReads);
235  DUMP_VALUE(Base, UserFileReadBytes);
236  DUMP_VALUE(Base, UserDiskReads);
237  DUMP_VALUE(Base, UserFileWrites);
238  DUMP_VALUE(Base, UserFileWriteBytes);
239  DUMP_VALUE(Base, UserDiskWrites);
240  DUMP_VALUE(Base, MetaDataReads);
241  DUMP_VALUE(Base, MetaDataReadBytes);
242  DUMP_VALUE(Base, MetaDataDiskReads);
243  DUMP_VALUE(Base, MetaDataWrites);
244  DUMP_VALUE(Base, MetaDataWriteBytes);
245  DUMP_VALUE(Base, MetaDataDiskWrites);
246 
247  _ftprintf(stdout, _T("\n"));
248 }
249 
250 static void
251 DumpExFat(PVOID Statistics, PVOID Specific)
252 {
253  PEXFAT_STATISTICS ExFat;
255 
256  Base = Statistics;
257  ExFat = Specific;
258 
259  /* First, display the generic stats */
260  DumpBase(Base, _T("EXFAT"));
261 
262  /* Then, display the EXFAT specific ones */
263  DUMP_VALUE(ExFat, CreateHits);
264  DUMP_VALUE(ExFat, SuccessfulCreates);
265  DUMP_VALUE(ExFat, FailedCreates);
266  DUMP_VALUE(ExFat, NonCachedReads);
267  DUMP_VALUE(ExFat, NonCachedReadBytes);
268  DUMP_VALUE(ExFat, NonCachedWrites);
269  DUMP_VALUE(ExFat, NonCachedWriteBytes);
270  DUMP_VALUE(ExFat, NonCachedDiskReads);
271  DUMP_VALUE(ExFat, NonCachedDiskWrites);
272 }
273 
274 static void
275 DumpFat(PVOID Statistics, PVOID Specific)
276 {
277  PFAT_STATISTICS Fat;
279 
280  Base = Statistics;
281  Fat = Specific;
282 
283  /* First, display the generic stats */
284  DumpBase(Base, _T("FAT"));
285 
286  /* Then, display the FAT specific ones */
287  DUMP_VALUE(Fat, CreateHits);
288  DUMP_VALUE(Fat, SuccessfulCreates);
289  DUMP_VALUE(Fat, FailedCreates);
290  DUMP_VALUE(Fat, NonCachedReads);
291  DUMP_VALUE(Fat, NonCachedReadBytes);
292  DUMP_VALUE(Fat, NonCachedWrites);
293  DUMP_VALUE(Fat, NonCachedWriteBytes);
294  DUMP_VALUE(Fat, NonCachedDiskReads);
295  DUMP_VALUE(Fat, NonCachedDiskWrites);
296 }
297 
298 static void
299 DumpNtfs(PVOID Statistics, PVOID Specific)
300 {
301  PNTFS_STATISTICS Ntfs;
303 
304  Base = Statistics;
305  Ntfs = Specific;
306 
307  /* First, display the generic stats */
308  DumpBase(Base, _T("NTFS"));
309 
310  /* Then, display the NTFS specific ones */
311  DUMP_VALUE(Ntfs, MftReads);
312  DUMP_VALUE(Ntfs, MftReadBytes);
313  DUMP_VALUE(Ntfs, MftWrites);
314  DUMP_VALUE(Ntfs, MftWriteBytes);
315  DUMP_VALUE(Ntfs, Mft2Writes);
316  DUMP_VALUE(Ntfs, Mft2WriteBytes);
317  DUMP_VALUE(Ntfs, RootIndexReads);
318  DUMP_VALUE(Ntfs, RootIndexReadBytes);
319  DUMP_VALUE(Ntfs, RootIndexWrites);
320  DUMP_VALUE(Ntfs, RootIndexWriteBytes);
321  DUMP_VALUE(Ntfs, BitmapReads);
322  DUMP_VALUE(Ntfs, BitmapReadBytes);
323  DUMP_VALUE(Ntfs, BitmapWrites);
324  DUMP_VALUE(Ntfs, BitmapWriteBytes);
325  DUMP_VALUE(Ntfs, MftBitmapReads);
326  DUMP_VALUE(Ntfs, MftBitmapReadBytes);
327  DUMP_VALUE(Ntfs, MftBitmapWrites);
328  DUMP_VALUE(Ntfs, MftBitmapWriteBytes);
329  DUMP_VALUE(Ntfs, UserIndexReads);
330  DUMP_VALUE(Ntfs, UserIndexReadBytes);
331  DUMP_VALUE(Ntfs, UserIndexWrites);
332  DUMP_VALUE(Ntfs, UserIndexWriteBytes);
333  DUMP_VALUE(Ntfs, LogFileReads);
334  DUMP_VALUE(Ntfs, LogFileReadBytes);
335  DUMP_VALUE(Ntfs, LogFileWrites);
336  DUMP_VALUE(Ntfs, LogFileWriteBytes);
337 }
338 
339 #define GET_NEXT(stats, length, iter, type) (type)((ULONG_PTR)stats + (length * iter))
340 #define SUM_VALUE(stats, new, value) stats->value += new->value
341 
342 inline int
343 ValidateSizes(ULONG Length, DWORD ProcCount, DWORD BytesRead, DWORD SpecificSize)
344 {
345  /* Check whether we could read our base length for every processor */
346  if (Length * ProcCount > BytesRead)
347  {
348  _ftprintf(stderr, _T("Only performed a partial read: %lu (expected: %lu)\n"), BytesRead, Length * ProcCount);
349  return 1;
350  }
351 
352  /* Check whether this covers a specific entry and a generic entry for every processor */
353  if ((sizeof(FILESYSTEM_STATISTICS) + SpecificSize) * ProcCount > BytesRead)
354  {
355  _ftprintf(stderr, _T("Only performed a partial read: %lu (expected: %lu)\n"), BytesRead, (sizeof(FILESYSTEM_STATISTICS) + SpecificSize));
356  return 1;
357  }
358 
359  return 0;
360 }
361 
362 inline void
364 {
365  /* Sum any entry in the generic structures */
366  SUM_VALUE(Base, NextBase, UserFileReads);
367  SUM_VALUE(Base, NextBase, UserFileReadBytes);
368  SUM_VALUE(Base, NextBase, UserDiskReads);
369  SUM_VALUE(Base, NextBase, UserFileWrites);
370  SUM_VALUE(Base, NextBase, UserFileWriteBytes);
371  SUM_VALUE(Base, NextBase, UserDiskWrites);
372  SUM_VALUE(Base, NextBase, MetaDataReads);
373  SUM_VALUE(Base, NextBase, MetaDataReadBytes);
374  SUM_VALUE(Base, NextBase, MetaDataDiskReads);
375  SUM_VALUE(Base, NextBase, MetaDataWrites);
376  SUM_VALUE(Base, NextBase, MetaDataWriteBytes);
377  SUM_VALUE(Base, NextBase, MetaDataDiskWrites);
378 }
379 
380 static int
381 SumExFat(PVOID Statistics, PVOID Specific, ULONG Length, DWORD ProcCount, DWORD BytesRead)
382 {
383  DWORD i;
384  PEXFAT_STATISTICS ExFat;
386 
387  /* First, validate we won't read beyond allocation */
388  if (ValidateSizes(Length, ProcCount, BytesRead, sizeof(EXFAT_STATISTICS)))
389  {
390  return 1;
391  }
392 
393  Base = Statistics;
394  ExFat = Specific;
395 
396  /* And for every processor, sum every relevant value in first entry */
397  for (i = 1; i < ProcCount; ++i)
398  {
399  PEXFAT_STATISTICS NextExFat;
400  PFILESYSTEM_STATISTICS NextBase;
401 
402  NextBase = GET_NEXT(Base, Length, i, PFILESYSTEM_STATISTICS);
403  NextExFat = GET_NEXT(ExFat, Length, i, PEXFAT_STATISTICS);
404 
405  /* Generic first */
406  SumBase(Base, NextBase);
407  /* Specific then */
408  SUM_VALUE(ExFat, NextExFat, CreateHits);
409  SUM_VALUE(ExFat, NextExFat, SuccessfulCreates);
410  SUM_VALUE(ExFat, NextExFat, FailedCreates);
411  SUM_VALUE(ExFat, NextExFat, NonCachedReads);
412  SUM_VALUE(ExFat, NextExFat, NonCachedReadBytes);
413  SUM_VALUE(ExFat, NextExFat, NonCachedWrites);
414  SUM_VALUE(ExFat, NextExFat, NonCachedWriteBytes);
415  SUM_VALUE(ExFat, NextExFat, NonCachedDiskReads);
416  SUM_VALUE(ExFat, NextExFat, NonCachedDiskWrites);
417  }
418 
419  return 0;
420 }
421 
422 static int
423 SumFat(PVOID Statistics, PVOID Specific, ULONG Length, DWORD ProcCount, DWORD BytesRead)
424 {
425  DWORD i;
426  PFAT_STATISTICS Fat;
428 
429  /* First, validate we won't read beyond allocation */
430  if (ValidateSizes(Length, ProcCount, BytesRead, sizeof(FAT_STATISTICS)))
431  {
432  return 1;
433  }
434 
435  Base = Statistics;
436  Fat = Specific;
437 
438  /* And for every processor, sum every relevant value in first entry */
439  for (i = 1; i < ProcCount; ++i)
440  {
441  PFAT_STATISTICS NextFat;
442  PFILESYSTEM_STATISTICS NextBase;
443 
444  NextBase = GET_NEXT(Base, Length, i, PFILESYSTEM_STATISTICS);
445  NextFat = GET_NEXT(Fat, Length, i, PFAT_STATISTICS);
446 
447  /* Generic first */
448  SumBase(Base, NextBase);
449  /* Specific then */
450  SUM_VALUE(Fat, NextFat, CreateHits);
451  SUM_VALUE(Fat, NextFat, SuccessfulCreates);
452  SUM_VALUE(Fat, NextFat, FailedCreates);
453  SUM_VALUE(Fat, NextFat, NonCachedReads);
454  SUM_VALUE(Fat, NextFat, NonCachedReadBytes);
455  SUM_VALUE(Fat, NextFat, NonCachedWrites);
456  SUM_VALUE(Fat, NextFat, NonCachedWriteBytes);
457  SUM_VALUE(Fat, NextFat, NonCachedDiskReads);
458  SUM_VALUE(Fat, NextFat, NonCachedDiskWrites);
459  }
460 
461  return 0;
462 }
463 
464 static int
465 SumNtfs(PVOID Statistics, PVOID Specific, ULONG Length, DWORD ProcCount, DWORD BytesRead)
466 {
467  DWORD i;
468  PNTFS_STATISTICS Ntfs;
470 
471  /* First, validate we won't read beyond allocation */
472  if (ValidateSizes(Length, ProcCount, BytesRead, sizeof(NTFS_STATISTICS)))
473  {
474  return 1;
475  }
476 
477  Base = Statistics;
478  Ntfs = Specific;
479 
480  /* And for every processor, sum every relevant value in first entry */
481  for (i = 1; i < ProcCount; ++i)
482  {
483  PNTFS_STATISTICS NextNtfs;
484  PFILESYSTEM_STATISTICS NextBase;
485 
486  NextBase = GET_NEXT(Base, Length, i, PFILESYSTEM_STATISTICS);
487  NextNtfs = GET_NEXT(Ntfs, Length, i, PNTFS_STATISTICS);
488 
489  /* Generic first */
490  SumBase(Base, NextBase);
491  /* Specific then */
492  SUM_VALUE(Ntfs, NextNtfs, MftReads);
493  SUM_VALUE(Ntfs, NextNtfs, MftReadBytes);
494  SUM_VALUE(Ntfs, NextNtfs, MftWrites);
495  SUM_VALUE(Ntfs, NextNtfs, MftWriteBytes);
496  SUM_VALUE(Ntfs, NextNtfs, Mft2Writes);
497  SUM_VALUE(Ntfs, NextNtfs, Mft2WriteBytes);
498  SUM_VALUE(Ntfs, NextNtfs, RootIndexReads);
499  SUM_VALUE(Ntfs, NextNtfs, RootIndexReadBytes);
500  SUM_VALUE(Ntfs, NextNtfs, RootIndexWrites);
501  SUM_VALUE(Ntfs, NextNtfs, RootIndexWriteBytes);
502  SUM_VALUE(Ntfs, NextNtfs, BitmapReads);
503  SUM_VALUE(Ntfs, NextNtfs, BitmapReadBytes);
504  SUM_VALUE(Ntfs, NextNtfs, BitmapWrites);
505  SUM_VALUE(Ntfs, NextNtfs, BitmapWriteBytes);
506  SUM_VALUE(Ntfs, NextNtfs, MftBitmapReads);
507  SUM_VALUE(Ntfs, NextNtfs, MftBitmapReadBytes);
508  SUM_VALUE(Ntfs, NextNtfs, MftBitmapWrites);
509  SUM_VALUE(Ntfs, NextNtfs, MftBitmapWriteBytes);
510  SUM_VALUE(Ntfs, NextNtfs, UserIndexReads);
511  SUM_VALUE(Ntfs, NextNtfs, UserIndexReadBytes);
512  SUM_VALUE(Ntfs, NextNtfs, UserIndexWrites);
513  SUM_VALUE(Ntfs, NextNtfs, UserIndexWriteBytes);
514  SUM_VALUE(Ntfs, NextNtfs, LogFileReads);
515  SUM_VALUE(Ntfs, NextNtfs, LogFileReadBytes);
516  SUM_VALUE(Ntfs, NextNtfs, LogFileWrites);
517  SUM_VALUE(Ntfs, NextNtfs, LogFileWriteBytes);
518  }
519 
520  return 0;
521 }
522 
523 static int
525 {
526  HANDLE Volume;
527  SYSTEM_INFO SystemInfo;
529  PFILESYSTEM_STATISTICS Statistics;
530  DWORD BytesRead, Length, ProcCount;
531  /* +1 because 0 isn't assigned to a filesystem */
534 
535  /* We need a volume (letter or GUID) */
536  if (argc < 2)
537  {
538  _ftprintf(stderr, _T("Usage: fsutil fsinfo statistics <volume>\n"));
539  _ftprintf(stderr, _T("\tFor example: fsutil fsinfo statistics c:\n"));
540  return 1;
541  }
542 
543  /* Get a handle for the volume */
544  Volume = OpenVolume(argv[1], FALSE, FALSE);
545  if (Volume == INVALID_HANDLE_VALUE)
546  {
547  return 1;
548  }
549 
550  /* And query the statistics status - this call is expected to fail */
551  Statistics = &Buffer;
552  Length = sizeof(Buffer);
553  /* Assume we have a single proc for now */
554  ProcCount = 1;
555  if (DeviceIoControl(Volume, FSCTL_FILESYSTEM_GET_STATISTICS, NULL, 0, Statistics,
556  Length, &BytesRead, NULL) == FALSE)
557  {
558  DWORD Error;
559 
560  /* Check we failed because we provided a too small buffer */
561  Error = GetLastError();
562  if (Error == ERROR_MORE_DATA)
563  {
564  /* Get proc count */
565  GetSystemInfo(&SystemInfo);
566  ProcCount = SystemInfo.dwNumberOfProcessors;
567  /* Get the maximum size to allocate: it's the total size (generic + specific) for every proc */
568  Length = Statistics->SizeOfCompleteStructure * ProcCount;
569 
570  Statistics = LocalAlloc(LPTR, Length);
571  if (Statistics == NULL)
572  {
573  _ftprintf(stderr, _T("Failed to allocate memory!\n"));
574  CloseHandle(Volume);
575  return 1;
576  }
577 
578  /* Reissue the FSCTL, it's supposed to succeed now! */
579  if (DeviceIoControl(Volume, FSCTL_FILESYSTEM_GET_STATISTICS, NULL, 0, Statistics,
580  Length, &BytesRead, NULL) == FALSE)
581  {
583  LocalFree(Statistics);
584  CloseHandle(Volume);
585  return 1;
586  }
587  }
588  else
589  {
590  PrintErrorMessage(Error);
591  CloseHandle(Volume);
592  return 1;
593  }
594  }
595 
596  /* No need to deal with the volume any longer */
597  CloseHandle(Volume);
598 
599  /* We only support FAT, EXFAT and NTFS for now */
601  {
602  _ftprintf(stderr, _T("Unrecognized file system type: %d\n"), Statistics->FileSystemType);
603  if (Statistics != &Buffer)
604  {
605  LocalFree(Statistics);
606  }
607 
608  return 1;
609  }
610 
611  /* Sum all the statistics (both generic and specific) from all the processors in the first entry */
612  if (SumFct[Statistics->FileSystemType](Statistics, (PVOID)((ULONG_PTR)Statistics + sizeof(FILESYSTEM_STATISTICS)),
613  Statistics->SizeOfCompleteStructure, ProcCount, BytesRead))
614  {
615  if (Statistics != &Buffer)
616  {
617  LocalFree(Statistics);
618  }
619 
620  return 1;
621  }
622 
623  /* And finally, display the statistics (both generic and specific) */
624  DumpFct[Statistics->FileSystemType](Statistics, (PVOID)((ULONG_PTR)Statistics + sizeof(FILESYSTEM_STATISTICS)));
625 
626  /* If we allocated memory, release it */
627  if (Statistics != &Buffer)
628  {
629  LocalFree(Statistics);
630  }
631 
632  return 0;
633 }
634 
635 static void
637 {
638  PrintDefaultUsage(_T(" FSINFO "), Command, (HandlerItem *)&HandlersList,
639  (sizeof(HandlersList) / sizeof(HandlersList[0])));
640 }
641 
642 int
643 FsInfoMain(int argc, const TCHAR *argv[])
644 {
645  return FindHandler(argc, argv, (HandlerItem *)&HandlersList,
646  (sizeof(HandlersList) / sizeof(HandlersList[0])),
647  PrintUsage);
648 }
static int argc
Definition: ServiceArgs.c:12
#define TRUE
Definition: types.h:120
void SumBase(PFILESYSTEM_STATISTICS Base, PFILESYSTEM_STATISTICS NextBase)
Definition: fsinfo.c:363
#define CloseHandle
Definition: compat.h:398
#define FILE_SUPPORTS_TRANSACTIONS
Definition: from_kernel.h:248
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:47
PWCHAR FileSystem
Definition: format.c:72
Type
Definition: Type.h:6
void PrintDefaultUsage(const TCHAR *Command, const TCHAR *SubCommand, HandlerItem *HandlersList, int HandlerListCount)
Definition: common.c:102
#define FILE_SUPPORTS_OBJECT_IDS
Definition: from_kernel.h:243
#define GetDriveType
Definition: winbase.h:3626
#define DWORD
Definition: msvc.h:34
#define FILE_VOLUME_QUOTAS
Definition: from_kernel.h:238
#define GET_NEXT(stats, length, iter, type)
Definition: fsinfo.c:339
#define DUMP_VALUE(stats, value)
Definition: fsinfo.c:225
#define DRIVE_RAMDISK
Definition: winbase.h:252
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
#define FILE_VOLUME_IS_COMPRESSED
Definition: from_kernel.h:242
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static HandlerProc DrivesMain
Definition: fsinfo.c:12
#define FILE_SUPPORTS_REPARSE_POINTS
Definition: from_kernel.h:240
static int SumNtfs(PVOID Statistics, PVOID Specific, ULONG Length, DWORD ProcCount, DWORD BytesRead)
Definition: fsinfo.c:465
Definition: shell.h:41
static char ** argv
Definition: ServiceArgs.c:11
FILE * stdout
#define DRIVE_REMOVABLE
Definition: winbase.h:248
uint32_t ULONG_PTR
Definition: typedefs.h:63
int FindHandler(int argc, const TCHAR *argv[], HandlerItem *HandlersList, int HandlerListCount, void(*UsageHelper)(const TCHAR *))
Definition: common.c:11
static void DumpBase(PFILESYSTEM_STATISTICS Base, TCHAR *Name)
Definition: fsinfo.c:228
static void DumpFat(PVOID Statistics, PVOID Specific)
Definition: fsinfo.c:275
#define FILE_SUPPORTS_ENCRYPTION
Definition: from_kernel.h:244
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define DRIVE_REMOTE
Definition: winbase.h:250
#define FILESYSTEM_STATISTICS_TYPE_NTFS
Definition: winioctl.h:672
#define FILE_SEQUENTIAL_WRITE_ONCE
Definition: from_kernel.h:247
#define FILESYSTEM_STATISTICS_TYPE_EXFAT
Definition: winioctl.h:674
static HandlerProc DriveTypeMain
Definition: fsinfo.c:13
smooth NULL
Definition: ftsmooth.c:416
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
HANDLE OpenVolume(const TCHAR *Volume, BOOLEAN AllowRemote, BOOLEAN NtfsOnly)
Definition: common.c:49
#define FSCTL_GET_NTFS_VOLUME_DATA
Definition: ntifs_ex.h:261
void * PVOID
Definition: retypes.h:9
static int SumExFat(PVOID Statistics, PVOID Specific, ULONG Length, DWORD ProcCount, DWORD BytesRead)
Definition: fsinfo.c:381
#define _ftprintf
Definition: tchar.h:518
#define DRIVE_UNKNOWN
Definition: winbase.h:253
#define FSCTL_FILESYSTEM_GET_STATISTICS
Definition: nt_native.h:850
#define FILE_DAX_VOLUME
static void DumpExFat(PVOID Statistics, PVOID Specific)
Definition: fsinfo.c:251
char TCHAR
Definition: xmlstorage.h:189
#define FILE_UNICODE_ON_DISK
Definition: from_kernel.h:235
#define _T(x)
Definition: vfdio.h:22
static int SumFat(PVOID Statistics, PVOID Specific, ULONG Length, DWORD ProcCount, DWORD BytesRead)
Definition: fsinfo.c:423
#define FILE_CASE_SENSITIVE_SEARCH
Definition: from_kernel.h:233
#define MAX_PATH
Definition: compat.h:26
unsigned int UINT
Definition: ndis.h:50
static HandlerProc VolumeInfoMain
Definition: fsinfo.c:14
unsigned long DWORD
Definition: ntddk_ex.h:95
static void DumpNtfs(PVOID Statistics, PVOID Specific)
Definition: fsinfo.c:299
BOOL Error
Definition: chkdsk.c:66
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define FILE_NAMED_STREAMS
Definition: from_kernel.h:245
#define FILE_SUPPORTS_OPEN_BY_FILE_ID
Definition: from_kernel.h:251
#define HANDLE_FLAG(Flags, Flag, Desc)
struct _FILESYSTEM_STATISTICS FILESYSTEM_STATISTICS
int ValidateSizes(ULONG Length, DWORD ProcCount, DWORD BytesRead, DWORD SpecificSize)
Definition: fsinfo.c:343
#define FILE_CASE_PRESERVED_NAMES
Definition: from_kernel.h:234
#define FILE_FILE_COMPRESSION
Definition: from_kernel.h:237
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define DRIVE_NO_ROOT_DIR
Definition: winbase.h:254
#define DRIVE_FIXED
Definition: winbase.h:249
DWORD WINAPI GetLogicalDrives(VOID)
Definition: disk.c:110
int() HandlerProc(int argc, const TCHAR *argv[])
Definition: fsutil.h:8
#define GetVolumeInformation
Definition: winbase.h:3667
static VOID PrintErrorMessage(DWORD dwError)
Definition: at.c:308
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define FILE_SUPPORTS_SPARSE_FILES
Definition: from_kernel.h:239
#define FILE_SUPPORTS_HARD_LINKS
Definition: from_kernel.h:249
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
static HandlerProc NtfsInfoMain
Definition: fsinfo.c:15
#define DRIVE_CDROM
Definition: winbase.h:251
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:142
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES
Definition: from_kernel.h:250
int FsInfoMain(int argc, const TCHAR *argv[])
Definition: fsinfo.c:643
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
DWORD dwNumberOfProcessors
Definition: winbase.h:1130
unsigned int ULONG
Definition: retypes.h:1
FILE * stderr
#define LPTR
Definition: winbase.h:362
#define FILE_PERSISTENT_ACLS
Definition: from_kernel.h:236
static HandlerProc StatisticsMain
Definition: fsinfo.c:16
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1373
#define FILE_READ_ONLY_VOLUME
Definition: from_kernel.h:246
#define FILE_SUPPORTS_USN_JOURNAL
Definition: from_kernel.h:252
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
static HandlerItem HandlersList[]
Definition: fsinfo.c:17
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
static void PrintUsage(const TCHAR *Command)
Definition: fsinfo.c:636
#define SUM_VALUE(stats, new, value)
Definition: fsinfo.c:340
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29
ULONG SizeOfCompleteStructure
Definition: winioctl.h:657