Author: pschweitzer
Date: Mon Aug 24 08:36:58 2015
New Revision: 68808
URL:
http://svn.reactos.org/svn/reactos?rev=68808&view=rev
Log:
[NTFS]
Implement FileStreamInformation class for IRP_MJ_QUERY_INFORMATION.
It allows enumerating streams for a given file
Modified:
trunk/reactos/drivers/filesystems/ntfs/finfo.c
Modified: trunk/reactos/drivers/filesystems/ntfs/finfo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/f…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/finfo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/finfo.c [iso-8859-1] Mon Aug 24 08:36:58 2015
@@ -218,6 +218,74 @@
return STATUS_SUCCESS;
}
+static
+NTSTATUS
+NtfsGetSteamInformation(PNTFS_FCB Fcb,
+ PDEVICE_EXTENSION DeviceExt,
+ PFILE_STREAM_INFORMATION StreamInfo,
+ PULONG BufferLength)
+{
+ NTSTATUS Status;
+ ULONG CurrentSize;
+ PNTFS_ATTR_RECORD Attribute;
+ PFILE_RECORD_HEADER FileRecord;
+ PFILE_STREAM_INFORMATION CurrentInfo = StreamInfo, Previous = NULL;
+
+ if (*BufferLength < sizeof(FILE_STREAM_INFORMATION))
+ return STATUS_BUFFER_OVERFLOW;
+
+ FileRecord = ExAllocatePoolWithTag(NonPagedPool,
DeviceExt->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+ if (FileRecord == NULL)
+ {
+ DPRINT1("Not enough memory!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Status = ReadFileRecord(DeviceExt, Fcb->MFTIndex, FileRecord);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Can't find record!\n");
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return Status;
+ }
+
+ Status = STATUS_SUCCESS;
+ Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord +
FileRecord->AttributeOffset);
+ while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord +
FileRecord->BytesInUse) &&
+ Attribute->Type != AttributeEnd)
+ {
+ if (Attribute->Type == AttributeData)
+ {
+ CurrentSize = FIELD_OFFSET(FILE_STREAM_INFORMATION, StreamName) +
Attribute->NameLength * sizeof(WCHAR);
+
+ if (CurrentSize > *BufferLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ CurrentInfo->NextEntryOffset = 0;
+ CurrentInfo->StreamNameLength = Attribute->NameLength * sizeof(WCHAR);
+ CurrentInfo->StreamSize.QuadPart = AttributeDataLength(Attribute);
+ CurrentInfo->StreamAllocationSize.QuadPart =
AttributeAllocatedLength(Attribute);
+ RtlMoveMemory(CurrentInfo->StreamName, (PWCHAR)((ULONG_PTR)Attribute +
Attribute->NameOffset), CurrentInfo->StreamNameLength);
+
+ if (Previous != NULL)
+ {
+ Previous->NextEntryOffset = (ULONG_PTR)CurrentInfo -
(ULONG_PTR)Previous;
+ }
+ Previous = CurrentInfo;
+ CurrentInfo = (PFILE_STREAM_INFORMATION)((ULONG_PTR)CurrentInfo +
CurrentSize);
+ *BufferLength -= CurrentSize;
+ }
+
+ Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
+ }
+
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return Status;
+}
+
/*
* FUNCTION: Retrieve the specified file information
*/
@@ -296,6 +364,13 @@
&BufferLength);
break;
+ case FileStreamInformation:
+ Status = NtfsGetSteamInformation(Fcb,
+ DeviceObject->DeviceExtension,
+ SystemBuffer,
+ &BufferLength);
+ break;
+
case FileAlternateNameInformation:
case FileAllInformation:
DPRINT1("Unimplemented information class %u\n",
FileInformationClass);