[ros-diffs] [navaraf] 21920: Attribute list support for NTFS and some memory leak fixes.

navaraf at svn.reactos.org navaraf at svn.reactos.org
Wed May 17 16:40:14 CEST 2006


Author: navaraf
Date: Wed May 17 18:40:14 2006
New Revision: 21920

URL: http://svn.reactos.ru/svn/reactos?rev=21920&view=rev
Log:
Attribute list support for NTFS and some memory leak fixes.

Modified:
    trunk/reactos/boot/freeldr/freeldr/fs/fs.c
    trunk/reactos/boot/freeldr/freeldr/fs/ntfs.c
    trunk/reactos/boot/freeldr/freeldr/include/fs/ntfs.h

Modified: trunk/reactos/boot/freeldr/freeldr/fs/fs.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/boot/freeldr/freeldr/fs/fs.c?rev=21920&r1=21919&r2=21920&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/fs/fs.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/fs/fs.c Wed May 17 18:40:14 2006
@@ -171,6 +171,19 @@
 
 VOID FsCloseFile(PFILE FileHandle)
 {
+	switch (FsType)
+	{
+	case FS_FAT:
+	case FS_ISO9660:
+	case FS_EXT2:
+		break;
+	case FS_NTFS:
+		NtfsCloseFile(FileHandle);
+		break;
+	default:
+		FileSystemError("Error: Unknown filesystem.");
+		break;
+	}
 }
 
 /*

Modified: trunk/reactos/boot/freeldr/freeldr/fs/ntfs.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/boot/freeldr/freeldr/fs/ntfs.c?rev=21920&r1=21919&r2=21920&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/fs/ntfs.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/fs/ntfs.c Wed May 17 18:40:14 2006
@@ -20,7 +20,6 @@
 /*
  * Limitations:
  * - No support for compressed files.
- * - No attribute list support.
  * - May crash on corrupted filesystem.
  */
 
@@ -36,7 +35,16 @@
 ULONG NtfsDriveNumber;
 ULONG NtfsSectorOfClusterZero;
 PNTFS_MFT_RECORD NtfsMasterFileTable;
-NTFS_ATTR_CONTEXT NtfsMFTContext;
+/* FIXME: NtfsMFTContext is never freed. */
+PNTFS_ATTR_CONTEXT NtfsMFTContext;
+
+static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
+{
+    if (AttrRecord->IsNonResident)
+        return AttrRecord->NonResident.DataSize;
+    else
+        return AttrRecord->Resident.ValueLength;
+}
 
 static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
 {
@@ -79,65 +87,42 @@
     return DataRun;
 }
 
