https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4d3df0da50b99f8f868449d262b88ffe2ac1d789

commit 4d3df0da50b99f8f868449d262b88ffe2ac1d789
Author:     Sylvain Deverre <deverre.s...@gmail.com>
AuthorDate: Thu Aug 8 22:09:13 2019 +0200
Commit:     Colin Finck <co...@reactos.org>
CommitDate: Fri Aug 16 11:08:29 2019 +0200

    [NTFS] Correctly find attributes stored in another file record in MFT (and 
referenced in data stream)
---
 drivers/filesystems/ntfs/attrib.c | 93 ++++++++++++++++++++++++++++-----------
 drivers/filesystems/ntfs/mft.c    | 56 +++++++++++++++++++++++
 drivers/filesystems/ntfs/ntfs.h   | 25 ++++++++++-
 3 files changed, 147 insertions(+), 27 deletions(-)

diff --git a/drivers/filesystems/ntfs/attrib.c 
b/drivers/filesystems/ntfs/attrib.c
index 1a04b763a2a..006465ce975 100644
--- a/drivers/filesystems/ntfs/attrib.c
+++ b/drivers/filesystems/ntfs/attrib.c
@@ -1258,7 +1258,74 @@ InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT 
Context)
     }
 
     ReleaseAttributeContext(ListContext);
-    Context->NonResidentEnd = 
(PNTFS_ATTR_RECORD)((PCHAR)Context->NonResidentStart + ListSize);
+    Context->NonResidentEnd = 
(PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentStart + ListSize);
+    return STATUS_SUCCESS;
+}
+
+static
+PNTFS_ATTRIBUTE_LIST_ITEM
+InternalGetNextAttributeListItem(PFIND_ATTR_CONTXT Context)
+{
+    PNTFS_ATTRIBUTE_LIST_ITEM NextItem;
+
+    if (Context->NonResidentCur == (PVOID)-1)
+    {
+        return NULL;
+    }
+
+    if (Context->NonResidentCur == NULL || Context->NonResidentCur->Type == 
AttributeEnd)
+    {
+        Context->NonResidentCur = (PVOID)-1;
+        return NULL;
+    }
+
+    if (Context->NonResidentCur->Length == 0)
+    {
+        DPRINT1("Broken length list entry length !");
+        Context->NonResidentCur = (PVOID)-1;
+        return NULL;
+    }
+
+    NextItem = (PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentCur + 
Context->NonResidentCur->Length);
+    if (NextItem->Length == 0 || NextItem->Type == AttributeEnd)
+    {
+        Context->NonResidentCur = (PVOID)-1;
+        return NULL;
+    }
+
+    if (NextItem < Context->NonResidentStart || NextItem > 
Context->NonResidentEnd)
+    {
+        Context->NonResidentCur = (PVOID)-1;
+        return NULL;
+    }
+
+    Context->NonResidentCur = NextItem;
+    return NextItem;
+}
+
+NTSTATUS
+FindFirstAttributeListItem(PFIND_ATTR_CONTXT Context,
+                           PNTFS_ATTRIBUTE_LIST_ITEM *Item)
+{
+    if (Context->NonResidentStart == NULL || Context->NonResidentStart->Type 
== AttributeEnd)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    Context->NonResidentCur = Context->NonResidentStart;
+    *Item = Context->NonResidentCur;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FindNextAttributeListItem(PFIND_ATTR_CONTXT Context,
+                          PNTFS_ATTRIBUTE_LIST_ITEM *Item)
+{
+    *Item = InternalGetNextAttributeListItem(Context);
+    if (*Item == NULL)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
     return STATUS_SUCCESS;
 }
 
@@ -1308,30 +1375,6 @@ InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
         return NULL;
     }
 
-    if (Context->CurrAttr < Context->NonResidentStart ||
-        Context->CurrAttr >= Context->NonResidentEnd)
-    {
-        Context->CurrAttr = Context->NonResidentStart;
-    }
-    else if (Context->CurrAttr->Length != 0)
-    {
-        NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + 
Context->CurrAttr->Length);
-        Context->Offset += ((ULONG_PTR)NextAttribute - 
(ULONG_PTR)Context->CurrAttr);
-        Context->CurrAttr = NextAttribute;
-    }
-    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;
 }
diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c
index f03074cdfda..e1411f0ac96 100644
--- a/drivers/filesystems/ntfs/mft.c
+++ b/drivers/filesystems/ntfs/mft.c
@@ -140,6 +140,7 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
     NTSTATUS Status;
     FIND_ATTR_CONTXT Context;
     PNTFS_ATTR_RECORD Attribute;
+    PNTFS_ATTRIBUTE_LIST_ITEM AttrListItem;
 
     DPRINT("FindAttribute(%p, %p, 0x%x, %S, %lu, %p, %p)\n", Vcb, MftRecord, 
Type, Name, NameLength, AttrCtx, Offset);
 
@@ -184,6 +185,61 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
         Status = FindNextAttribute(&Context, &Attribute);
     }
 
