https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5579428b4f1361481dae3…
commit 5579428b4f1361481dae3ea0b901c0a915401148
Author: Trevor Thompson <tmt256(a)email.vccs.edu>
AuthorDate: Thu Jul 27 18:22:24 2017 +0000
[NTFS] - Add some utility functions and improve some comments. Improve
NtfsAddFilenameToDirectory().
+PrintAllVCNs() - Diagnostic function which prints VCN of every node in an index
allocation.
+GetAllocationOffsetFromVCN() - Calculates location of an index buffer from the
node's VCN.
+GetInfoClassName() - Gets a string representation of an info class enumeration, to
speed up development of unimplemented classes.
-NtfsSetInformation() & NtfsQueryInformation() - Use GetInfoClassName to report
unhandled information classes.
-CompareTreeKeys() - Add a comment and clarify some comments.
-NtfsAddFilenameToDirectory() - Don't try to update the size of Index Root on disk
if the attribute length hasn't changed.
svn path=/branches/GSoC_2016/NTFS/; revision=75424
---
drivers/filesystems/ntfs/btree.c | 46 +++++++++++++-
drivers/filesystems/ntfs/finfo.c | 128 ++++++++++++++++++++++++++++++++++++++-
drivers/filesystems/ntfs/mft.c | 38 ++++++------
drivers/filesystems/ntfs/ntfs.h | 16 +++++
4 files changed, 206 insertions(+), 22 deletions(-)
diff --git a/drivers/filesystems/ntfs/btree.c b/drivers/filesystems/ntfs/btree.c
index a7eacb3173..38fa9aefee 100644
--- a/drivers/filesystems/ntfs/btree.c
+++ b/drivers/filesystems/ntfs/btree.c
@@ -32,6 +32,47 @@
/* FUNCTIONS ****************************************************************/
+// TEMP FUNCTION for diagnostic purposes.
+// Prints VCN of every node in an index allocation
+VOID
+PrintAllVCNs(PDEVICE_EXTENSION Vcb,
+ PNTFS_ATTR_CONTEXT IndexAllocationContext,
+ ULONG NodeSize)
+{
+ ULONGLONG CurrentOffset = 0;
+ PINDEX_BUFFER CurrentNode, Buffer;
+ ULONGLONG BufferSize = AttributeDataLength(&IndexAllocationContext->Record);
+ ULONGLONG i;
+ int Count = 0;
+
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, TAG_NTFS);
+
+ ULONG BytesRead = ReadAttribute(Vcb, IndexAllocationContext, 0, (PCHAR)Buffer,
BufferSize);
+
+ ASSERT(BytesRead = BufferSize);
+
+ CurrentNode = Buffer;
+
+ // loop through all the nodes
+ for (i = 0; i < BufferSize; i += NodeSize)
+ {
+ NTSTATUS Status = FixupUpdateSequenceArray(Vcb, &CurrentNode->Ntfs);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ERROR: Fixing fixup failed!\n");
+ continue;
+ }
+
+ DPRINT1("Node #%d, VCN: %I64u\n", Count, CurrentNode->VCN);
+
+ CurrentNode = (PINDEX_BUFFER)((ULONG_PTR)CurrentNode + NodeSize);
+ CurrentOffset += NodeSize;
+ Count++;
+ }
+
+ ExFreePoolWithTag(Buffer, TAG_NTFS);
+}
+
/**
* @name CompareTreeKeys
* @implemented
@@ -62,6 +103,7 @@ CompareTreeKeys(PB_TREE_KEY Key1, PB_TREE_KEY Key2, BOOLEAN
CaseSensitive)
UNICODE_STRING Key1Name, Key2Name;
LONG Comparison;
+ // Key1 must not be the final key (AKA the dummy key)
ASSERT(!(Key1->IndexEntry->Flags & NTFS_INDEX_ENTRY_END));
// If Key2 is the "dummy key", key 1 will always come first
@@ -89,7 +131,7 @@ CompareTreeKeys(PB_TREE_KEY Key1, PB_TREE_KEY Key2, BOOLEAN
CaseSensitive)
// Compare the names of the same length
Comparison = RtlCompareUnicodeString(&Key1Name, &Key2Name,
!CaseSensitive);
- // If the truncated files are the same length, the shorter one comes first
+ // If the truncated names are the same length, the shorter one comes first
if (Comparison == 0)
return -1;
}
@@ -102,7 +144,7 @@ CompareTreeKeys(PB_TREE_KEY Key1, PB_TREE_KEY Key2, BOOLEAN
CaseSensitive)
// Compare the names of the same length
Comparison = RtlCompareUnicodeString(&Key1Name, &Key2Name,
!CaseSensitive);
- // If the truncated files are the same length, the shorter one comes first
+ // If the truncated names are the same length, the shorter one comes first
if (Comparison == 0)
return 1;
}
diff --git a/drivers/filesystems/ntfs/finfo.c b/drivers/filesystems/ntfs/finfo.c
index 323b85cf45..aee8aa51e2 100644
--- a/drivers/filesystems/ntfs/finfo.c
+++ b/drivers/filesystems/ntfs/finfo.c
@@ -289,6 +289,128 @@ NtfsGetSteamInformation(PNTFS_FCB Fcb,
return Status;
}
+// Convert enum value to friendly name
+const PCSTR
+GetInfoClassName(FILE_INFORMATION_CLASS infoClass)
+{
+ const PCSTR fileInfoClassNames[] = { "???????",
+ "FileDirectoryInformation",
+ "FileFullDirectoryInformation",
+ "FileBothDirectoryInformation",
+ "FileBasicInformation",
+ "FileStandardInformation",
+ "FileInternalInformation",
+ "FileEaInformation",
+ "FileAccessInformation",
+ "FileNameInformation",
+ "FileRenameInformation",
+ "FileLinkInformation",
+ "FileNamesInformation",
+ "FileDispositionInformation",
+ "FilePositionInformation",
+ "FileFullEaInformation",
+ "FileModeInformation",
+ "FileAlignmentInformation",
+ "FileAllInformation",
+ "FileAllocationInformation",
+ "FileEndOfFileInformation",
+ "FileAlternateNameInformation",
+ "FileStreamInformation",
+ "FilePipeInformation",
+ "FilePipeLocalInformation",
+ "FilePipeRemoteInformation",
+ "FileMailslotQueryInformation",
+ "FileMailslotSetInformation",
+ "FileCompressionInformation",
+ "FileObjectIdInformation",
+ "FileCompletionInformation",
+ "FileMoveClusterInformation",
+ "FileQuotaInformation",
+ "FileReparsePointInformation",
+ "FileNetworkOpenInformation",
+ "FileAttributeTagInformation",
+ "FileTrackingInformation",
+ "FileIdBothDirectoryInformation",
+ "FileIdFullDirectoryInformation",
+ "FileValidDataLengthInformation",
+ "FileShortNameInformation",
+ "FileIoCompletionNotificationInformation",
+ "FileIoStatusBlockRangeInformation",
+ "FileIoPriorityHintInformation",
+ "FileSfioReserveInformation",
+ "FileSfioVolumeInformation",
+ "FileHardLinkInformation",
+ "FileProcessIdsUsingFileInformation",
+ "FileNormalizedNameInformation",
+ "FileNetworkPhysicalNameInformation",
+ "FileIdGlobalTxDirectoryInformation",
+ "FileIsRemoteDeviceInformation",
+ "FileAttributeCacheInformation",
+ "FileNumaNodeInformation",
+ "FileStandardLinkInformation",
+ "FileRemoteProtocolInformation",
+ "FileReplaceCompletionInformation",
+ "FileMaximumInformation",
+ "FileDirectoryInformation",
+ "FileFullDirectoryInformation",
+ "FileBothDirectoryInformation",
+ "FileBasicInformation",
+ "FileStandardInformation",
+ "FileInternalInformation",
+ "FileEaInformation",
+ "FileAccessInformation",
+ "FileNameInformation",
+ "FileRenameInformation",
+ "FileLinkInformation",
+ "FileNamesInformation",
+ "FileDispositionInformation",
+ "FilePositionInformation",
+ "FileFullEaInformation",
+ "FileModeInformation",
+ "FileAlignmentInformation",
+ "FileAllInformation",
+ "FileAllocationInformation",
+ "FileEndOfFileInformation",
+ "FileAlternateNameInformation",
+ "FileStreamInformation",
+ "FilePipeInformation",
+ "FilePipeLocalInformation",
+ "FilePipeRemoteInformation",
+ "FileMailslotQueryInformation",
+ "FileMailslotSetInformation",
+ "FileCompressionInformation",
+ "FileObjectIdInformation",
+ "FileCompletionInformation",
+ "FileMoveClusterInformation",
+ "FileQuotaInformation",
+ "FileReparsePointInformation",
+ "FileNetworkOpenInformation",
+ "FileAttributeTagInformation",
+ "FileTrackingInformation",
+ "FileIdBothDirectoryInformation",
+ "FileIdFullDirectoryInformation",
+ "FileValidDataLengthInformation",
+ "FileShortNameInformation",
+ "FileIoCompletionNotificationInformation",
+ "FileIoStatusBlockRangeInformation",
+ "FileIoPriorityHintInformation",
+ "FileSfioReserveInformation",
+ "FileSfioVolumeInformation",
+ "FileHardLinkInformation",
+ "FileProcessIdsUsingFileInformation",
+ "FileNormalizedNameInformation",
+ "FileNetworkPhysicalNameInformation",
+ "FileIdGlobalTxDirectoryInformation",
+ "FileIsRemoteDeviceInformation",
+ "FileAttributeCacheInformation",
+ "FileNumaNodeInformation",
+ "FileStandardLinkInformation",
+ "FileRemoteProtocolInformation",
+ "FileReplaceCompletionInformation",
+ "FileMaximumInformation" };
+ return fileInfoClassNames[infoClass];
+}
+
/*
* FUNCTION: Retrieve the specified file information
*/
@@ -376,12 +498,12 @@ NtfsQueryInformation(PNTFS_IRP_CONTEXT IrpContext)
case FileAlternateNameInformation:
case FileAllInformation:
- DPRINT1("Unimplemented information class %u\n",
FileInformationClass);
+ DPRINT1("Unimplemented information class: %s\n",
GetInfoClassName(FileInformationClass));
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
- DPRINT1("Unimplemented information class %u\n",
FileInformationClass);
+ DPRINT1("Unimplemented information class: %s\n",
GetInfoClassName(FileInformationClass));
Status = STATUS_INVALID_PARAMETER;
}
@@ -645,7 +767,7 @@ NtfsSetInformation(PNTFS_IRP_CONTEXT IrpContext)
// TODO: all other information classes
default:
- DPRINT1("FIXME: Unimplemented information class %u\n",
FileInformationClass);
+ DPRINT1("FIXME: Unimplemented information class: %s\n",
GetInfoClassName(FileInformationClass));
Status = STATUS_NOT_IMPLEMENTED;
}
diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c
index 72953c0086..928839edd7 100644
--- a/drivers/filesystems/ntfs/mft.c
+++ b/drivers/filesystems/ntfs/mft.c
@@ -2018,25 +2018,29 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
// we must create an index allocation and index bitmap (TODO). Also TODO: support
file records with
// $ATTRIBUTE_LIST's.
AttributeLength = NewIndexRoot->Header.AllocatedSize +
FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header);
- DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)ParentFileRecord +
IndexRootOffset);
-
- // Find the attribute (or attribute-end marker) after the index root
- NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute +
DestinationAttribute->Length);
- if (NextAttribute->Type != AttributeEnd)
+
+ if (AttributeLength != IndexRootContext->Record.Resident.ValueLength)
{
- DPRINT1("FIXME: For now, only resizing index root at the end of a file
record is supported!\n");
- ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return STATUS_NOT_IMPLEMENTED;
- }
+ DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)ParentFileRecord +
IndexRootOffset);
- // Update the length of the attribute in the file record of the parent directory
- InternalSetResidentAttributeLength(IndexRootContext,
- ParentFileRecord,
- IndexRootOffset,
- AttributeLength);
+ // Find the attribute (or attribute-end marker) after the index root
+ NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute +
DestinationAttribute->Length);
+ if (NextAttribute->Type != AttributeEnd)
+ {
+ DPRINT1("FIXME: For now, only resizing index root at the end of a file
record is supported!\n");
+ ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ // Update the length of the attribute in the file record of the parent directory
+ InternalSetResidentAttributeLength(IndexRootContext,
+ ParentFileRecord,
+ IndexRootOffset,
+ AttributeLength);
+ }
NT_ASSERT(ParentFileRecord->BytesInUse <=
DeviceExt->NtfsInfo.BytesPerFileRecord);
diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h
index 9cbc4d5485..39c33210fc 100644
--- a/drivers/filesystems/ntfs/ntfs.h
+++ b/drivers/filesystems/ntfs/ntfs.h
@@ -208,6 +208,9 @@ typedef enum
#define INDEX_ROOT_SMALL 0x0
#define INDEX_ROOT_LARGE 0x1
+#define INDEX_NODE_SMALL 0x0
+#define INDEX_NODE_LARGE 0x1
+
#define NTFS_INDEX_ENTRY_NODE 1
#define NTFS_INDEX_ENTRY_END 2
@@ -700,9 +703,22 @@ CreateIndexRootFromBTree(PDEVICE_EXTENSION DeviceExt,
VOID
DestroyBTree(PB_TREE Tree);
+VOID
+DestroyBTreeNode(PB_TREE_FILENAME_NODE Node);
+
VOID
DumpBTree(PB_TREE Tree);
+VOID
+DumpBTreeNode(PB_TREE_FILENAME_NODE Node,
+ ULONG Number,
+ ULONG Depth);
+
+ULONGLONG
+GetAllocationOffsetFromVCN(PDEVICE_EXTENSION DeviceExt,
+ ULONG IndexBufferSize,
+ ULONGLONG Vcn);
+
NTSTATUS
NtfsInsertKey(ULONGLONG FileReference,
PFILENAME_ATTRIBUTE FileNameAttribute,