mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +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);
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1308,30 +1375,6 @@ InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
|
||||||
return NULL;
|
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;
|
Context->CurrAttr = (PVOID)-1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,7 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
FIND_ATTR_CONTXT Context;
|
FIND_ATTR_CONTXT Context;
|
||||||
PNTFS_ATTR_RECORD Attribute;
|
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);
|
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);
|
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);
|
FindCloseAttribute(&Context);
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,17 @@ typedef struct
|
||||||
};
|
};
|
||||||
} NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD;
|
} 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,
|
// The beginning and length of an attribute record are always aligned to an 8-byte boundary,
|
||||||
// relative to the beginning of the file record.
|
// relative to the beginning of the file record.
|
||||||
#define ATTR_RECORD_ALIGNMENT 8
|
#define ATTR_RECORD_ALIGNMENT 8
|
||||||
|
@ -486,6 +497,7 @@ typedef struct _NTFS_ATTR_CONTEXT
|
||||||
ULONGLONG CacheRunCurrentOffset;
|
ULONGLONG CacheRunCurrentOffset;
|
||||||
LARGE_MCB DataRunsMCB;
|
LARGE_MCB DataRunsMCB;
|
||||||
ULONGLONG FileMFTIndex;
|
ULONGLONG FileMFTIndex;
|
||||||
|
ULONGLONG FileOwnerMFTIndex; /* If attribute list attribute, reference the original file */
|
||||||
PNTFS_ATTR_RECORD pRecord;
|
PNTFS_ATTR_RECORD pRecord;
|
||||||
} NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;
|
} NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;
|
||||||
|
|
||||||
|
@ -534,8 +546,9 @@ typedef struct _FIND_ATTR_CONTXT
|
||||||
PNTFS_ATTR_RECORD FirstAttr;
|
PNTFS_ATTR_RECORD FirstAttr;
|
||||||
PNTFS_ATTR_RECORD CurrAttr;
|
PNTFS_ATTR_RECORD CurrAttr;
|
||||||
PNTFS_ATTR_RECORD LastAttr;
|
PNTFS_ATTR_RECORD LastAttr;
|
||||||
PNTFS_ATTR_RECORD NonResidentStart;
|
PNTFS_ATTRIBUTE_LIST_ITEM NonResidentStart;
|
||||||
PNTFS_ATTR_RECORD NonResidentEnd;
|
PNTFS_ATTRIBUTE_LIST_ITEM NonResidentEnd;
|
||||||
|
PNTFS_ATTRIBUTE_LIST_ITEM NonResidentCur;
|
||||||
ULONG Offset;
|
ULONG Offset;
|
||||||
} FIND_ATTR_CONTXT, *PFIND_ATTR_CONTXT;
|
} FIND_ATTR_CONTXT, *PFIND_ATTR_CONTXT;
|
||||||
|
|
||||||
|
@ -659,6 +672,14 @@ PFILENAME_ATTRIBUTE
|
||||||
GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
||||||
PFILE_RECORD_HEADER FileRecord);
|
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
|
NTSTATUS
|
||||||
FindFirstAttribute(PFIND_ATTR_CONTXT Context,
|
FindFirstAttribute(PFIND_ATTR_CONTXT Context,
|
||||||
PDEVICE_EXTENSION Vcb,
|
PDEVICE_EXTENSION Vcb,
|
||||||
|
|
Loading…
Reference in a new issue