-/* FIXME: Add support for attribute lists! */
-static BOOLEAN NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, ULONG Type, const WCHAR *Name)
-{
-    PNTFS_ATTR_RECORD AttrRecord;
-    PNTFS_ATTR_RECORD AttrRecordEnd;
-    ULONG NameLength;
-    PWCHAR AttrName;
-
-    AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
-    AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + NtfsMftRecordSize);
-    for (NameLength = 0; Name[NameLength] != 0; NameLength++)
-        ;
-
-    while (AttrRecord < AttrRecordEnd)
-    {
-        if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
-            break;
-
-        if (AttrRecord->Type == Type)
-        {
-            if (AttrRecord->NameLength == NameLength)
-            {
-                AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
-                if (RtlEqualMemory(AttrName, Name, NameLength << 1))
-                {
-                    /* Found it, fill up the context and return. */
-                    Context->Record = AttrRecord;
-                    if (AttrRecord->IsNonResident)
-                    {
-                    	LONGLONG DataRunOffset;
-                    	ULONGLONG DataRunLength;
-
-                        Context->CacheRun = (PUCHAR)Context->Record + Context->Record->NonResident.MappingPairsOffset;
-                        Context->CacheRunOffset = 0;
-                        Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
-                        Context->CacheRunLength = DataRunLength;
-                        if (DataRunOffset != -1)
-                        {
-                            /* Normal run. */
-                            Context->CacheRunStartLCN =
-                            Context->CacheRunLastLCN = DataRunOffset;
-                        }
-                        else
-                        {
-                            /* Sparse run. */
-                            Context->CacheRunStartLCN = -1;
-                            Context->CacheRunLastLCN = 0;
-                        }
-                        Context->CacheRunCurrentOffset = 0;
-                    }
-                    return TRUE;
-                }
-            }
-        }
-
-        AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
-    }
-
-    return FALSE;
+static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
+{
+    PNTFS_ATTR_CONTEXT Context;
+
+    Context = MmAllocateMemory(FIELD_OFFSET(NTFS_ATTR_CONTEXT, Record) + AttrRecord->Length);
+    RtlCopyMemory(&Context->Record, AttrRecord, AttrRecord->Length);
+    if (AttrRecord->IsNonResident)
+    {
+    	LONGLONG DataRunOffset;
+    	ULONGLONG DataRunLength;
+
+        Context->CacheRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
+        Context->CacheRunOffset = 0;
+        Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
+        Context->CacheRunLength = DataRunLength;
+        if (DataRunOffset != -1)
+        {
+            /* Normal run. */
+            Context->CacheRunStartLCN =
+            Context->CacheRunLastLCN = DataRunOffset;
+        }
+        else
+        {
+            /* Sparse run. */
+            Context->CacheRunStartLCN = -1;
+            Context->CacheRunLastLCN = 0;
+        }
+        Context->CacheRunCurrentOffset = 0;
+    }
+
+    return Context;
+}
+
+static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
+{
+    MmFreeMemory(Context);
 }
 
 /* FIXME: Optimize for multisector reads. */
@@ -194,13 +179,13 @@
     ULONGLONG ReadLength;
     ULONGLONG AlreadyRead;
 
