+++ /dev/null
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS NTFS Information tool
- * FILE: cmdutils/ntfsinfo/ntfsinfo.c
- * PURPOSE: Query information from NTFS volume using FSCTL
- * PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
- */
-
-#include <windows.h>
-#include <tchar.h>
-#include <stdio.h>
-
-typedef struct
-{
- ULONG Type;
- USHORT UsaOffset;
- USHORT UsaCount;
- ULONGLONG Lsn;
-} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;
-
-#define NRH_FILE_TYPE 0x454C4946
-#define ATTRIBUTE_TYPE_DATA 0x80
-#define ATTRIBUTE_TYPE_END 0xFFFFFFFF
-
-typedef struct _FILE_RECORD_HEADER
-{
- NTFS_RECORD_HEADER Ntfs;
- USHORT SequenceNumber;
- USHORT LinkCount;
- USHORT AttributeOffset;
- USHORT Flags;
- ULONG BytesInUse;
- ULONG BytesAllocated;
- ULONGLONG BaseFileRecord;
- USHORT NextAttributeNumber;
-} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
-
-typedef struct
-{
- ULONG Type;
- ULONG Length;
- UCHAR IsNonResident;
- UCHAR NameLength;
- USHORT NameOffset;
- USHORT Flags;
- USHORT Instance;
- union
- {
- struct
- {
- ULONG ValueLength;
- USHORT ValueOffset;
- UCHAR Flags;
- UCHAR Reserved;
- } Resident;
- struct
- {
- ULONGLONG LowestVCN;
- ULONGLONG HighestVCN;
- USHORT MappingPairsOffset;
- USHORT CompressionUnit;
- UCHAR Reserved[4];
- LONGLONG AllocatedSize;
- LONGLONG DataSize;
- LONGLONG InitializedSize;
- LONGLONG CompressedSize;
- } NonResident;
- };
-} NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD;
-
-static TCHAR * MetaDataFiles[] = {
- _T("$MFT\t\t"),
- _T("$MFTMirr\t"),
- _T("$LogFile\t"),
- _T("$Volume\t\t"),
- _T("$AttrDef\t"),
- _T("."),
- _T("$Bitmap\t\t"),
- _T("$Boot\t\t"),
- _T("$BadClus\t"),
- _T("$Quota\t\t"),
- _T("$UpCase\t\t"),
- _T("$Extended\t"),
- NULL,
-};
-
-int
-__cdecl
-_tmain(int argc, const TCHAR *argv[])
-{
- TCHAR VolumeName[] = _T("\\\\.\\C:");
- HANDLE VolumeHandle;
- NTFS_VOLUME_DATA_BUFFER VolumeInfo;
- DWORD LengthReturned;
- ULONGLONG VolumeSize;
- ULONGLONG MftClusters;
- UINT File = 0;
- PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer;
-
- if (argc > 1)
- {
- TCHAR Letter = argv[1][0];
-
- if ((Letter >= 'A' && Letter <= 'Z') ||
- (Letter >= 'a' && Letter <= 'z'))
- {
- VolumeName[4] = Letter;
- }
- }
-
- VolumeHandle = CreateFile(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
- if (VolumeHandle == INVALID_HANDLE_VALUE)
- {
- _ftprintf(stderr, _T("Failed opening the volume '%s' (%lx)\n"), VolumeName, GetLastError());
- return 1;
- }
-
- if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &VolumeInfo, sizeof(VolumeInfo), &LengthReturned, NULL))
- {
- _ftprintf(stderr, _T("Failed requesting volume '%s' data (%lx)\n"), VolumeName, GetLastError());
- CloseHandle(VolumeHandle);
- return 1;
- }
-
- if (LengthReturned < sizeof(VolumeInfo))
- {
- _ftprintf(stderr, _T("Failed reading volume '%s' data (%lx)\n"), VolumeName, GetLastError());
- CloseHandle(VolumeHandle);
- return 1;
- }
-
- _tprintf(_T("Volume Size\n-----------\n"));
- VolumeSize = VolumeInfo.TotalClusters.QuadPart * VolumeInfo.BytesPerCluster;
- _tprintf(_T("Volume size\t\t: %I64u MB\n"), VolumeSize >> 20);
- _tprintf(_T("Total sectors\t\t: %I64u\n"), VolumeInfo.NumberSectors.QuadPart);
- _tprintf(_T("Total clusters\t\t: %I64u\n"), VolumeInfo.TotalClusters.QuadPart);
- _tprintf(_T("Free clusters\t\t: %I64u\n"), VolumeInfo.FreeClusters.QuadPart);
- _tprintf(_T("Free space\t\t: %I64u MB (%u%% of drive)\n"), (VolumeInfo.FreeClusters.QuadPart * VolumeInfo.BytesPerCluster) >> 20, (VolumeInfo.FreeClusters.QuadPart * 100) / VolumeInfo.TotalClusters.QuadPart);
-
- _tprintf(_T("\nAllocation Size\n---------------\n"));
- _tprintf(_T("Bytes per sector\t: %lu\n"), VolumeInfo.BytesPerSector);
- _tprintf(_T("Bytes per cluster\t: %lu\n"), VolumeInfo.BytesPerCluster);
- _tprintf(_T("Bytes per MFT record:\t: %lu\n"), VolumeInfo.BytesPerFileRecordSegment);
- _tprintf(_T("Clusters per MFT record\t: %lu\n"), VolumeInfo.ClustersPerFileRecordSegment);
-
- _tprintf(_T("\nMFT Information\n---------------\n"));
- _tprintf(_T("MFT size\t\t: %I64u MB (%u%% of drive)\n"), VolumeInfo.MftValidDataLength.QuadPart >> 20, (VolumeInfo.MftValidDataLength.QuadPart * 100) / VolumeSize);
- _tprintf(_T("MFT start cluster\t: %I64u\n"), VolumeInfo.MftStartLcn.QuadPart);
- _tprintf(_T("MFT zone clusters\t: %I64u - %I64u\n"), VolumeInfo.MftZoneStart.QuadPart, VolumeInfo.MftZoneEnd.QuadPart);
- MftClusters = VolumeInfo.MftZoneEnd.QuadPart - VolumeInfo.MftZoneStart.QuadPart;
- _tprintf(_T("MFT zone size\t\t: %I64u MB (%u%% of drive)\n"), (MftClusters * VolumeInfo.BytesPerCluster) >> 20, (MftClusters * 100) / VolumeInfo.TotalClusters.QuadPart);
- _tprintf(_T("MFT mirror start\t: %I64u\n"), VolumeInfo.Mft2StartLcn.QuadPart);
-
- _tprintf(_T("\nMeta-Data files\n---------------\n"));
- OutputBuffer = HeapAlloc(GetProcessHeap(), 0, VolumeInfo.BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER));
- while (MetaDataFiles[File] != NULL)
- {
- NTFS_FILE_RECORD_INPUT_BUFFER InputBuffer;
- PFILE_RECORD_HEADER FileRecord;
- PNTFS_ATTR_RECORD Attribute;
- ULONGLONG Size = 0;
-
- if (File == 5)
- {
- ++File;
- continue;
- }
-
- InputBuffer.FileReferenceNumber.QuadPart = File;
- if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_FILE_RECORD, &InputBuffer, sizeof(InputBuffer),
- OutputBuffer, VolumeInfo.BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER),
- &LengthReturned, NULL))
- {
- ++File;
- continue;
- }
-
- if (OutputBuffer->FileReferenceNumber.QuadPart != File)
- {
- ++File;
- continue;
- }
-
- FileRecord = (PFILE_RECORD_HEADER)OutputBuffer->FileRecordBuffer;
- if (FileRecord->Ntfs.Type != NRH_FILE_TYPE)
- {
- ++File;
- continue;
- }
-
- Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
- while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
- Attribute->Type != ATTRIBUTE_TYPE_END)
- {
- if (Attribute->Type == ATTRIBUTE_TYPE_DATA)
- {
- Size = (Attribute->IsNonResident) ? Attribute->NonResident.AllocatedSize : Attribute->Resident.ValueLength;
- break;
- }
-
- Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
- }
-
- _tprintf(_T("%s%I64u bytes\n"), MetaDataFiles[File], Size);
-
- ++File;
- }
-
- HeapFree(GetProcessHeap(), 0, OutputBuffer);
- CloseHandle(VolumeHandle);
- return 0;
-}