From 3886e2f66b059678486c1e6dfd9b155f5da87cc7 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Mon, 15 Jul 2002 15:37:33 +0000 Subject: [PATCH] Dump the first MFT cluster and some file attributes. svn path=/trunk/; revision=3230 --- reactos/drivers/fs/ntfs/attrib.c | 217 +++++++++++++++++++++++++++++++ reactos/drivers/fs/ntfs/fsctl.c | 13 +- reactos/drivers/fs/ntfs/makefile | 6 +- reactos/drivers/fs/ntfs/mft.c | 100 ++++++++++++++ reactos/drivers/fs/ntfs/ntfs.h | 149 ++++++++++++++++++++- 5 files changed, 470 insertions(+), 15 deletions(-) create mode 100644 reactos/drivers/fs/ntfs/attrib.c create mode 100644 reactos/drivers/fs/ntfs/mft.c diff --git a/reactos/drivers/fs/ntfs/attrib.c b/reactos/drivers/fs/ntfs/attrib.c new file mode 100644 index 00000000000..22ce811825f --- /dev/null +++ b/reactos/drivers/fs/ntfs/attrib.c @@ -0,0 +1,217 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: attrib.c,v 1.1 2002/07/15 15:37:33 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/attrib.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +VOID +NtfsDumpAttribute(PATTRIBUTE Attribute) +{ + PNONRESIDENT_ATTRIBUTE NresAttr; + PRESIDENT_ATTRIBUTE ResAttr; + UNICODE_STRING Name; + PUCHAR Ptr; + UCHAR RunHeader; + ULONG RunLength; + ULONG RunStart; + + switch (Attribute->AttributeType) + { + case AttributeStandardInformation: + DbgPrint(" $STANDARD_INFORMATION "); + break; + + case AttributeAttributeList: + DbgPrint(" $ATTRIBUTE_LIST "); + break; + + case AttributeFileName: + DbgPrint(" $FILE_NAME "); + break; + + case AttributeObjectId: + DbgPrint(" $OBJECT_ID "); + break; + + case AttributeSecurityDescriptor: + DbgPrint(" $SECURITY_DESCRIPTOR "); + break; + + case AttributeVolumeName: + DbgPrint(" $VOLUME_NAME "); + break; + + case AttributeVolumeInformation: + DbgPrint(" $VOLUME_INFORMATION "); + break; + + case AttributeData: + DbgPrint(" $DATA "); + break; + + case AttributeIndexRoot: + DbgPrint(" $INDEX_ROOT "); + break; + + case AttributeIndexAllocation: + DbgPrint(" $INDEX_ALLOCATION "); + break; + + case AttributeBitmap: + DbgPrint(" $BITMAP "); + break; + + case AttributeReparsePoint: + DbgPrint(" $REPARSE_POINT "); + break; + + case AttributeEAInformation: + DbgPrint(" $EA_INFORMATION "); + break; + + case AttributeEA: + DbgPrint(" $EA "); + break; + + case AttributePropertySet: + DbgPrint(" $PROPERTY_SET "); + break; + + case AttributeLoggedUtilityStream: + DbgPrint(" $LOGGED_UTILITY_STREAM "); + break; + + default: + DbgPrint(" Attribute %lx ", + Attribute->AttributeType); + break; + } + + if (Attribute->NameLength != 0) + { + Name.Length = Attribute->NameLength * sizeof(WCHAR); + Name.MaximumLength = Name.Length; + Name.Buffer = (PWCHAR)((ULONG)Attribute + Attribute->NameOffset); + + DbgPrint("'%wZ' ", &Name); + } + + DbgPrint("(%s)\n", + Attribute->Nonresident ? "nonresident" : "resident"); + + if (Attribute->Nonresident != 0) + { + NresAttr = (PNONRESIDENT_ATTRIBUTE)Attribute; + Ptr = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset); + while (*Ptr != 0) + { + RunHeader = *Ptr++; + + switch (RunHeader & 0x0F) + { + case 1: + RunLength = (ULONG)*Ptr++; + break; + + case 2: + RunLength = *((PUSHORT)Ptr); + Ptr += 2; + break; + + case 3: + RunLength = *Ptr++; + RunLength += *Ptr++ << 8; + RunLength += *Ptr++ << 16; + break; + + case 4: + RunLength = *((PULONG)Ptr); + Ptr += 4; + break; + + default: + DbgPrint("RunLength size of %hu not implemented!\n", RunHeader & 0x0F); + KeBugCheck(0); + } + + switch (RunHeader >> 4) + { + case 1: + RunStart = (ULONG)*Ptr; + Ptr++; + break; + + case 2: + RunStart = *((PUSHORT)Ptr); + Ptr += 2; + break; + + case 3: + RunStart = *Ptr++; + RunStart += *Ptr++ << 8; + RunStart += *Ptr++ << 16; + break; + + case 4: + RunStart = *((PULONG)Ptr); + Ptr += 4; + break; + + default: + DbgPrint("RunStart size of %hu not implemented!\n", RunHeader >> 4); + KeBugCheck(0); + } + + DbgPrint(" AllocatedSize %I64d DataSize %I64d\n", NresAttr->AllocatedSize, NresAttr->DataSize); +// DbgPrint(" Run: Header %hx Start %lu Length %lu\n", RunHeader, RunStart, RunLength); + if (RunLength == 1) + { + DbgPrint(" logical sector %lu (0x%lx)\n", RunStart, RunStart); + } + else + { + DbgPrint(" logical sectors %lu-%lu (0x%lx-0x%lx)\n", + RunStart, RunStart + RunLength - 1, + RunStart, RunStart + RunLength - 1); + } + } + } + + +} + + +/* EOF */ diff --git a/reactos/drivers/fs/ntfs/fsctl.c b/reactos/drivers/fs/ntfs/fsctl.c index 2f4d63c434f..dc6741ab3b8 100644 --- a/reactos/drivers/fs/ntfs/fsctl.c +++ b/reactos/drivers/fs/ntfs/fsctl.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: fsctl.c,v 1.1 2002/06/25 22:23:06 ekohl Exp $ +/* $Id: fsctl.c,v 1.2 2002/07/15 15:37:33 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -119,7 +119,7 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION Vcb) { DISK_GEOMETRY DiskGeometry; - PUCHAR Buffer; +// PUCHAR Buffer; ULONG Size; NTSTATUS Status; PBOOT_SECTOR BootSector; @@ -160,8 +160,8 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, Vcb->NtfsInfo.BytesPerCluster = BootSector->BytesPerSector * BootSector->SectorsPerCluster; Vcb->NtfsInfo.SectorCount = BootSector->SectorCount; - Vcb->NtfsInfo.MftStart = BootSector->MftLocation; - Vcb->NtfsInfo.MftMirrStart = BootSector->MftMirrLocation; + Vcb->NtfsInfo.MftStart.QuadPart = BootSector->MftLocation; + Vcb->NtfsInfo.MftMirrStart.QuadPart = BootSector->MftMirrLocation; Vcb->NtfsInfo.SerialNumber = BootSector->SerialNumber; //#indef NDEBUG @@ -179,9 +179,12 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, DbgPrint(" SerialNumber: %I64x\n", BootSector->SerialNumber); //#endif + + NtfsOpenMft(DeviceObject, Vcb); + } - ExFreePool(Buffer); + ExFreePool(BootSector); return(Status); } diff --git a/reactos/drivers/fs/ntfs/makefile b/reactos/drivers/fs/ntfs/makefile index 70bf698e4fb..be25fa08590 100644 --- a/reactos/drivers/fs/ntfs/makefile +++ b/reactos/drivers/fs/ntfs/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.1 2002/06/25 22:23:06 ekohl Exp $ +# $Id: makefile,v 1.2 2002/07/15 15:37:33 ekohl Exp $ PATH_TO_TOP = ../../.. @@ -6,8 +6,8 @@ TARGET_TYPE = driver TARGET_NAME = ntfs -TARGET_OBJECTS = $(TARGET_NAME).o blockdev.o create.o dirctl.o fcb.o finfo.o \ - fsctl.o volinfo.o +TARGET_OBJECTS = $(TARGET_NAME).o attrib.o blockdev.o create.o dirctl.o \ + fcb.o finfo.o fsctl.o mft.o volinfo.o include $(PATH_TO_TOP)/rules.mak diff --git a/reactos/drivers/fs/ntfs/mft.c b/reactos/drivers/fs/ntfs/mft.c new file mode 100644 index 00000000000..f0d62476e95 --- /dev/null +++ b/reactos/drivers/fs/ntfs/mft.c @@ -0,0 +1,100 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: mft.c,v 1.1 2002/07/15 15:37:33 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/mft.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + + +NTSTATUS +NtfsOpenMft(PDEVICE_OBJECT DeviceObject, + PDEVICE_EXTENSION Vcb) +{ + PVOID Buffer; + PFILE_RECORD_HEADER RecordHeader; + PATTRIBUTE Attribute; + NTSTATUS Status; + + DPRINT1("NtfsOpenMft() called\n"); + + Buffer = ExAllocatePool(NonPagedPool, + Vcb->NtfsInfo.BytesPerCluster); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + + /* read first MFT cluster */ + Status = NtfsReadRawSectors(DeviceObject, + Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster, + Vcb->NtfsInfo.SectorsPerCluster, + Vcb->NtfsInfo.BytesPerSector, + (PVOID)Buffer); + if (NT_SUCCESS(Status)) + { + /* Enumerate MFT records */ + RecordHeader = Buffer; + while (((ULONG)RecordHeader - (ULONG)Buffer) < Vcb->NtfsInfo.BytesPerCluster) + { + DbgPrint("\n"); +// DbgPrint("Magic: %.04s\n", (PCHAR)&RecordHeader->Ntfs.Type); +// DbgPrint("Real size: %lx\n", RecordHeader->RealSize); +// DbgPrint("AllocSize: %lx\n", RecordHeader->AllocSize); + + /* Enumerate attributes */ + Attribute = (PATTRIBUTE)((ULONG)RecordHeader + + RecordHeader->Ntfs.UsnOffset + + RecordHeader->Ntfs.UsnSize * sizeof(USHORT)); + while (Attribute->AttributeType != 0xFFFFFFFF) + { + NtfsDumpAttribute(Attribute); + + Attribute = (PATTRIBUTE)((ULONG)Attribute + Attribute->Length); + } + + + RecordHeader = (PFILE_RECORD_HEADER)((ULONG)RecordHeader + RecordHeader->BytesAllocated); + } + + } + + ExFreePool(Buffer); + + return(Status); +} + + +/* EOF */ diff --git a/reactos/drivers/fs/ntfs/ntfs.h b/reactos/drivers/fs/ntfs/ntfs.h index 8665c72f977..3ea321d38ed 100644 --- a/reactos/drivers/fs/ntfs/ntfs.h +++ b/reactos/drivers/fs/ntfs/ntfs.h @@ -47,8 +47,8 @@ typedef struct _NTFS_INFO ULONG SectorsPerCluster; ULONG BytesPerCluster; ULONGLONG SectorCount; - ULONGLONG MftStart; - ULONGLONG MftMirrStart; + ULARGE_INTEGER MftStart; + ULARGE_INTEGER MftMirrStart; ULONGLONG SerialNumber; } NTFS_INFO, *PNTFS_INFO; @@ -122,8 +122,6 @@ typedef struct _CCB #define TAG_CCB TAG('I', 'C', 'C', 'B') - - typedef struct { PDRIVER_OBJECT DriverObject; @@ -131,15 +129,145 @@ typedef struct ULONG Flags; } NTFS_GLOBAL_DATA, *PNTFS_GLOBAL_DATA; + +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 +} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; + + +typedef struct +{ + ULONG Type; + USHORT UsnOffset; + USHORT UsnSize; + ULONGLONG Usn; +} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER; + +typedef struct +{ + 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 +{ + ATTRIBUTE_TYPE AttributeType; + ULONG Length; + BOOLEAN Nonresident; + UCHAR NameLength; + USHORT NameOffset; + USHORT Flags; + USHORT AttributeNumber; +} ATTRIBUTE, *PATTRIBUTE; + +typedef struct +{ + ATTRIBUTE Attribute; + ULONG ValueLength; + USHORT ValueOffset; + UCHAR Flags; +// UCHAR Padding0; +} RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE; + +typedef struct +{ + ATTRIBUTE Attribute; + ULONGLONG StartVcn; // LowVcn + ULONGLONG LastVcn; // HighVcn + USHORT RunArrayOffset; + USHORT CompressionUnit; + ULONG Padding0; + UCHAR IndexedFlag; + ULONGLONG AllocatedSize; + ULONGLONG DataSize; + ULONGLONG InitializedSize; + ULONGLONG CompressedSize; +} NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE; + + +typedef struct +{ + ULONGLONG CreationTime; + ULONGLONG ChangeTime; + ULONGLONG LastWriteTime; + ULONGLONG LastAccessTime; + ULONG FileAttribute; + ULONG AlignmentOrReserved[3]; +#if 0 + ULONG QuotaId; + ULONG SecurityId; + ULONGLONG QuotaCharge; + USN Usn; +#endif +} STANDARD_INFORMATION, *PSTANDARD_INFORMATION; + + +typedef struct +{ + ATTRIBUTE_TYPE AttributeType; + USHORT Length; + UCHAR NameLength; + UCHAR NameOffset; + ULONGLONG StartVcn; // LowVcn + ULONGLONG FileReferenceNumber; + USHORT AttributeNumber; + USHORT AlignmentOrReserved[3]; +} ATTRIBUTE_LIST, *PATTRIBUTE_LIST; + + +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; + + + extern PNTFS_GLOBAL_DATA NtfsGlobalData; - - - //int CdfsStrcmpi( wchar_t *str1, wchar_t *str2 ); //void CdfsWstrcpy( wchar_t *str1, wchar_t *str2, int max ); +/* attrib.c */ + +VOID +NtfsDumpAttribute(PATTRIBUTE Attribute); + + /* blockdev.c */ NTSTATUS @@ -251,6 +379,13 @@ NTSTATUS STDCALL NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +/* mft.c */ +NTSTATUS +NtfsOpenMft(PDEVICE_OBJECT DeviceObject, + PDEVICE_EXTENSION Vcb); + + #if 0 /* misc.c */