/* FUNCTIONS ****************************************************************/
-/**
-* @name NtfsAddFilenameToDirectory
-* @implemented
-*
-* Adds a $FILE_NAME attribute to a given directory index.
-*
-* @param DeviceExt
-* Points to the target disk's DEVICE_EXTENSION.
-*
-* @param DirectoryMftIndex
-* Mft index of the parent directory which will receive the file.
-*
-* @param FileReferenceNumber
-* File reference of the file to be added to the directory. This is a combination of the
-* Mft index and sequence number.
-*
-* @param FilenameAttribute
-* Pointer to the FILENAME_ATTRIBUTE of the file being added to the directory.
-*
-* @return
-* STATUS_SUCCESS on success.
-* STATUS_INSUFFICIENT_RESOURCES if an allocation fails.
-* STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record.
-*
-* @remarks
-* WIP - Can only support an empty directory.
-* One FILENAME_ATTRIBUTE is added to the directory's index for each link to that file. So, each
-* file which contains one FILENAME_ATTRIBUTE for a long name and another for the 8.3 name, will
-* get both attributes added to its parent directory.
-*/
-NTSTATUS
-NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
- ULONGLONG DirectoryMftIndex,
- ULONGLONG FileReferenceNumber,
- PFILENAME_ATTRIBUTE FilenameAttribute)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- PFILE_RECORD_HEADER ParentFileRecord;
- PNTFS_ATTR_CONTEXT IndexRootContext;
- PINDEX_ROOT_ATTRIBUTE I30IndexRoot;
- ULONG IndexRootOffset;
- ULONGLONG I30IndexRootLength;
- PINDEX_ENTRY_ATTRIBUTE IndexNodeEntry;
- ULONG LengthWritten;
- PNTFS_ATTR_RECORD DestinationAttribute;
- PINDEX_ROOT_ATTRIBUTE NewIndexRoot;
- ULONG AttributeLength;
- PNTFS_ATTR_RECORD NextAttribute;
-
- // Allocate memory for the parent directory
- ParentFileRecord = ExAllocatePoolWithTag(NonPagedPool,
- DeviceExt->NtfsInfo.BytesPerFileRecord,
- TAG_NTFS);
- if (!ParentFileRecord)
- {
- DPRINT1("ERROR: Couldn't allocate memory for file record!\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- // Open the parent directory
- Status = ReadFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
- if (!NT_SUCCESS(Status))
- {
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- DPRINT1("ERROR: Couldn't read parent directory with index %I64u\n",
- DirectoryMftIndex);
- return Status;
- }
-
- DPRINT1("Dumping old parent file record:\n");
- NtfsDumpFileRecord(DeviceExt, ParentFileRecord);
-
- // Find the index root attribute for the directory
- Status = FindAttribute(DeviceExt,
- ParentFileRecord,
- AttributeIndexRoot,
- L"$I30",
- 4,
- &IndexRootContext,
- &IndexRootOffset);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ERROR: Couldn't find $I30 $INDEX_ROOT attribute for parent directory with MFT #: %I64u!\n",
- DirectoryMftIndex);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return Status;
- }
-
- I30IndexRootLength = AttributeDataLength(&IndexRootContext->Record);
-
- // Allocate memory for the index root data
- I30IndexRoot = (PINDEX_ROOT_ATTRIBUTE)ExAllocatePoolWithTag(NonPagedPool, I30IndexRootLength, TAG_NTFS);
- if (!I30IndexRoot)
- {
- DPRINT1("ERROR: Couldn't allocate memory for index root attribute!\n");
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- }
-
- // Read the Index Root
- Status = ReadAttribute(DeviceExt, IndexRootContext, 0, (PCHAR)I30IndexRoot, I30IndexRootLength);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ERROR: Couln't read index root attribute for Mft index #%I64u\n", DirectoryMftIndex);
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return Status;
- }
-
- // Make sure it's empty (temporarily)
- IndexNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)I30IndexRoot + I30IndexRoot->Header.FirstEntryOffset + 0x10);
- if (IndexNodeEntry->Data.Directory.IndexedFile != 0 || IndexNodeEntry->Flags != 2)
- {
- DPRINT1("FIXME: File-creation is only supported in empty directories right now! Be patient! :)\n");
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return STATUS_NOT_IMPLEMENTED;
- }
-
- // Now we need to setup a new index root attribute to replace the old one
- NewIndexRoot = ExAllocatePoolWithTag(NonPagedPool, DeviceExt->NtfsInfo.BytesPerIndexRecord, TAG_NTFS);
- if (!NewIndexRoot)
- {
- DPRINT1("ERROR: Unable to allocate memory for new index root attribute!\n");
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- // Setup the new index record
- RtlZeroMemory(NewIndexRoot, DeviceExt->NtfsInfo.BytesPerIndexRecord); // shouldn't be necessary but aids in debugging
-
- NewIndexRoot->AttributeType = AttributeFileName;
- NewIndexRoot->CollationRule = COLLATION_FILE_NAME;
- NewIndexRoot->SizeOfEntry = DeviceExt->NtfsInfo.BytesPerIndexRecord;
- // If Bytes per index record is less than cluster size, clusters per index record becomes sectors per index
- if(NewIndexRoot->SizeOfEntry < DeviceExt->NtfsInfo.BytesPerCluster)
- NewIndexRoot->ClustersPerIndexRecord = NewIndexRoot->SizeOfEntry / DeviceExt->NtfsInfo.BytesPerSector;
- else
- NewIndexRoot->ClustersPerIndexRecord = NewIndexRoot->SizeOfEntry / DeviceExt->NtfsInfo.BytesPerCluster;
-
- // Setup the Index node header
- NewIndexRoot->Header.FirstEntryOffset = 0x10;
- NewIndexRoot->Header.Flags = INDEX_ROOT_SMALL;
- // still need to calculate sizes
-
- // The first index node entry will be for the filename we're adding
- IndexNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)NewIndexRoot + NewIndexRoot->Header.FirstEntryOffset + 0x10);
- IndexNodeEntry->Data.Directory.IndexedFile = FileReferenceNumber;
- IndexNodeEntry->Flags = INDEX_ROOT_SMALL;
- IndexNodeEntry->KeyLength = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + (2 * FilenameAttribute->NameLength);
- IndexNodeEntry->Length = ALIGN_UP_BY(IndexNodeEntry->KeyLength, 8) + FIELD_OFFSET(INDEX_ENTRY_ATTRIBUTE, FileName);
-
- // Now we can calculate the Node length (temp logic)
- NewIndexRoot->Header.TotalSizeOfEntries = NewIndexRoot->Header.FirstEntryOffset + IndexNodeEntry->Length + 0x10;
- NewIndexRoot->Header.AllocatedSize = NewIndexRoot->Header.TotalSizeOfEntries;
-
- DPRINT1("New Index Node Entry Stream Length: %u\nNew Inde Node Entry Length: %u\n",
- IndexNodeEntry->KeyLength,
- IndexNodeEntry->Length);
-
- // copy over the attribute proper
- RtlCopyMemory(&IndexNodeEntry->FileName, FilenameAttribute, IndexNodeEntry->KeyLength);
-
- // Now setup the dummy key
- IndexNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexNodeEntry + IndexNodeEntry->Length);
-
- IndexNodeEntry->Data.Directory.IndexedFile = 0;
- IndexNodeEntry->Length = 0x10;
- IndexNodeEntry->KeyLength = 0;
- IndexNodeEntry->Flags = NTFS_INDEX_ENTRY_END;
-
- // This is when we'd normally setup the length (already done above)
-
- // Write back the new index root attribute to the parent directory file record
-
- // First, we need to make sure the attribute is large enough.
- // We can't set the size as we normally would, because if we extend past the file record,
- // 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);
-
- 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);
-
- Status = UpdateFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ERROR: Failed to update file record of directory with index: %llx\n", DirectoryMftIndex);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- return Status;
- }
-
- // Update the parent directory with the new index root
- Status = WriteAttribute(DeviceExt,
- IndexRootContext,
- 0,
- (PUCHAR)NewIndexRoot,
- AttributeLength,
- &LengthWritten);
- if (!NT_SUCCESS(Status) )
- {
- DPRINT1("ERROR: Unable to write new index root attribute to parent directory!\n");
- ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return Status;
- }
-
- // re-read the parent file record, so we can dump it
- Status = ReadFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ERROR: Couldn't read parent directory after messing with it!\n");
- }
- else
- {
- DPRINT1("Dumping new parent file record:\n");
- NtfsDumpFileRecord(DeviceExt, ParentFileRecord);
- }
-
- // Cleanup
- ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
- ReleaseAttributeContext(IndexRootContext);
- ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
- ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
-
- return Status;
-}
-
ULONGLONG
NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext, NULL);
if (NT_SUCCESS(Status))
{
- Size = AttributeDataLength(&DataContext->Record);
- Allocated = AttributeAllocatedLength(&DataContext->Record);
+ Size = AttributeDataLength(DataContext->pRecord);
+ Allocated = AttributeAllocatedLength(DataContext->pRecord);
ReleaseAttributeContext(DataContext);
}
static NTSTATUS
-NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
- PFILE_RECORD_HEADER FileRecord,
- ULONGLONG MFTIndex,
- PFILE_NAMES_INFORMATION Info,
- ULONG BufferLength)
+NtfsGetNamesInformation(PDEVICE_EXTENSION DeviceExt,
+ PFILE_RECORD_HEADER FileRecord,
+ ULONGLONG MFTIndex,
+ PFILE_NAMES_INFORMATION Info,
+ ULONG BufferLength)
{
ULONG Length;
PFILENAME_ATTRIBUTE FileName;
- DPRINT("NtfsGetNameInformation() called\n");
+ DPRINT("NtfsGetNamesInformation() called\n");
FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
&FileRecord,
&MFTRecord,
Fcb->MFTIndex,
- (Stack->Flags & SL_CASE_SENSITIVE));
+ BooleanFlagOn(Stack->Flags, SL_CASE_SENSITIVE));
if (NT_SUCCESS(Status))
{
switch (FileInformationClass)
{
- case FileNameInformation:
- Status = NtfsGetNameInformation(DeviceExtension,
- FileRecord,
- MFTRecord,
- (PFILE_NAMES_INFORMATION)Buffer,
- BufferLength);
+ case FileNamesInformation:
+ Status = NtfsGetNamesInformation(DeviceExtension,
+ FileRecord,
+ MFTRecord,
+ (PFILE_NAMES_INFORMATION)Buffer,
+ BufferLength);
break;
case FileDirectoryInformation: