diff --git a/reactos/drivers/filesystems/ntfs/attrib.c b/reactos/drivers/filesystems/ntfs/attrib.c index e75219abfdc..7b4b9e4b91b 100644 --- a/reactos/drivers/filesystems/ntfs/attrib.c +++ b/reactos/drivers/filesystems/ntfs/attrib.c @@ -23,6 +23,7 @@ * PROGRAMMERS: Eric Kohl * Valentin Verkhovsky * Hervé Poussineau (hpoussin@reactos.org) + * Pierre Schweitzer (pierre@reactos.org) */ /* INCLUDES *****************************************************************/ @@ -92,6 +93,207 @@ FindRun(PNTFS_ATTR_RECORD NresAttr, return TRUE; } +static +NTSTATUS +InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context) +{ + ULONGLONG ListSize; + PNTFS_ATTR_RECORD Attribute; + PNTFS_ATTR_CONTEXT ListContext; + + DPRINT("InternalReadNonResidentAttributes(%p)\n", Context); + + Attribute = Context->CurrAttr; + ASSERT(Attribute->Type == AttributeAttributeList); + + if (Context->OnlyResident) + { + Context->NonResidentStart = NULL; + Context->NonResidentEnd = NULL; + return STATUS_SUCCESS; + } + + if (Context->NonResidentStart != NULL) + { + return STATUS_FILE_CORRUPT_ERROR; + } + + ListContext = PrepareAttributeContext(Attribute); + ListSize = AttributeDataLength(&ListContext->Record); + if (ListSize > 0xFFFFFFFF) + { + ReleaseAttributeContext(ListContext); + return STATUS_BUFFER_OVERFLOW; + } + + Context->NonResidentStart = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS); + if (Context->NonResidentStart == NULL) + { + ReleaseAttributeContext(ListContext); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (ReadAttribute(Context->Vcb, ListContext, 0, (PCHAR)Context->NonResidentStart, (ULONG)ListSize) != ListSize) + { + ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS); + Context->NonResidentStart = NULL; + ReleaseAttributeContext(ListContext); + return STATUS_FILE_CORRUPT_ERROR; + } + + ReleaseAttributeContext(ListContext); + Context->NonResidentEnd = (PNTFS_ATTR_RECORD)((PCHAR)Context->NonResidentStart + ListSize); + return STATUS_SUCCESS; +} + +static +PNTFS_ATTR_RECORD +InternalGetNextAttribute(PFIND_ATTR_CONTXT Context) +{ + if (Context->CurrAttr == (PVOID)-1) + { + return NULL; + } + + if (Context->CurrAttr >= Context->FirstAttr && + Context->CurrAttr < Context->LastAttr) + { + if (Context->CurrAttr->Length == 0) + { + DPRINT1("Broken length!\n"); + Context->CurrAttr = (PVOID)-1; + return NULL; + } + + Context->CurrAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length); + if (Context->CurrAttr < Context->LastAttr && + Context->CurrAttr->Type != AttributeEnd) + { + return Context->CurrAttr; + } + } + + if (Context->NonResidentStart == NULL) + { + Context->CurrAttr = (PVOID)-1; + return NULL; + } + + if (Context->CurrAttr < Context->NonResidentStart || + Context->CurrAttr >= Context->NonResidentEnd) + { + Context->CurrAttr = Context->NonResidentStart; + } + else if (Context->CurrAttr->Length != 0) + { + Context->CurrAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length); + } + else + { + DPRINT1("Broken length!\n"); + Context->CurrAttr = (PVOID)-1; + return NULL; + } + + if (Context->CurrAttr < Context->NonResidentEnd && + Context->CurrAttr->Type != AttributeEnd) + { + return Context->CurrAttr; + } + + Context->CurrAttr = (PVOID)-1; + return NULL; +} + +NTSTATUS +FindFirstAttribute(PFIND_ATTR_CONTXT Context, + PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord, + BOOLEAN OnlyResident, + PNTFS_ATTR_RECORD * Attribute) +{ + NTSTATUS Status; + + DPRINT("FindFistAttribute(%p, %p, %p, %p, %u, %p)\n", Context, Vcb, FileRecord, OnlyResident, Attribute); + + Context->Vcb = Vcb; + Context->OnlyResident = OnlyResident; + Context->FirstAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); + Context->CurrAttr = Context->FirstAttr; + Context->LastAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse); + Context->NonResidentStart = NULL; + Context->NonResidentEnd = NULL; + + if (Context->FirstAttr->Type == AttributeEnd) + { + Context->CurrAttr = (PVOID)-1; + return STATUS_END_OF_FILE; + } + else if (Context->FirstAttr->Type == AttributeAttributeList) + { + Status = InternalReadNonResidentAttributes(Context); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + *Attribute = InternalGetNextAttribute(Context); + if (*Attribute == NULL) + { + return STATUS_END_OF_FILE; + } + } + else + { + *Attribute = Context->CurrAttr; + } + + return STATUS_SUCCESS; +} + +NTSTATUS +FindNextAttribute(PFIND_ATTR_CONTXT Context, + PNTFS_ATTR_RECORD * Attribute) +{ + NTSTATUS Status; + + DPRINT("FindNextAttribute(%p, %p)\n", Context, Attribute); + + *Attribute = InternalGetNextAttribute(Context); + if (*Attribute == NULL) + { + return STATUS_END_OF_FILE; + } + + if (Context->CurrAttr->Type != AttributeAttributeList) + { + return STATUS_SUCCESS; + } + + Status = InternalReadNonResidentAttributes(Context); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + *Attribute = InternalGetNextAttribute(Context); + if (*Attribute == NULL) + { + return STATUS_END_OF_FILE; + } + + return STATUS_SUCCESS; +} + +VOID +FindCloseAttribute(PFIND_ATTR_CONTXT Context) +{ + if (Context->NonResidentStart != NULL) + { + ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS); + Context->NonResidentStart = NULL; + } +} static VOID @@ -341,27 +543,33 @@ VOID NtfsDumpFileAttributes(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord) { + NTSTATUS Status; + FIND_ATTR_CONTXT Context; PNTFS_ATTR_RECORD Attribute; - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); - while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) && - Attribute->Type != AttributeEnd) + Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute); + while (NT_SUCCESS(Status)) { NtfsDumpAttribute(Vcb, Attribute); - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + Status = FindNextAttribute(&Context, &Attribute); } + + FindCloseAttribute(&Context); } PFILENAME_ATTRIBUTE -GetFileNameFromRecord(PFILE_RECORD_HEADER FileRecord, UCHAR NameType) +GetFileNameFromRecord(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord, + UCHAR NameType) { + FIND_ATTR_CONTXT Context; PNTFS_ATTR_RECORD Attribute; PFILENAME_ATTRIBUTE Name; + NTSTATUS Status; - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); - while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) && - Attribute->Type != AttributeEnd) + Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute); + while (NT_SUCCESS(Status)) { if (Attribute->Type == AttributeFileName) { @@ -370,50 +578,57 @@ GetFileNameFromRecord(PFILE_RECORD_HEADER FileRecord, UCHAR NameType) (Name->NameType == NTFS_FILE_NAME_WIN32_AND_DOS && NameType == NTFS_FILE_NAME_WIN32) || (Name->NameType == NTFS_FILE_NAME_WIN32_AND_DOS && NameType == NTFS_FILE_NAME_DOS)) { + FindCloseAttribute(&Context); return Name; } } - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + Status = FindNextAttribute(&Context, &Attribute); } + FindCloseAttribute(&Context); return NULL; } PSTANDARD_INFORMATION -GetStandardInformationFromRecord(PFILE_RECORD_HEADER FileRecord) +GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord) { + NTSTATUS Status; + FIND_ATTR_CONTXT Context; PNTFS_ATTR_RECORD Attribute; PSTANDARD_INFORMATION StdInfo; - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); - while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) && - Attribute->Type != AttributeEnd) + Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute); + while (NT_SUCCESS(Status)) { if (Attribute->Type == AttributeStandardInformation) { StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset); + FindCloseAttribute(&Context); return StdInfo; } - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + Status = FindNextAttribute(&Context, &Attribute); } + FindCloseAttribute(&Context); return NULL; } PFILENAME_ATTRIBUTE -GetBestFileNameFromRecord(PFILE_RECORD_HEADER FileRecord) +GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord) { PFILENAME_ATTRIBUTE FileName; - FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX); + FileName = GetFileNameFromRecord(Vcb, FileRecord, NTFS_FILE_NAME_POSIX); if (FileName == NULL) { - FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32); + FileName = GetFileNameFromRecord(Vcb, FileRecord, NTFS_FILE_NAME_WIN32); if (FileName == NULL) { - FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS); + FileName = GetFileNameFromRecord(Vcb, FileRecord, NTFS_FILE_NAME_DOS); } } diff --git a/reactos/drivers/filesystems/ntfs/create.c b/reactos/drivers/filesystems/ntfs/create.c index efb9c81cde4..d8ad7082a5f 100644 --- a/reactos/drivers/filesystems/ntfs/create.c +++ b/reactos/drivers/filesystems/ntfs/create.c @@ -135,7 +135,7 @@ NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt, break; } - FileName = GetBestFileNameFromRecord(MftRecord); + FileName = GetBestFileNameFromRecord(DeviceExt, MftRecord); if (FileName == NULL) { DPRINT1("$FILE_NAME attribute not found for %I64x\n", Id); diff --git a/reactos/drivers/filesystems/ntfs/dirctl.c b/reactos/drivers/filesystems/ntfs/dirctl.c index d7ff4daab8d..a9d16fdb12d 100644 --- a/reactos/drivers/filesystems/ntfs/dirctl.c +++ b/reactos/drivers/filesystems/ntfs/dirctl.c @@ -73,7 +73,7 @@ NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt, DPRINT("NtfsGetNameInformation() called\n"); - FileName = GetBestFileNameFromRecord(FileRecord); + FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord); if (FileName == NULL) { DPRINT1("No name information for file ID: %#I64x\n", MFTIndex); @@ -107,7 +107,7 @@ NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt, DPRINT("NtfsGetDirectoryInformation() called\n"); - FileName = GetBestFileNameFromRecord(FileRecord); + FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord); if (FileName == NULL) { DPRINT1("No name information for file ID: %#I64x\n", MFTIndex); @@ -115,7 +115,7 @@ NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt, return STATUS_OBJECT_NAME_NOT_FOUND; } - StdInfo = GetStandardInformationFromRecord(FileRecord); + StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord); ASSERT(StdInfo != NULL); Length = FileName->NameLength * sizeof (WCHAR); @@ -156,7 +156,7 @@ NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt, DPRINT("NtfsGetFullDirectoryInformation() called\n"); - FileName = GetBestFileNameFromRecord(FileRecord); + FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord); if (FileName == NULL) { DPRINT1("No name information for file ID: %#I64x\n", MFTIndex); @@ -164,7 +164,7 @@ NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt, return STATUS_OBJECT_NAME_NOT_FOUND; } - StdInfo = GetStandardInformationFromRecord(FileRecord); + StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord); ASSERT(StdInfo != NULL); Length = FileName->NameLength * sizeof (WCHAR); @@ -206,16 +206,16 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt, DPRINT("NtfsGetBothDirectoryInformation() called\n"); - FileName = GetBestFileNameFromRecord(FileRecord); + FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord); if (FileName == NULL) { DPRINT1("No name information for file ID: %#I64x\n", MFTIndex); NtfsDumpFileAttributes(DeviceExt, FileRecord); return STATUS_OBJECT_NAME_NOT_FOUND; } - ShortFileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS); + ShortFileName = GetFileNameFromRecord(DeviceExt, FileRecord, NTFS_FILE_NAME_DOS); - StdInfo = GetStandardInformationFromRecord(FileRecord); + StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord); ASSERT(StdInfo != NULL); Length = FileName->NameLength * sizeof (WCHAR); diff --git a/reactos/drivers/filesystems/ntfs/fcb.c b/reactos/drivers/filesystems/ntfs/fcb.c index 7d3d0700eda..02bbb1045ec 100644 --- a/reactos/drivers/filesystems/ntfs/fcb.c +++ b/reactos/drivers/filesystems/ntfs/fcb.c @@ -319,7 +319,7 @@ NtfsMakeRootFCB(PNTFS_VCB Vcb) return NULL; } - FileName = GetFileNameFromRecord(MftRecord, NTFS_FILE_NAME_WIN32); + FileName = GetFileNameFromRecord(Vcb, MftRecord, NTFS_FILE_NAME_WIN32); if (!FileName) { ExFreePoolWithTag(MftRecord, TAG_NTFS); @@ -387,7 +387,7 @@ NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB); - FileName = GetBestFileNameFromRecord(Record); + FileName = GetBestFileNameFromRecord(Vcb, Record); if (!FileName) { return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here @@ -428,7 +428,7 @@ NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, rcFCB->RFCB.ValidDataLength.QuadPart = Size; rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize; - StdInfo = GetStandardInformationFromRecord(Record); + StdInfo = GetStandardInformationFromRecord(Vcb, Record); if (StdInfo != NULL) { rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute; diff --git a/reactos/drivers/filesystems/ntfs/finfo.c b/reactos/drivers/filesystems/ntfs/finfo.c index 9b1ad8c628f..50604f847df 100644 --- a/reactos/drivers/filesystems/ntfs/finfo.c +++ b/reactos/drivers/filesystems/ntfs/finfo.c @@ -22,6 +22,7 @@ * PURPOSE: NTFS filesystem driver * PROGRAMMERS: Eric Kohl * Hervé Poussineau (hpoussin@reactos.org) + * Pierre Schweitzer (pierre@reactos.org) */ /* INCLUDES *****************************************************************/ @@ -225,9 +226,10 @@ NtfsGetSteamInformation(PNTFS_FCB Fcb, PFILE_STREAM_INFORMATION StreamInfo, PULONG BufferLength) { - NTSTATUS Status; ULONG CurrentSize; + FIND_ATTR_CONTXT Context; PNTFS_ATTR_RECORD Attribute; + NTSTATUS Status, BrowseStatus; PFILE_RECORD_HEADER FileRecord; PFILE_STREAM_INFORMATION CurrentInfo = StreamInfo, Previous = NULL; @@ -249,10 +251,8 @@ NtfsGetSteamInformation(PNTFS_FCB Fcb, return Status; } - Status = STATUS_SUCCESS; - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); - while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) && - Attribute->Type != AttributeEnd) + BrowseStatus = FindFirstAttribute(&Context, DeviceExt, FileRecord, FALSE, &Attribute); + while (NT_SUCCESS(BrowseStatus)) { if (Attribute->Type == AttributeData) { @@ -281,9 +281,10 @@ NtfsGetSteamInformation(PNTFS_FCB Fcb, *BufferLength -= CurrentSize; } - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + BrowseStatus = FindNextAttribute(&Context, &Attribute); } + FindCloseAttribute(&Context); ExFreePoolWithTag(FileRecord, TAG_NTFS); return Status; } diff --git a/reactos/drivers/filesystems/ntfs/fsctl.c b/reactos/drivers/filesystems/ntfs/fsctl.c index 0fffc338165..f5ec6b362be 100644 --- a/reactos/drivers/filesystems/ntfs/fsctl.c +++ b/reactos/drivers/filesystems/ntfs/fsctl.c @@ -570,6 +570,8 @@ GetNfsVolumeData(PDEVICE_EXTENSION DeviceExt, PIO_STACK_LOCATION Stack; PNTFS_VOLUME_DATA_BUFFER DataBuffer; PNTFS_ATTR_RECORD Attribute; + FIND_ATTR_CONTXT Context; + NTSTATUS Status; DataBuffer = (PNTFS_VOLUME_DATA_BUFFER)Irp->AssociatedIrp.SystemBuffer; Stack = IoGetCurrentIrpStackLocation(Irp); @@ -595,9 +597,8 @@ GetNfsVolumeData(PDEVICE_EXTENSION DeviceExt, DataBuffer->MftZoneStart.QuadPart = 0; // FIXME DataBuffer->MftZoneEnd.QuadPart = 0; // FIXME - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DeviceExt->MasterFileTable + DeviceExt->MasterFileTable->AttributeOffset); - while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)DeviceExt->MasterFileTable + DeviceExt->MasterFileTable->BytesInUse) && - Attribute->Type != AttributeEnd) + Status = FindFirstAttribute(&Context, DeviceExt, DeviceExt->MasterFileTable, FALSE, &Attribute); + while (NT_SUCCESS(Status)) { if (Attribute->Type == AttributeData) { @@ -607,8 +608,9 @@ GetNfsVolumeData(PDEVICE_EXTENSION DeviceExt, break; } - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + Status = FindNextAttribute(&Context, &Attribute); } + FindCloseAttribute(&Context); Irp->IoStatus.Information = sizeof(NTFS_VOLUME_DATA_BUFFER); diff --git a/reactos/drivers/filesystems/ntfs/mft.c b/reactos/drivers/filesystems/ntfs/mft.c index 484d9f2e5d2..a28c811b174 100644 --- a/reactos/drivers/filesystems/ntfs/mft.c +++ b/reactos/drivers/filesystems/ntfs/mft.c @@ -79,95 +79,6 @@ ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context) } -PNTFS_ATTR_CONTEXT -FindAttributeHelper(PDEVICE_EXTENSION Vcb, - PNTFS_ATTR_RECORD AttrRecord, - PNTFS_ATTR_RECORD AttrRecordEnd, - ULONG Type, - PCWSTR Name, - ULONG NameLength) -{ - DPRINT("FindAttributeHelper(%p, %p, %p, 0x%x, %S, %u)\n", Vcb, AttrRecord, AttrRecordEnd, Type, Name, NameLength); - - while (AttrRecord < AttrRecordEnd) - { - DPRINT("AttrRecord->Type = 0x%x\n", AttrRecord->Type); - - if (AttrRecord->Type == AttributeEnd) - break; - - if (AttrRecord->Type == AttributeAttributeList) - { - PNTFS_ATTR_CONTEXT Context; - PNTFS_ATTR_CONTEXT ListContext; - PVOID ListBuffer; - ULONGLONG ListSize; - PNTFS_ATTR_RECORD ListAttrRecord; - PNTFS_ATTR_RECORD ListAttrRecordEnd; - - ListContext = PrepareAttributeContext(AttrRecord); - - ListSize = AttributeDataLength(&ListContext->Record); - if(ListSize <= 0xFFFFFFFF) - ListBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS); - else - ListBuffer = NULL; - - if(!ListBuffer) - { - DPRINT("Failed to allocate memory: %x\n", (ULONG)ListSize); - continue; - } - - ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer; - ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize); - - if (ReadAttribute(Vcb, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize) - { - Context = FindAttributeHelper(Vcb, ListAttrRecord, ListAttrRecordEnd, - Type, Name, NameLength); - - ReleaseAttributeContext(ListContext); - ExFreePoolWithTag(ListBuffer, TAG_NTFS); - - if (Context != NULL) - { - if (AttrRecord->IsNonResident) DPRINT("Found context = %p\n", Context); - return Context; - } - } - } - - if (AttrRecord->Type == Type) - { - if (AttrRecord->NameLength == NameLength) - { - PWCHAR AttrName; - - AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset); - DPRINT("%.*S, %.*S\n", AttrRecord->NameLength, AttrName, NameLength, Name); - if (RtlCompareMemory(AttrName, Name, NameLength << 1) == (NameLength << 1)) - { - /* Found it, fill up the context and return. */ - DPRINT("Found context\n"); - return PrepareAttributeContext(AttrRecord); - } - } - } - - if (AttrRecord->Length == 0) - { - DPRINT("Null length attribute record\n"); - return NULL; - } - AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length); - } - - DPRINT("Ended\n"); - return NULL; -} - - NTSTATUS FindAttribute(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, @@ -176,21 +87,36 @@ FindAttribute(PDEVICE_EXTENSION Vcb, ULONG NameLength, PNTFS_ATTR_CONTEXT * AttrCtx) { - PNTFS_ATTR_RECORD AttrRecord; - PNTFS_ATTR_RECORD AttrRecordEnd; + NTSTATUS Status; + FIND_ATTR_CONTXT Context; + PNTFS_ATTR_RECORD Attribute; DPRINT("FindAttribute(%p, %p, 0x%x, %S, %u, %p)\n", Vcb, MftRecord, Type, Name, NameLength, AttrCtx); - AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributeOffset); - AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Vcb->NtfsInfo.BytesPerFileRecord); - - *AttrCtx = FindAttributeHelper(Vcb, AttrRecord, AttrRecordEnd, Type, Name, NameLength); - if (*AttrCtx == NULL) + Status = FindFirstAttribute(&Context, Vcb, MftRecord, FALSE, &Attribute); + while (NT_SUCCESS(Status)) { - return STATUS_OBJECT_NAME_NOT_FOUND; + if (Attribute->Type == Type && Attribute->NameLength == NameLength) + { + PWCHAR AttrName; + + AttrName = (PWCHAR)((PCHAR)Attribute + Attribute->NameOffset); + DPRINT("%.*S, %.*S\n", Attribute->NameLength, AttrName, NameLength, Name); + if (RtlCompareMemory(AttrName, Name, NameLength << 1) == (NameLength << 1)) + { + /* Found it, fill up the context and return. */ + DPRINT("Found context\n"); + *AttrCtx = PrepareAttributeContext(Attribute); + FindCloseAttribute(&Context); + return STATUS_SUCCESS; + } + } + + Status = FindNextAttribute(&Context, &Attribute); } - return STATUS_SUCCESS; + FindCloseAttribute(&Context); + return STATUS_OBJECT_NAME_NOT_FOUND; } diff --git a/reactos/drivers/filesystems/ntfs/ntfs.h b/reactos/drivers/filesystems/ntfs/ntfs.h index 38862588098..6366b3cff02 100644 --- a/reactos/drivers/filesystems/ntfs/ntfs.h +++ b/reactos/drivers/filesystems/ntfs/ntfs.h @@ -462,6 +462,17 @@ typedef struct _FCB } NTFS_FCB, *PNTFS_FCB; +typedef struct _FIND_ATTR_CONTXT +{ + PDEVICE_EXTENSION Vcb; + BOOLEAN OnlyResident; + PNTFS_ATTR_RECORD FirstAttr; + PNTFS_ATTR_RECORD CurrAttr; + PNTFS_ATTR_RECORD LastAttr; + PNTFS_ATTR_RECORD NonResidentStart; + PNTFS_ATTR_RECORD NonResidentEnd; +} FIND_ATTR_CONTXT, *PFIND_ATTR_CONTXT; + extern PNTFS_GLOBAL_DATA NtfsGlobalData; FORCEINLINE @@ -487,16 +498,35 @@ DecodeRun(PUCHAR DataRun, ULONGLONG *DataRunLength); VOID -NtfsDumpFileAttributes(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord); +NtfsDumpFileAttributes(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord); PSTANDARD_INFORMATION -GetStandardInformationFromRecord(PFILE_RECORD_HEADER FileRecord); +GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord); PFILENAME_ATTRIBUTE -GetFileNameFromRecord(PFILE_RECORD_HEADER FileRecord, UCHAR NameType); +GetFileNameFromRecord(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord, + UCHAR NameType); PFILENAME_ATTRIBUTE -GetBestFileNameFromRecord(PFILE_RECORD_HEADER FileRecord); +GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord); + +NTSTATUS +FindFirstAttribute(PFIND_ATTR_CONTXT Context, + PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER FileRecord, + BOOLEAN OnlyResident, + PNTFS_ATTR_RECORD * Attribute); + +NTSTATUS +FindNextAttribute(PFIND_ATTR_CONTXT Context, + PNTFS_ATTR_RECORD * Attribute); + +VOID +FindCloseAttribute(PFIND_ATTR_CONTXT Context); /* blockdev.c */ diff --git a/reactos/drivers/filesystems/ntfs/rw.c b/reactos/drivers/filesystems/ntfs/rw.c index 336e107d666..cfccd04a6e4 100644 --- a/reactos/drivers/filesystems/ntfs/rw.c +++ b/reactos/drivers/filesystems/ntfs/rw.c @@ -98,13 +98,14 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt, Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Fcb->Stream, wcslen(Fcb->Stream), &DataContext); if (!NT_SUCCESS(Status)) { + NTSTATUS BrowseStatus; + FIND_ATTR_CONTXT Context; PNTFS_ATTR_RECORD Attribute; DPRINT1("No '%S' data stream associated with file!\n", Fcb->Stream); - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); - while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) && - Attribute->Type != AttributeEnd) + BrowseStatus = FindFirstAttribute(&Context, DeviceExt, FileRecord, FALSE, &Attribute); + while (NT_SUCCESS(BrowseStatus)) { if (Attribute->Type == AttributeData) { @@ -116,8 +117,9 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt, DPRINT1("Data stream: '%wZ' available\n", &Name); } - Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + BrowseStatus = FindNextAttribute(&Context, &Attribute); } + FindCloseAttribute(&Context); ReleaseAttributeContext(DataContext); ExFreePoolWithTag(FileRecord, TAG_NTFS);