mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 18:11:57 +00:00
[NTFSINFO]
Time to free some Sysinternals tool: ntfsinfo. To make it short, this tool dumps various information about a NTFS volume and its reserved meta-data files Our version comes with three advantages compared to the Russinovich's tool: - It's FLOSS - It works properly on NT5+ (developed with W2K3 & W7) whereas R's cannot display meta-data files information - It will open a volume by default if none provided One issue so far: it doesn't work properly on ReactOS! CORE-8725 svn path=/trunk/; revision=68326
This commit is contained in:
parent
5b284d6338
commit
1c3c66afa4
4 changed files with 222 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
|||
add_subdirectory(appwiz)
|
||||
add_subdirectory(cat)
|
||||
add_subdirectory(ntfsinfo)
|
||||
add_subdirectory(tee)
|
||||
add_subdirectory(touch)
|
||||
add_subdirectory(uptime)
|
||||
|
|
5
rosapps/applications/cmdutils/ntfsinfo/CMakeLists.txt
Normal file
5
rosapps/applications/cmdutils/ntfsinfo/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
list(APPEND SOURCE ntfsinfo.c ntfsinfo.rc)
|
||||
add_executable(ntfsinfo ${SOURCE})
|
||||
set_module_type(ntfsinfo win32cui UNICODE)
|
||||
add_importlibs(ntfsinfo msvcrt kernel32 ntdll)
|
||||
add_cd_file(TARGET ntfsinfo DESTINATION reactos/system32 FOR all)
|
212
rosapps/applications/cmdutils/ntfsinfo/ntfsinfo.c
Normal file
212
rosapps/applications/cmdutils/ntfsinfo/ntfsinfo.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
4
rosapps/applications/cmdutils/ntfsinfo/ntfsinfo.rc
Normal file
4
rosapps/applications/cmdutils/ntfsinfo/ntfsinfo.rc
Normal file
|
@ -0,0 +1,4 @@
|
|||
#define REACTOS_STR_FILE_DESCRIPTION "NTFS Information\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "ntfsinfo\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "ntfsinfo.exe\0"
|
||||
#include <reactos/version.rc>
|
Loading…
Add table
Add a link
Reference in a new issue