Patch by Valentin Verkhovsky: Ntfs driver is updated now and ready for testing.

I've been working on MFT processing for while.
Thus driver performs  only  files & attribute enumerating
by VCN-LCN pair mapping   like M$ Nfi  utility.

For me it compiles and the image loads correctly.

svn path=/trunk/; revision=6087
This commit is contained in:
Emanuele Aliberti 2003-09-15 16:01:16 +00:00
parent ed00963623
commit 1f1078fba3
4 changed files with 463 additions and 117 deletions

View file

@ -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;
}

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#define NDEBUG
#include <debug.h>
#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");

View file

@ -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 */

View file

@ -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 */