Author: pschweitzer
Date: Sat Nov 1 09:56:33 2014
New Revision: 65165
URL:
http://svn.reactos.org/svn/reactos?rev=65165&view=rev
Log:
[NTFS_TEST]
Add a simple application (à la NTFSInfo & nfi) to dump the data about a NTFS volume
using the FSCTL control codes.
This is for both demonstrating how it works and to assess our driver behavior against
Windows behavior of these FSCTL.
CORE-8725
Added:
trunk/rostests/tests/ntfs/
trunk/rostests/tests/ntfs/CMakeLists.txt (with props)
trunk/rostests/tests/ntfs/ntfs.c (with props)
Added: trunk/rostests/tests/ntfs/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/tests/ntfs/CMakeLists.txt…
==============================================================================
--- trunk/rostests/tests/ntfs/CMakeLists.txt (added)
+++ trunk/rostests/tests/ntfs/CMakeLists.txt [iso-8859-1] Sat Nov 1 09:56:33 2014
@@ -0,0 +1,3 @@
+add_executable(ntfs_test ntfs.c)
+set_module_type(ntfs_test win32cui)
+add_importlibs(ntfs_test msvcrt kernel32)
Propchange: trunk/rostests/tests/ntfs/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/tests/ntfs/ntfs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/tests/ntfs/ntfs.c?rev=651…
==============================================================================
--- trunk/rostests/tests/ntfs/ntfs.c (added)
+++ trunk/rostests/tests/ntfs/ntfs.c [iso-8859-1] Sat Nov 1 09:56:33 2014
@@ -0,0 +1,242 @@
+/*
+ * PROJECT: ReactOS NTFS tests/dump
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Query information from NTFS volume using FSCTL and dumps $MFT
+ * PROGRAMMER: Pierre Schweitzer <pierre(a)reactos.org>
+ */
+
+#include <windows.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
+
+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 enum
+{
+ AttributeStandardInformation = 0x10,
+ AttributeAttributeList = 0x20,
+ AttributeFileName = 0x30,
+ AttributeObjectId = 0x40,
+ AttributeSecurityDescriptor = 0x50,
+ AttributeVolumeName = 0x60,
+ AttributeVolumeInformation = 0x70,
+ AttributeData = 0x80,
+ AttributeIndexRoot = 0x90,
+ AttributeIndexAllocation = 0xA0,
+ AttributeBitmap = 0xB0,
+ AttributeReparsePoint = 0xC0,
+ AttributeEAInformation = 0xD0,
+ AttributeEA = 0xE0,
+ AttributePropertySet = 0xF0,
+ AttributeLoggedUtilityStream = 0x100,
+ AttributeEnd = 0xFFFFFFFF
+} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;
+
+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;
+
+typedef struct
+{
+ ULONGLONG CreationTime;
+ ULONGLONG ChangeTime;
+ ULONGLONG LastWriteTime;
+ ULONGLONG LastAccessTime;
+ ULONG FileAttribute;
+ ULONG AlignmentOrReserved[3];
+} STANDARD_INFORMATION, *PSTANDARD_INFORMATION;
+
+typedef struct
+{
+ ULONGLONG DirectoryFileReferenceNumber;
+ ULONGLONG CreationTime;
+ ULONGLONG ChangeTime;
+ ULONGLONG LastWriteTime;
+ ULONGLONG LastAccessTime;
+ ULONGLONG AllocatedSize;
+ ULONGLONG DataSize;
+ ULONG FileAttributes;
+ ULONG AlignmentOrReserved;
+ UCHAR NameLength;
+ UCHAR NameType;
+ WCHAR Name[1];
+} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;
+
+int main(int argc, char **argv)
+{
+ static WCHAR VolumeName[] = L"\\\\.\\E:";
+ HANDLE VolumeHandle;
+ struct {
+ NTFS_VOLUME_DATA_BUFFER Data;
+ NTFS_EXTENDED_VOLUME_DATA Extended;
+ } VolumeInfo;
+ DWORD LengthReturned;
+ NTFS_FILE_RECORD_INPUT_BUFFER InputBuffer;
+ PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer;
+ DWORD OutputLength;
+ PFILE_RECORD_HEADER FileRecord;
+ PNTFS_ATTR_RECORD Attribute;
+ DWORD k;
+
+ VolumeHandle = CreateFileW(VolumeName, GENERIC_READ, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+ if (VolumeHandle == INVALID_HANDLE_VALUE)
+ {
+ fprintf(stderr, "Failed opening volume!\n");
+ return -1;
+ }
+
+ if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0,
&VolumeInfo, sizeof(VolumeInfo), &LengthReturned, NULL))
+ {
+ fprintf(stderr, "Failed requesting volume data!\n");
+ CloseHandle(VolumeHandle);
+ return -1;
+ }
+
+ printf("Using NTFS: %u.%u\n", VolumeInfo.Extended.MajorVersion,
VolumeInfo.Extended.MinorVersion);
+
+ InputBuffer.FileReferenceNumber.QuadPart = 0LL;
+ OutputLength = sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER) +
VolumeInfo.Data.BytesPerFileRecordSegment;
+ OutputBuffer = malloc(OutputLength);
+ if (OutputBuffer == NULL)
+ {
+ fprintf(stderr, "Allocation failure!\n");
+ CloseHandle(VolumeHandle);
+ }
+
+ if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_FILE_RECORD, &InputBuffer,
sizeof(InputBuffer), OutputBuffer, OutputLength, &LengthReturned, NULL))
+ {
+ fprintf(stderr, "Failed opening $MFT!\n");
+ free(OutputBuffer);
+ CloseHandle(VolumeHandle);
+ return -1;
+ }
+
+ if (OutputBuffer->FileReferenceNumber.QuadPart != 0LL)
+ {
+ fprintf(stderr, "Wrong entry read! %I64x\n",
OutputBuffer->FileReferenceNumber.QuadPart);
+ free(OutputBuffer);
+ CloseHandle(VolumeHandle);
+ return -1;
+ }
+
+ FileRecord = (PFILE_RECORD_HEADER)OutputBuffer->FileRecordBuffer;
+ if (FileRecord->Ntfs.Type != NRH_FILE_TYPE)
+ {
+ fprintf(stderr, "Wrong type read! %lx\n", FileRecord->Ntfs.Type);
+ free(OutputBuffer);
+ CloseHandle(VolumeHandle);
+ return -1;
+ }
+
+ printf("File record size: %lu. Read file record size: %lu\n",
VolumeInfo.Data.BytesPerFileRecordSegment, OutputBuffer->FileRecordLength);
+ printf("SequenceNumber: %u\n", FileRecord->SequenceNumber);
+ printf("LinkCount: %u\n", FileRecord->LinkCount);
+ printf("AttributeOffset: %u\n", FileRecord->AttributeOffset);
+ printf("Flags: %u\n", FileRecord->Flags);
+ printf("BytesInUse: %lu\n", FileRecord->BytesInUse);
+ printf("BytesAllocated: %lu\n", FileRecord->BytesAllocated);
+ printf("BaseFileRecord: %I64x\n", FileRecord->BaseFileRecord);
+ printf("NextAttributeNumber: %u\n", FileRecord->NextAttributeNumber);
+
+ Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord +
FileRecord->AttributeOffset);
+ while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord +
FileRecord->BytesInUse) &&
+ Attribute->Type != AttributeEnd)
+ {
+ PSTANDARD_INFORMATION StdInfo;
+ PFILENAME_ATTRIBUTE FileName;
+
+ if (!Attribute->IsNonResident)
+ {
+ switch (Attribute->Type)
+ {
+ case AttributeStandardInformation:
+ StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute +
Attribute->Resident.ValueOffset);
+ printf("\t$STANDARD_INFORMATION:\n");
+ printf("\tCreationTime: %I64u\n",
StdInfo->CreationTime);
+ printf("\tChangeTime: %I64u\n", StdInfo->ChangeTime);
+ printf("\tLastWriteTime: %I64u\n",
StdInfo->LastWriteTime);
+ printf("\tLastAccessTime: %I64u\n",
StdInfo->LastAccessTime);
+ printf("\tFileAttribute: %lu\n",
StdInfo->FileAttribute);
+ break;
+
+ case AttributeFileName:
+ FileName = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute +
Attribute->Resident.ValueOffset);
+ printf("\t$FILE_NAME:\n");
+ printf("\tDirectoryFileReferenceNumber: %I64u\n",
FileName->DirectoryFileReferenceNumber);
+ printf("\tCreationTime: %I64u\n",
FileName->CreationTime);
+ printf("\tChangeTime: %I64u\n", FileName->ChangeTime);
+ printf("\tLastWriteTime: %I64u\n",
FileName->LastWriteTime);
+ printf("\tLastAccessTime: %I64u\n",
FileName->LastAccessTime);
+ printf("\tAllocatedSize: %I64u\n",
FileName->AllocatedSize);
+ printf("\tDataSize: %I64u\n", FileName->DataSize);
+ printf("\tFileAttributes: %lu\n",
FileName->FileAttributes);
+ printf("\tAlignmentOrReserved: %lu\n",
FileName->AlignmentOrReserved);
+ printf("\tNameLength: %u\n", FileName->NameLength);
+ printf("\tNameType: %u\n", FileName->NameType);
+ printf("\tName: ");
+ for (k = 0; k < FileName->NameLength; ++k)
+ {
+ wprintf(L"%C", FileName->Name[k]);
+ }
+ printf("\n");
+ break;
+ }
+ }
+
+ Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
+ }
+
+ free(OutputBuffer);
+ CloseHandle(VolumeHandle);
+
+ return 0;
+}
Propchange: trunk/rostests/tests/ntfs/ntfs.c
------------------------------------------------------------------------------
svn:eol-style = native