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.…
==============================================================================
--- 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/ntf…
==============================================================================
--- 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/includ…
==============================================================================
--- 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);