diff --git a/reactos/drivers/fs/ntfs/attrib.c b/reactos/drivers/fs/ntfs/attrib.c index 8b015e5d7da..efff474cc36 100644 --- a/reactos/drivers/fs/ntfs/attrib.c +++ b/reactos/drivers/fs/ntfs/attrib.c @@ -16,13 +16,14 @@ * 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.5 2003/08/07 11:47:32 silverblade Exp $ +/* $Id: attrib.c,v 1.6 2003/09/15 16:01:16 ea Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/fs/ntfs/attrib.c * PURPOSE: NTFS filesystem driver * PROGRAMMER: Eric Kohl + * Updated by Valentin Verkhovsky 2003/09/12 */ /* INCLUDES *****************************************************************/ @@ -39,13 +40,47 @@ /* FUNCTIONS ****************************************************************/ + + +ULONG RunLength(PUCHAR run) +{ + return(*run & 0x0f) + ((*run >> 4) & 0x0f) + 1; +} + + +LONGLONG RunLCN(PUCHAR run) +{ + UCHAR n1 = *run & 0x0f; + UCHAR n2 = (*run >> 4) & 0x0f; + LONGLONG lcn = n2 == 0 ? 0 : (CHAR)(run[n1 + n2]); + LONG i = 0; + + for (i = n1 +n2 - 1; i > n1; i--) + lcn = (lcn << 8) + run[i]; + return lcn; +} + + + +ULONGLONG RunCount(PUCHAR run) +{ + UCHAR n = *run & 0xf; + ULONGLONG count = 0; + ULONG i = 0; + + for (i = n; i > 0; i--) + count = (count << 8) + run[i]; + return count; +} + + VOID NtfsDumpFileNameAttribute(PATTRIBUTE Attribute) { PRESIDENT_ATTRIBUTE ResAttr; PFILENAME_ATTRIBUTE FileNameAttr; - DbgPrint(" $FILE_NAME "); + DbgPrint(" FILE_NAME "); ResAttr = (PRESIDENT_ATTRIBUTE)Attribute; // DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset); @@ -90,7 +125,7 @@ NtfsDumpVolumeInformationAttribute(PATTRIBUTE Attribute) } -VOID +BOOL NtfsDumpAttribute(PATTRIBUTE Attribute) { PNONRESIDENT_ATTRIBUTE NresAttr; @@ -100,9 +135,16 @@ NtfsDumpAttribute(PATTRIBUTE Attribute) UCHAR RunHeader; ULONG RunLength; ULONG RunStart; + switch (Attribute->AttributeType) { + + case AttributeFileName: + NtfsDumpFileNameAttribute(Attribute); + break; + + case AttributeStandardInformation: DbgPrint(" $STANDARD_INFORMATION "); break; @@ -111,9 +153,7 @@ NtfsDumpAttribute(PATTRIBUTE Attribute) DbgPrint(" $ATTRIBUTE_LIST "); break; - case AttributeFileName: - NtfsDumpFileNameAttribute(Attribute); - break; + case AttributeObjectId: DbgPrint(" $OBJECT_ID "); @@ -133,6 +173,7 @@ NtfsDumpAttribute(PATTRIBUTE Attribute) case AttributeData: DbgPrint(" $DATA "); + //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute)); break; case AttributeIndexRoot: @@ -184,85 +225,23 @@ NtfsDumpAttribute(PATTRIBUTE Attribute) DbgPrint("(%s)\n", Attribute->Nonresident ? "non-resident" : "resident"); + + - if (Attribute->Nonresident != 0) + + 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); - } + return TRUE; } - } + return FALSE; + + + + + + } diff --git a/reactos/drivers/fs/ntfs/fsctl.c b/reactos/drivers/fs/ntfs/fsctl.c index b471989c5f9..036bb8bb5a4 100644 --- a/reactos/drivers/fs/ntfs/fsctl.c +++ b/reactos/drivers/fs/ntfs/fsctl.c @@ -16,20 +16,21 @@ * 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.7 2003/07/17 13:31:39 chorns Exp $ +/* $Id: fsctl.c,v 1.8 2003/09/15 16:01:16 ea Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: services/fs/ntfs/fsctl.c * PURPOSE: NTFS filesystem driver * PROGRAMMER: Eric Kohl + * Updated by Valentin Verkhovsky 2003/09/12 */ /* INCLUDES *****************************************************************/ #include -//#define NDEBUG +#define NDEBUG #include #include "ntfs.h" @@ -163,6 +164,7 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, Vcb->NtfsInfo.MftStart.QuadPart = BootSector->MftLocation; Vcb->NtfsInfo.MftMirrStart.QuadPart = BootSector->MftMirrLocation; Vcb->NtfsInfo.SerialNumber = BootSector->SerialNumber; + Vcb->NtfsInfo.ClustersPerFileRecord = BootSector->ClustersPerMftRecord; //#indef NDEBUG DbgPrint("Boot sector information:\n"); diff --git a/reactos/drivers/fs/ntfs/mft.c b/reactos/drivers/fs/ntfs/mft.c index f0d62476e95..ac21419dfcc 100644 --- a/reactos/drivers/fs/ntfs/mft.c +++ b/reactos/drivers/fs/ntfs/mft.c @@ -16,13 +16,14 @@ * 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 $ +/* $Id: mft.c,v 1.2 2003/09/15 16:01:16 ea 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 + * PROGRAMMER: Eric Kohl + * Updated by Valentin Verkhovsky 2003/09/12 */ /* INCLUDES *****************************************************************/ @@ -35,6 +36,9 @@ #include "ntfs.h" +#define __min(a,b) (((a) < (b)) ? (a) : (b)) + + /* FUNCTIONS ****************************************************************/ @@ -43,58 +47,379 @@ NtfsOpenMft(PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION Vcb) { PVOID Buffer; - PFILE_RECORD_HEADER RecordHeader; + PVOID Bitmap; + PFILE_RECORD_HEADER MftRecord; + PFILE_RECORD_HEADER file; PATTRIBUTE Attribute; + PATTRIBUTE AttrData; + PRESIDENT_ATTRIBUTE ResAttr; + NTSTATUS Status; - + ULONG BytesPerFileRecord; DPRINT1("NtfsOpenMft() called\n"); + ULONG n = 0; + BytesPerFileRecord = Vcb->NtfsInfo.ClustersPerFileRecord * + Vcb->NtfsInfo.BytesPerCluster; + Buffer = ExAllocatePool(NonPagedPool, - Vcb->NtfsInfo.BytesPerCluster); + BytesPerFileRecord); 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, + BytesPerFileRecord / Vcb->NtfsInfo.BytesPerSector, Vcb->NtfsInfo.BytesPerSector, (PVOID)Buffer); - if (NT_SUCCESS(Status)) + + + 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); + + DbgPrint("Enumerate MFT \n"); + MftRecord = Buffer; - /* Enumerate attributes */ - Attribute = (PATTRIBUTE)((ULONG)RecordHeader + - RecordHeader->Ntfs.UsnOffset + - RecordHeader->Ntfs.UsnSize * sizeof(USHORT)); - while (Attribute->AttributeType != 0xFFFFFFFF) - { - NtfsDumpAttribute(Attribute); + FixupUpdateSequenceArray(MftRecord); + + ULONG i; + Attribute = FindAttribute(MftRecord, AttributeBitmap, 0); + + + /* Get number of file records*/ + n = AttributeLength(FindAttribute(MftRecord, AttributeData,0)) + / BytesPerFileRecord; + + file = ExAllocatePool(NonPagedPool, BytesPerFileRecord); + + if (file == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Enumerate MFT Records */ + + for ( i=0; i < n; i++) + { + + + ReadFileRecord(i, file, Vcb, MftRecord, DeviceObject); + + if (file->Ntfs.Type == 'ELIF' && (file->Flags & 1) != 0) + { + + DbgPrint("\n"); + DbgPrint("File %lu\n", i); + DbgPrint("\n"); + /* Enumerate attributtes */ - Attribute = (PATTRIBUTE)((ULONG)Attribute + Attribute->Length); - } + EnumerAttribute(file, Vcb, DeviceObject); + DbgPrint("\n"); + DbgPrint("\n"); + + + } + + } - RecordHeader = (PFILE_RECORD_HEADER)((ULONG)RecordHeader + RecordHeader->BytesAllocated); + } + + ExFreePool(Buffer); + + ExFreePool(file); - } - - ExFreePool(Buffer); return(Status); } +PATTRIBUTE FindAttribute(PFILE_RECORD_HEADER file, -/* EOF */ + ATTRIBUTE_TYPE type, PWSTR name) +{ + PATTRIBUTE attr = (PATTRIBUTE)((PVOID)file + file->AttributeOffset); + + while (attr->AttributeType !=-1) + { + + if(attr->AttributeType == type) { + return attr; + } + attr = (PATTRIBUTE)((ULONG)attr + attr->Length); + } + + return 0; +} + + +ULONG AttributeLengthAllocated(PATTRIBUTE attr) +{ + + PRESIDENT_ATTRIBUTE ResAttr; + PNONRESIDENT_ATTRIBUTE NresAttr; + if(attr->Nonresident == FALSE) + { + ResAttr = (PRESIDENT_ATTRIBUTE)attr; + return ResAttr->ValueLength; + } + + else + { + NresAttr = (PNONRESIDENT_ATTRIBUTE)attr; + + return NresAttr->AllocatedSize; + } + + +} + +VOID ReadAttribute(PATTRIBUTE attr, PVOID buffer, PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject) +{ + if(attr->Nonresident == FALSE) + { + PRESIDENT_ATTRIBUTE ResAttr = (PRESIDENT_ATTRIBUTE)attr; + memcpy(buffer, (PRESIDENT_ATTRIBUTE)((PVOID)ResAttr + ResAttr->ValueOffset), + ResAttr->ValueLength); + + + } + + + PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr; + ReadExternalAttribute(NresAttr, 0, (ULONG)(NresAttr->LastVcn) + 1, + buffer, Vcb, DeviceObject); + + + + +} + + + +ULONG AttributeLength(PATTRIBUTE attr) +{ + PRESIDENT_ATTRIBUTE ResAttr; + PNONRESIDENT_ATTRIBUTE NresAttr; + + if(attr->Nonresident == FALSE) + { + ResAttr = (PRESIDENT_ATTRIBUTE)attr; + return ResAttr->ValueLength; + } + + else + { + NresAttr = (PNONRESIDENT_ATTRIBUTE)attr; + return NresAttr->DataSize; + } + +} + + + +VOID ReadFileRecord(ULONG index, PFILE_RECORD_HEADER file, + PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER Mft, + PDEVICE_OBJECT DeviceObject) + +{ + + PVOID p; + ULONG clusters = Vcb->NtfsInfo.ClustersPerFileRecord; + ULONG BytesPerFileRecord = clusters * Vcb->NtfsInfo.BytesPerCluster; + + + p = ExAllocatePool(NonPagedPool, BytesPerFileRecord); + + ULONGLONG vcn = index * BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster; + + ReadVCN(Mft, AttributeData, vcn, clusters, p, Vcb,DeviceObject); + + LONG m = (Vcb->NtfsInfo.BytesPerCluster / BytesPerFileRecord) - 1; + + ULONG n = m > 0 ? (index & m) : 0; + + memcpy(file, p + n * BytesPerFileRecord, BytesPerFileRecord); + + ExFreePool(p); + FixupUpdateSequenceArray(file); + + +} + + + +VOID ReadExternalAttribute(PNONRESIDENT_ATTRIBUTE NresAttr, + ULONGLONG vcn, ULONG count, PVOID buffer, + PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject) +{ + + + ULONGLONG lcn, runcount; + ULONG readcount, left; + + PUCHAR bytes = (PUCHAR)buffer; + + for (left = count; left>0; left -=readcount) + { + FindRun(NresAttr, vcn, &lcn, &runcount); + + readcount = (ULONG)(__min(runcount, left)); + + + ULONG n = readcount * Vcb->NtfsInfo.BytesPerCluster; + + if (lcn == 0) + memset(bytes, 0, n); + else + ReadLCN(lcn, readcount, bytes, Vcb, DeviceObject); + + vcn += readcount; + bytes += n; + + + } + + +} + + +BOOL FindRun(PNONRESIDENT_ATTRIBUTE NresAttr, ULONGLONG vcn, + PULONGLONG lcn, PULONGLONG count) +{ + PUCHAR run; + + ULONGLONG base = NresAttr->StartVcn; + + + if (vcn < NresAttr->StartVcn || vcn > NresAttr->LastVcn) + return FALSE; + + *lcn = 0; + + + for (run = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset); + *run != 0; run += RunLength(run)) { + + *lcn += RunLCN(run); + *count = RunCount(run); + + if(base <= vcn && vcn < base + *count) + { + *lcn = RunLCN(run) == 0 ? 0 : *lcn + vcn - base; + *count -= (ULONG)(vcn - base); + + + return TRUE; + } + else + base += *count; + + + } + + return FALSE; +} + + + +VOID ReadVCN(PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type, + ULONGLONG vcn, ULONG count, PVOID buffer, + PDEVICE_EXTENSION Vcb, PDEVICE_OBJECT DeviceObject) +{ + + PNONRESIDENT_ATTRIBUTE NresAttr; + PATTRIBUTE attr; + attr = FindAttribute(file, type,0); + + NresAttr = (PNONRESIDENT_ATTRIBUTE) attr; + + if (NresAttr == 0 || (vcn < NresAttr->StartVcn ||vcn > NresAttr->LastVcn)) + { + + PATTRIBUTE attrList = FindAttribute(file,AttributeAttributeList,0); + DbgPrint("Exeption \n"); + //KeDebugCheck(0); + } + + ReadExternalAttribute(NresAttr, vcn, count, buffer, Vcb, DeviceObject); + + +} + +BOOL bitset(PUCHAR bitmap, ULONG i) +{ + return (bitmap[i>>3] & (1 << (i & 7))) !=0; +} + + +VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file) +{ + PUSHORT usa = (PUSHORT)((PVOID)file + file->Ntfs.UsaOffset); + PUSHORT sector = (PUSHORT)file; + ULONG i; + + for( i =1; i < file->Ntfs.UsaCount; i++) + { + sector[255] = usa[i]; + sector += 256; + + } + +} + + +VOID ReadLCN(ULONGLONG lcn, ULONG count, PVOID buffer, PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject) +{ + + LARGE_INTEGER DiskSector; + DiskSector.QuadPart = lcn; + + + NtfsReadRawSectors(DeviceObject, DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster, + count * Vcb->NtfsInfo.SectorsPerCluster, Vcb->NtfsInfo.BytesPerSector, buffer); +} + + +VOID EnumerAttribute(PFILE_RECORD_HEADER file, PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject) + +{ + + ULONGLONG lcn; + ULONGLONG runcount; + ULONG size; + PATTRIBUTE attr = (PATTRIBUTE)((PVOID)file + file->AttributeOffset); + + while (attr->AttributeType !=-1) + { + + if(NtfsDumpAttribute(attr)) + { + + PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr; + + + FindRun(NresAttr,0,&lcn, &runcount); + + DbgPrint(" AllocatedSize %I64d DataSize %I64d\n", NresAttr->AllocatedSize, NresAttr->DataSize); + DbgPrint(" logical sectors: %lu", lcn); + DbgPrint("-%lu\n", lcn + runcount -1); + + } + attr = (PATTRIBUTE)((ULONG)attr + attr->Length); + + } + + +} + + + + /* EOF */ diff --git a/reactos/drivers/fs/ntfs/ntfs.h b/reactos/drivers/fs/ntfs/ntfs.h index 4b67eb7e131..2e21a0bdb98 100644 --- a/reactos/drivers/fs/ntfs/ntfs.h +++ b/reactos/drivers/fs/ntfs/ntfs.h @@ -50,6 +50,7 @@ typedef struct _NTFS_INFO ULARGE_INTEGER MftStart; ULARGE_INTEGER MftMirrStart; ULONGLONG SerialNumber; + ULONG ClustersPerFileRecord; } NTFS_INFO, *PNTFS_INFO; @@ -153,8 +154,8 @@ typedef enum typedef struct { ULONG Type; /* Magic number 'FILE' */ - USHORT UsnOffset; /* Offset to the update sequence */ - USHORT UsnSize; /* Size in words of Update Sequence Number & Array (S) */ + USHORT UsaOffset; /* Offset to the update sequence */ + USHORT UsaCount; /* Size in words of Update Sequence Number & Array (S) */ ULONGLONG Lsn; /* $LogFile Sequence Number (LSN) */ } NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER; @@ -280,9 +281,12 @@ extern PNTFS_GLOBAL_DATA NtfsGlobalData; /* attrib.c */ -VOID +BOOL NtfsDumpAttribute(PATTRIBUTE Attribute); +LONGLONG RunLCN(PUCHAR run); + +ULONG RunLength(PUCHAR run); /* blockdev.c */ @@ -399,6 +403,42 @@ NtfsOpenMft(PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION Vcb); +VOID ReadAttribute(PATTRIBUTE attr, PVOID buffer, PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject); + +ULONG AttributeLength(PATTRIBUTE attr); + +VOID ReadFileRecord(ULONG index, PFILE_RECORD_HEADER file, + PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER Mft, + PDEVICE_OBJECT DeviceObject); + + +PATTRIBUTE FindAttribute(PFILE_RECORD_HEADER file, + + ATTRIBUTE_TYPE type, PWSTR name); + + +ULONG AttributeLengthAllocated(PATTRIBUTE attr); + +VOID ReadVCN(PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type, + ULONGLONG vcn, ULONG count, PVOID buffer, + PDEVICE_EXTENSION Vcb, PDEVICE_OBJECT DeviceObject); + + +VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file); + +VOID ReadExternalAttribute(PNONRESIDENT_ATTRIBUTE NresAttr, + ULONGLONG vcn, ULONG count, PVOID buffer, + PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject); + +VOID ReadLCN(ULONGLONG lcn, ULONG count, PVOID buffer, PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject); + + +VOID EnumerAttribute(PFILE_RECORD_HEADER file,PDEVICE_EXTENSION Vcb, + PDEVICE_OBJECT DeviceObject ); + #if 0 /* misc.c */