mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:23:01 +00:00
[NTFS] - Add some helper functions for new features. Add some fixes. Add support for creating an index allocation, splitting a b-tree node, or "demoting" the index root. This allows for file creation without functional limitations.
+AddBitmap() - adds a $BITMAP attribute to a file record. +AddIndexAllocation() - adds an $INDEX_ALLOCATION attribute to a file record. +CountBTreeKeys() - Counts the number of linked B-Tree keys. CreateIndexBufferFromBTreeNode() - Set INDEX_NODE_LARGE if the node has sub-nodes. CreateIndexRootFromBTree() - Simplify the usage and math of MaxIndexSize; make it only account for the cumulative size of the index entries. +DemoteBTreeRoot() - Replaces the contents of an index root with a dummy key, and puts those contents in a new node, which is made a child of the dummy key. This is done when an index root grows too large. +GetIndexEntryVCN() - Retrieves the VCN from an index entry. NtfsAddFilenameToDirectory() - Fix math for MaxIndexRootSize. NtfsInsertKey() - Add support for splitting a B-Tree node. Don't check size of index root (that will be handled later). +SplitBTreeNode() - Called when a B-Tree node grows too large. UpdateIndexAllocation() - Create an $I30 index allocation attribute and bitmap attribute if needed. UpdateIndexNode() - Update children before updating the current node. Store VCN of child nodes in the index entries of their respective keys. svn path=/branches/GSoC_2016/NTFS/; revision=75707
This commit is contained in:
parent
5e7c11842a
commit
52c30fdf37
4 changed files with 895 additions and 134 deletions
|
@ -36,6 +36,100 @@
|
|||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/**
|
||||
* @name AddBitmap
|
||||
* @implemented
|
||||
*
|
||||
* Adds a $BITMAP attribute to a given FileRecord.
|
||||
*
|
||||
* @param Vcb
|
||||
* Pointer to an NTFS_VCB for the destination volume.
|
||||
*
|
||||
* @param FileRecord
|
||||
* Pointer to a complete file record to add the attribute to.
|
||||
*
|
||||
* @param AttributeAddress
|
||||
* Pointer to the region of memory that will receive the $INDEX_ALLOCATION attribute.
|
||||
* This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
|
||||
*
|
||||
* @param Name
|
||||
* Pointer to a string of 16-bit Unicode characters naming the attribute. Most often L"$I30".
|
||||
*
|
||||
* @param NameLength
|
||||
* The number of wide-characters in the name. L"$I30" Would use 4 here.
|
||||
*
|
||||
* @return
|
||||
* STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end
|
||||
* of the given file record, or if the file record isn't large enough for the attribute.
|
||||
*
|
||||
* @remarks
|
||||
* Only adding the attribute to the end of the file record is supported; AttributeAddress must
|
||||
* be of type AttributeEnd.
|
||||
* This could be improved by adding an $ATTRIBUTE_LIST to the file record if there's not enough space.
|
||||
*
|
||||
*/
|
||||
NTSTATUS
|
||||
AddBitmap(PNTFS_VCB Vcb,
|
||||
PFILE_RECORD_HEADER FileRecord,
|
||||
PNTFS_ATTR_RECORD AttributeAddress,
|
||||
PCWSTR Name,
|
||||
USHORT NameLength)
|
||||
{
|
||||
ULONG AttributeLength;
|
||||
// Calculate the header length
|
||||
ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
|
||||
ULONG FileRecordEnd = AttributeAddress->Length;
|
||||
ULONG NameOffset;
|
||||
ULONG ValueOffset;
|
||||
// We'll start out with 8 bytes of bitmap data
|
||||
ULONG ValueLength = 8;
|
||||
ULONG BytesAvailable;
|
||||
|
||||
if (AttributeAddress->Type != AttributeEnd)
|
||||
{
|
||||
DPRINT1("FIXME: Can only add $BITMAP attribute to the end of a file record.\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NameOffset = ResidentHeaderLength;
|
||||
|
||||
// Calculate ValueOffset, which will be aligned to a 4-byte boundary
|
||||
ValueOffset = ALIGN_UP_BY(NameOffset + (sizeof(WCHAR) * NameLength), VALUE_OFFSET_ALIGNMENT);
|
||||
|
||||
// Calculate length of attribute
|
||||
AttributeLength = ValueOffset + ValueLength;
|
||||
AttributeLength = ALIGN_UP_BY(AttributeLength, ATTR_RECORD_ALIGNMENT);
|
||||
|
||||
// Make sure the file record is large enough for the new attribute
|
||||
BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
|
||||
if (BytesAvailable < AttributeLength)
|
||||
{
|
||||
DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Set Attribute fields
|
||||
RtlZeroMemory(AttributeAddress, AttributeLength);
|
||||
|
||||
AttributeAddress->Type = AttributeBitmap;
|
||||
AttributeAddress->Length = AttributeLength;
|
||||
AttributeAddress->NameLength = NameLength;
|
||||
AttributeAddress->NameOffset = NameOffset;
|
||||
AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
|
||||
|
||||
AttributeAddress->Resident.ValueLength = ValueLength;
|
||||
AttributeAddress->Resident.ValueOffset = ValueOffset;
|
||||
|
||||
// Set the name
|
||||
RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
|
||||
|
||||
// move the attribute-end and file-record-end markers to the end of the file record
|
||||
AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
|
||||
SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name AddData
|
||||
* @implemented
|
||||
|
@ -258,6 +352,105 @@ AddFileName(PFILE_RECORD_HEADER FileRecord,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name AddIndexAllocation
|
||||
* @implemented
|
||||
*
|
||||
* Adds an $INDEX_ALLOCATION attribute to a given FileRecord.
|
||||
*
|
||||
* @param Vcb
|
||||
* Pointer to an NTFS_VCB for the destination volume.
|
||||
*
|
||||
* @param FileRecord
|
||||
* Pointer to a complete file record to add the attribute to.
|
||||
*
|
||||
* @param AttributeAddress
|
||||
* Pointer to the region of memory that will receive the $INDEX_ALLOCATION attribute.
|
||||
* This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
|
||||
*
|
||||
* @param Name
|
||||
* Pointer to a string of 16-bit Unicode characters naming the attribute. Most often, this will be L"$I30".
|
||||
*
|
||||
* @param NameLength
|
||||
* The number of wide-characters in the name. L"$I30" Would use 4 here.
|
||||
*
|
||||
* @return
|
||||
* STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end
|
||||
* of the given file record, or if the file record isn't large enough for the attribute.
|
||||
*
|
||||
* @remarks
|
||||
* Only adding the attribute to the end of the file record is supported; AttributeAddress must
|
||||
* be of type AttributeEnd.
|
||||
* This could be improved by adding an $ATTRIBUTE_LIST to the file record if there's not enough space.
|
||||
*
|
||||
*/
|
||||
NTSTATUS
|
||||
AddIndexAllocation(PNTFS_VCB Vcb,
|
||||
PFILE_RECORD_HEADER FileRecord,
|
||||
PNTFS_ATTR_RECORD AttributeAddress,
|
||||
PCWSTR Name,
|
||||
USHORT NameLength)
|
||||
{
|
||||
ULONG RecordLength;
|
||||
ULONG FileRecordEnd;
|
||||
ULONG NameOffset;
|
||||
ULONG DataRunOffset;
|
||||
ULONG BytesAvailable;
|
||||
|
||||
if (AttributeAddress->Type != AttributeEnd)
|
||||
{
|
||||
DPRINT1("FIXME: Can only add $INDEX_ALLOCATION attribute to the end of a file record.\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Calculate the name offset
|
||||
NameOffset = FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.CompressedSize);
|
||||
|
||||
// Calculate the offset to the first data run
|
||||
DataRunOffset = (sizeof(WCHAR) * NameLength) + NameOffset;
|
||||
// The data run offset must be aligned to a 4-byte boundary
|
||||
DataRunOffset = ALIGN_UP_BY(DataRunOffset, DATA_RUN_ALIGNMENT);
|
||||
|
||||
// Calculate the length of the new attribute; the empty data run will consist of a single byte
|
||||
RecordLength = DataRunOffset + 1;
|
||||
|
||||
// The size of the attribute itself must be aligned to an 8 - byte boundary
|
||||
RecordLength = ALIGN_UP_BY(RecordLength, ATTR_RECORD_ALIGNMENT);
|
||||
|
||||
// Back up the last 4-bytes of the file record (even though this value doesn't matter)
|
||||
FileRecordEnd = AttributeAddress->Length;
|
||||
|
||||
// Make sure the file record can contain the new attribute
|
||||
BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
|
||||
if (BytesAvailable < RecordLength)
|
||||
{
|
||||
DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Set fields of attribute header
|
||||
RtlZeroMemory(AttributeAddress, RecordLength);
|
||||
|
||||
AttributeAddress->Type = AttributeIndexAllocation;
|
||||
AttributeAddress->Length = RecordLength;
|
||||
AttributeAddress->IsNonResident = TRUE;
|
||||
AttributeAddress->NameLength = NameLength;
|
||||
AttributeAddress->NameOffset = NameOffset;
|
||||
AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
|
||||
|
||||
AttributeAddress->NonResident.MappingPairsOffset = DataRunOffset;
|
||||
AttributeAddress->NonResident.HighestVCN = (LONGLONG)-1;
|
||||
|
||||
// Set the name
|
||||
RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
|
||||
|
||||
// move the attribute-end and file-record-end markers to the end of the file record
|
||||
AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
|
||||
SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name AddIndexRoot
|
||||
* @implemented
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue