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/fi... ============================================================================== --- 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);