+    /* No attribute found, check if it is referenced in another file record */
+    Status = FindFirstAttributeListItem(&Context, &AttrListItem);
+    while (NT_SUCCESS(Status))
+    {
+        if (AttrListItem->Type == Type && AttrListItem->NameLength == 
NameLength)
+        {
+            if (NameLength != 0)
+            {
+                PWCHAR AttrName;
+
+                AttrName = (PWCHAR)((PCHAR)AttrListItem + 
AttrListItem->NameOffset);
+                DPRINT("%.*S, %.*S\n", AttrListItem->NameLength, AttrName, 
NameLength, Name);
+                if (RtlCompareMemory(AttrName, Name, NameLength * 
sizeof(WCHAR)) == (NameLength  * sizeof(WCHAR)))
+                {
+                    Found = TRUE;
+                }
+            }
+            else
+            {
+                Found = TRUE;
+            }
+
+            if (Found == TRUE)
+            {
+                /* Get the MFT Index of attribute */
+                ULONGLONG MftIndex;
+                PFILE_RECORD_HEADER RemoteHdr;
+
+                MftIndex = AttrListItem->MFTIndex & NTFS_MFT_MASK;
+                RemoteHdr = 
ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
+
+                if (RemoteHdr == NULL)
+                {
+                    FindCloseAttribute(&Context);
+                    return STATUS_INSUFFICIENT_RESOURCES;
+                }
+
+                /* Check we are not reading ourselves */
+                if (MftRecord->MFTRecordNumber == MftIndex)
+                {
+                    DPRINT1("Attribute list references missing attribute to 
this file entry !");
+                    ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, 
RemoteHdr);
+                    FindCloseAttribute(&Context);
+                    return STATUS_OBJECT_NAME_NOT_FOUND;
+                }
+                /* Read the new file record */
+                ReadFileRecord(Vcb, MftIndex, RemoteHdr);
+                Status = FindAttribute(Vcb, RemoteHdr, Type, Name, NameLength, 
AttrCtx, Offset);
+                ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, 
RemoteHdr);
+                FindCloseAttribute(&Context);
+                return Status;
+            }
+        }
+        Status = FindNextAttributeListItem(&Context, &AttrListItem);
+    }
     FindCloseAttribute(&Context);
     return STATUS_OBJECT_NAME_NOT_FOUND;
 }
diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h
index c50a077e1c1..aa85b810883 100644
--- a/drivers/filesystems/ntfs/ntfs.h
+++ b/drivers/filesystems/ntfs/ntfs.h
@@ -300,6 +300,17 @@ typedef struct
     };
 } NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD;
 
+typedef struct
+{
+    ULONG Type;
+    USHORT Length;
+    UCHAR NameLength;
+    UCHAR NameOffset;
+    ULONGLONG StartingVCN;
+    ULONGLONG MFTIndex;
+    USHORT Instance;
+} NTFS_ATTRIBUTE_LIST_ITEM, *PNTFS_ATTRIBUTE_LIST_ITEM;
+
 // The beginning and length of an attribute record are always aligned to an 
8-byte boundary,
 // relative to the beginning of the file record.
 #define ATTR_RECORD_ALIGNMENT 8
@@ -486,6 +497,7 @@ typedef struct _NTFS_ATTR_CONTEXT
     ULONGLONG            CacheRunCurrentOffset;
     LARGE_MCB           DataRunsMCB;
     ULONGLONG           FileMFTIndex;
+    ULONGLONG           FileOwnerMFTIndex; /* If attribute list attribute, 
reference the original file */
     PNTFS_ATTR_RECORD    pRecord;
 } NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;
 
@@ -534,8 +546,9 @@ typedef struct _FIND_ATTR_CONTXT
     PNTFS_ATTR_RECORD FirstAttr;
     PNTFS_ATTR_RECORD CurrAttr;
     PNTFS_ATTR_RECORD LastAttr;
-    PNTFS_ATTR_RECORD NonResidentStart;
-    PNTFS_ATTR_RECORD NonResidentEnd;
+    PNTFS_ATTRIBUTE_LIST_ITEM NonResidentStart;
+    PNTFS_ATTRIBUTE_LIST_ITEM NonResidentEnd;
+    PNTFS_ATTRIBUTE_LIST_ITEM NonResidentCur;
     ULONG Offset;
 } FIND_ATTR_CONTXT, *PFIND_ATTR_CONTXT;
 
@@ -659,6 +672,14 @@ PFILENAME_ATTRIBUTE
 GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb,
                           PFILE_RECORD_HEADER FileRecord);
 
+NTSTATUS
+FindFirstAttributeListItem(PFIND_ATTR_CONTXT Context,
+                           PNTFS_ATTRIBUTE_LIST_ITEM *Item);
+
+NTSTATUS
+FindNextAttributeListItem(PFIND_ATTR_CONTXT Context,
+                          PNTFS_ATTRIBUTE_LIST_ITEM *Item);
+
 NTSTATUS
 FindFirstAttribute(PFIND_ATTR_CONTXT Context,
                    PDEVICE_EXTENSION Vcb,

Reply via email to