-    if (!Context->Record->IsNonResident)
-    {
-        if (Offset > Context->Record->Resident.ValueLength)
+    if (!Context->Record.IsNonResident)
+    {
+        if (Offset > Context->Record.Resident.ValueLength)
             return 0;
-        if (Offset + Length > Context->Record->Resident.ValueLength)
-            Length = Context->Record->Resident.ValueLength - Offset;
-        RtlCopyMemory(Buffer, (PCHAR)Context->Record + Context->Record->Resident.ValueOffset + Offset, Length);
+        if (Offset + Length > Context->Record.Resident.ValueLength)
+            Length = Context->Record.Resident.ValueLength - Offset;
+        RtlCopyMemory(Buffer, (PCHAR)&Context->Record + Context->Record.Resident.ValueOffset + Offset, Length);
         return Length;
     }
 
@@ -223,7 +208,7 @@
     else
     {
         LastLCN = 0;
-        DataRun = (PUCHAR)Context->Record + Context->Record->NonResident.MappingPairsOffset;
+        DataRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
         CurrentOffset = 0;
 
         while (1)
@@ -307,6 +292,78 @@
     return AlreadyRead;
 }
 
+static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength)
+{
+    while (AttrRecord < AttrRecordEnd)
+    {
+        if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
+            break;
+
+        if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
+        {
+            PNTFS_ATTR_CONTEXT Context;
+            PNTFS_ATTR_CONTEXT ListContext;
+            PVOID ListBuffer;
+            ULONGLONG ListSize;
+            PNTFS_ATTR_RECORD ListAttrRecord;
+            PNTFS_ATTR_RECORD ListAttrRecordEnd;
+
+            ListContext = NtfsPrepareAttributeContext(AttrRecord);
+
+            ListSize = NtfsGetAttributeSize(&ListContext->Record);
+            ListBuffer = MmAllocateMemory(ListSize);
+  
+            ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
+            ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
+
+            if (NtfsReadAttribute(ListContext, 0, ListBuffer, ListSize) == ListSize)
+            {
+                Context = NtfsFindAttributeHelper(ListAttrRecord, ListAttrRecordEnd,
+                                                  Type, Name, NameLength);
+
+                NtfsReleaseAttributeContext(ListContext);
+                MmFreeMemory(ListBuffer);
+                
+                if (Context != NULL)
+                    return Context;
+            }
+        }
+
+        if (AttrRecord->Type == Type)
+        {
+            if (AttrRecord->NameLength == NameLength)
+            {
+                PWCHAR AttrName;
+
+                AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
+                if (RtlEqualMemory(AttrName, Name, NameLength << 1))
+                {
+                    /* Found it, fill up the context and return. */
+                    return NtfsPrepareAttributeContext(AttrRecord);
+                }
+            }
+        }
+
+        AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
+    }
+
+    return NULL;
+}
+
+static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_MFT_RECORD MftRecord, ULONG Type, const WCHAR *Name)
+{
+    PNTFS_ATTR_RECORD AttrRecord;
+    PNTFS_ATTR_RECORD AttrRecordEnd;
+    ULONG NameLength;
+
+    AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
+    AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + NtfsMftRecordSize);
+    for (NameLength = 0; Name[NameLength] != 0; NameLength++)
+        ;
+
+    return NtfsFindAttributeHelper(AttrRecord, AttrRecordEnd, Type, Name, NameLength);
+}
+
 static BOOLEAN NtfsFixupRecord(PNTFS_RECORD Record)
 {
     USHORT *USA;
@@ -335,7 +392,7 @@
 {
     ULONGLONG BytesRead;
 
-    BytesRead = NtfsReadAttribute(&NtfsMFTContext, MFTIndex * NtfsMftRecordSize, (PCHAR)Buffer, NtfsMftRecordSize);
+    BytesRead = NtfsReadAttribute(NtfsMFTContext, MFTIndex * NtfsMftRecordSize, (PCHAR)Buffer, NtfsMftRecordSize);
     if (BytesRead != NtfsMftRecordSize)
         return FALSE;
 
@@ -399,9 +456,9 @@
 {
     PNTFS_MFT_RECORD MftRecord;
     ULONG Magic;
-    NTFS_ATTR_CONTEXT IndexRootCtx;
-    NTFS_ATTR_CONTEXT IndexBitmapCtx;
-    NTFS_ATTR_CONTEXT IndexAllocationCtx;
+    PNTFS_ATTR_CONTEXT IndexRootCtx;
+    PNTFS_ATTR_CONTEXT IndexBitmapCtx;
+    PNTFS_ATTR_CONTEXT IndexAllocationCtx;
     PNTFS_INDEX_ROOT IndexRoot;
     ULONGLONG BitmapDataSize;
     ULONGLONG IndexAllocationSize;
@@ -421,7 +478,8 @@
     {
         Magic = MftRecord->Magic;
 
-        if (!NtfsFindAttribute(&IndexRootCtx, MftRecord, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30"))
+        IndexRootCtx = NtfsFindAttribute(MftRecord, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30");
+        if (IndexRootCtx == NULL)
         {
             MmFreeMemory(MftRecord);
             return FALSE;
@@ -434,11 +492,12 @@
             return FALSE;
         }
 
-        NtfsReadAttribute(&IndexRootCtx, 0, IndexRecord, NtfsIndexRecordSize);
+        NtfsReadAttribute(IndexRootCtx, 0, IndexRecord, NtfsIndexRecordSize);
         IndexRoot = (PNTFS_INDEX_ROOT)IndexRecord;
         IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)&IndexRoot->IndexHeader + IndexRoot->IndexHeader.EntriesOffset);
         /* Index root is always resident. */
-        IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx.Record->Resident.ValueLength);
+        IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx->Record.Resident.ValueLength);
+        NtfsReleaseAttributeContext(IndexRootCtx);
 
         DbgPrint((DPRINT_FILESYSTEM, "NtfsIndexRecordSize: %x IndexBlockSize: %x\n", NtfsIndexRecordSize, IndexRoot->IndexBlockSize));
 
@@ -460,17 +519,15 @@
             DbgPrint((DPRINT_FILESYSTEM, "Large Index!\n"));
 
             IndexBlockSize = IndexRoot->IndexBlockSize;
-
-            if (!NtfsFindAttribute(&IndexBitmapCtx, MftRecord, NTFS_ATTR_TYPE_BITMAP, L"$I30"))
+        
+            IndexBitmapCtx = NtfsFindAttribute(MftRecord, NTFS_ATTR_TYPE_BITMAP, L"$I30");
+            if (IndexBitmapCtx == NULL)
             {
                 DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n"));
                 MmFreeMemory(MftRecord);
                 return FALSE;
             }
-            if (IndexBitmapCtx.Record->IsNonResident)
-                BitmapDataSize = IndexBitmapCtx.Record->NonResident.DataSize;
-            else
-                BitmapDataSize = IndexBitmapCtx.Record->Resident.ValueLength;
+            BitmapDataSize = NtfsGetAttributeSize(&IndexBitmapCtx->Record);
             DbgPrint((DPRINT_FILESYSTEM, "BitmapDataSize: %x\n", BitmapDataSize));
             BitmapData = MmAllocateMemory(BitmapDataSize);
             if (BitmapData == NULL)
@@ -479,9 +536,11 @@
                 MmFreeMemory(MftRecord);
                 return FALSE;
             }
-            NtfsReadAttribute(&IndexBitmapCtx, 0, BitmapData, BitmapDataSize);
-
-            if (!NtfsFindAttribute(&IndexAllocationCtx, MftRecord, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30"))
+            NtfsReadAttribute(IndexBitmapCtx, 0, BitmapData, BitmapDataSize);
+            NtfsReleaseAttributeContext(IndexBitmapCtx);
+
+            IndexAllocationCtx = NtfsFindAttribute(MftRecord, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30");
+            if (IndexAllocationCtx == NULL)
             {
                 DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n"));
                 MmFreeMemory(BitmapData);
@@ -489,10 +548,7 @@
                 MmFreeMemory(MftRecord);
                 return FALSE;
             }
-            if (IndexAllocationCtx.Record->IsNonResident)
-                IndexAllocationSize = IndexAllocationCtx.Record->NonResident.DataSize;
-            else
-                IndexAllocationSize = IndexAllocationCtx.Record->Resident.ValueLength;
+            IndexAllocationSize = NtfsGetAttributeSize(&IndexAllocationCtx->Record);
 
             RecordOffset = 0;
 
@@ -513,7 +569,7 @@
                     break;
                 }
 
-                NtfsReadAttribute(&IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
+                NtfsReadAttribute(IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
 
                 if (!NtfsFixupRecord((PNTFS_RECORD)IndexRecord))
                 {
@@ -534,6 +590,7 @@
                         MmFreeMemory(BitmapData);
                         MmFreeMemory(IndexRecord);
                         MmFreeMemory(MftRecord);
+                        NtfsReleaseAttributeContext(IndexAllocationCtx);
                         return TRUE;
                     }
                     IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
@@ -542,6 +599,7 @@
                 RecordOffset += IndexBlockSize;
             }
 
+            NtfsReleaseAttributeContext(IndexAllocationCtx);
             MmFreeMemory(BitmapData);
         }
 
@@ -556,7 +614,7 @@
     return FALSE;
 }
 
-static BOOLEAN NtfsLookupFile(PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONTEXT DataContext)
+static BOOLEAN NtfsLookupFile(PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONTEXT *DataContext)
 {
     ULONG NumberOfPathParts;
     CHAR PathPart[261];
@@ -590,7 +648,8 @@
         return FALSE;
     }
 
-    if (!NtfsFindAttribute(DataContext, MftRecord, NTFS_ATTR_TYPE_DATA, L""))
+    *DataContext = NtfsFindAttribute(MftRecord, NTFS_ATTR_TYPE_DATA, L"");
+    if (*DataContext == NULL)
     {
         DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile: Can't find data attribute\n"));
         return FALSE;
@@ -664,7 +723,8 @@
     RtlCopyMemory(NtfsMasterFileTable, (PCHAR)DISKREADBUFFER, NtfsMftRecordSize);
 
     DbgPrint((DPRINT_FILESYSTEM, "Searching for DATA attribute...\n"));
-    if (!NtfsFindAttribute(&NtfsMFTContext, NtfsMasterFileTable, NTFS_ATTR_TYPE_DATA, L""))
+    NtfsMFTContext = NtfsFindAttribute(NtfsMasterFileTable, NTFS_ATTR_TYPE_DATA, L"");
+    if (NtfsMFTContext == NULL)
     {
         FileSystemError("Can't find data attribute for Master File Table.");
         return FALSE;
@@ -696,11 +756,18 @@
     return (FILE*)FileHandle;
 }
 
+VOID NtfsCloseFile(FILE *File)
+{
+    PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
+    NtfsReleaseAttributeContext(FileHandle->DataContext);
+    MmFreeMemory(FileHandle);
+}
+
 BOOLEAN NtfsReadFile(FILE *File, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer)
 {
     PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
     ULONGLONG BytesRead64;
-    BytesRead64 = NtfsReadAttribute(&FileHandle->DataContext, FileHandle->Offset, Buffer, BytesToRead);
+    BytesRead64 = NtfsReadAttribute(FileHandle->DataContext, FileHandle->Offset, Buffer, BytesToRead);
     if (BytesRead64)
     {
         *BytesRead = (ULONG)BytesRead64;
@@ -713,10 +780,7 @@
 ULONG NtfsGetFileSize(FILE *File)
 {
     PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
-    if (FileHandle->DataContext.Record->IsNonResident)
-        return (ULONG)FileHandle->DataContext.Record->NonResident.DataSize;
-    else
-        return (ULONG)FileHandle->DataContext.Record->Resident.ValueLength;
+    return (ULONG)NtfsGetAttributeSize(&FileHandle->DataContext->Record);
 }
 
 VOID NtfsSetFilePointer(FILE *File, ULONG NewFilePointer)

Modified: trunk/reactos/boot/freeldr/freeldr/include/fs/ntfs.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/boot/freeldr/freeldr/include/fs/ntfs.h?rev=21920&r1=21919&r2=21920&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/fs/ntfs.h (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/fs/ntfs.h Wed May 17 18:40:14 2006
@@ -203,23 +203,24 @@
 
 typedef struct
 {
-	PNTFS_ATTR_RECORD	Record;
 	PUCHAR			CacheRun;
 	ULONGLONG			CacheRunOffset;
 	LONGLONG			CacheRunStartLCN;
 	ULONGLONG			CacheRunLength;
 	LONGLONG			CacheRunLastLCN;
 	ULONGLONG			CacheRunCurrentOffset;
+	NTFS_ATTR_RECORD	Record;
 } NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;
 
 typedef struct
 {
-	NTFS_ATTR_CONTEXT	DataContext;
+	PNTFS_ATTR_CONTEXT	DataContext;
 	ULONGLONG			Offset;
 } PACKED NTFS_FILE_HANDLE, *PNTFS_FILE_HANDLE;
 
 BOOLEAN	NtfsOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector);
 FILE*	NtfsOpenFile(PCSTR FileName);
+VOID	NtfsCloseFile(FILE *FileHandle);
 BOOLEAN	NtfsReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer);
 ULONG	NtfsGetFileSize(FILE *FileHandle);
 VOID	NtfsSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);




More information about the Ros-diffs mailing list