mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NTFS] Correctly find attributes stored in another file record in MFT (and referenced in data stream)
This commit is contained in:
parent
86b8aeb3f2
commit
4d3df0da50
3 changed files with 147 additions and 27 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue