Author: pschweitzer Date: Sun Nov 2 19:55:22 2014 New Revision: 65192
URL: http://svn.reactos.org/svn/reactos?rev=65192&view=rev Log: [NTFS] Quickly implement NtfsReadFile().
By quickly, I mean that it works but is under optimal in many ways, and also doesn't support any caching. So, don't expect breaking performances.
BUUUUUUT... This implements reading a file on a NTFS volume on ReactOS! And it works! Here is a picture of all the achievements of ReactOS with NTFS lately: http://www.heisspiter.net/~Pierre/rostests/NTFS_all.png -> Volume information -> Displaying files in explorer -> Moving across directories -> Reading a file (with more here)
That's all folks! (for now ;-))
Modified: trunk/reactos/drivers/filesystems/ntfs/rw.c
Modified: trunk/reactos/drivers/filesystems/ntfs/rw.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/rw... ============================================================================== --- trunk/reactos/drivers/filesystems/ntfs/rw.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/ntfs/rw.c [iso-8859-1] Sun Nov 2 19:55:22 2014 @@ -52,84 +52,116 @@ ULONG IrpFlags, PULONG LengthRead) { -#if 0 - NTSTATUS Status = STATUS_SUCCESS; - PUCHAR TempBuffer; - ULONG TempLength; - PCCB Ccb; - PFCB Fcb; - - DPRINT("CdfsReadFile(ReadOffset %lu Length %lu)\n", ReadOffset, Length); - - *LengthRead = 0; - - if (Length == 0) - return(STATUS_SUCCESS); - - Ccb = (PCCB)FileObject->FsContext2; - Fcb = (PFCB)FileObject->FsContext; - - if (ReadOffset >= Fcb->Entry.DataLengthL) - return(STATUS_END_OF_FILE); - - DPRINT("Reading %d bytes at %d\n", Length, ReadOffset); - - if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO))) - { - LARGE_INTEGER FileOffset; - IO_STATUS_BLOCK IoStatus; - - if (ReadOffset + Length > Fcb->Entry.DataLengthL) - Length = Fcb->Entry.DataLengthL - ReadOffset; - if (FileObject->PrivateCacheMap == NULL) - { - CcRosInitializeFileCache(FileObject, PAGE_SIZE); - } - - FileOffset.QuadPart = (LONGLONG)ReadOffset; - CcCopyRead(FileObject, - &FileOffset, - Length, - TRUE, - Buffer, - &IoStatus); - *LengthRead = IoStatus.Information; - - return(IoStatus.Status); - } - - if ((ReadOffset % BLOCKSIZE) != 0 || (Length % BLOCKSIZE) != 0) - { - return STATUS_INVALID_PARAMETER; - } - if (ReadOffset + Length > ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE)) - Length = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE) - ReadOffset; - - Status = CdfsReadSectors(DeviceExt->StorageDevice, - Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE), - Length / BLOCKSIZE, - Buffer); - if (NT_SUCCESS(Status)) - { - *LengthRead = Length; - if (Length + ReadOffset > Fcb->Entry.DataLengthL) - { - memset(Buffer + Fcb->Entry.DataLengthL - ReadOffset, - 0, Length + ReadOffset - Fcb->Entry.DataLengthL); - } - } - - return(Status); -#else - UNREFERENCED_PARAMETER(DeviceExt); - UNREFERENCED_PARAMETER(FileObject); - UNREFERENCED_PARAMETER(Buffer); - UNREFERENCED_PARAMETER(Length); - UNREFERENCED_PARAMETER(ReadOffset); - UNREFERENCED_PARAMETER(IrpFlags); + NTSTATUS Status = STATUS_SUCCESS; + PNTFS_FCB Fcb; + PFILE_RECORD_HEADER FileRecord; + PNTFS_ATTR_CONTEXT DataContext; + ULONG RealLength; + ULONG RealReadOffset; + ULONG RealLengthRead; + ULONG ToRead; + BOOLEAN AllocatedBuffer = FALSE; + PCHAR ReadBuffer = (PCHAR)Buffer; + + DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt, FileObject, Buffer, Length, ReadOffset, IrpFlags, LengthRead); + *LengthRead = 0; - return STATUS_END_OF_FILE; -#endif + + if (Length == 0) + { + DPRINT1("Null read!\n"); + return STATUS_SUCCESS; + } + + Fcb = (PNTFS_FCB)FileObject->FsContext; + + if (ReadOffset >= Fcb->Entry.AllocatedSize) + { + DPRINT1("Reading beyond file end!\n"); + return STATUS_END_OF_FILE; + } + + ToRead = Length; + if (ReadOffset + Length > Fcb->Entry.AllocatedSize) + ToRead = Fcb->Entry.AllocatedSize - ReadOffset; + + RealReadOffset = ReadOffset; + RealLength = ToRead; + + if ((ReadOffset % DeviceExt->NtfsInfo.BytesPerSector) != 0 || (ToRead % DeviceExt->NtfsInfo.BytesPerSector) != 0) + { + RealReadOffset = ROUND_DOWN(ReadOffset, DeviceExt->NtfsInfo.BytesPerSector); + RealLength = ROUND_UP(ToRead, DeviceExt->NtfsInfo.BytesPerSector); + + ReadBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength + DeviceExt->NtfsInfo.BytesPerSector, TAG_NTFS); + if (ReadBuffer == NULL) + { + DPRINT1("Not enough memory!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + AllocatedBuffer = TRUE; + } + + 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 = FindAttribute(DeviceExt, FileRecord, AttributeData, L"", 0, &DataContext); + if (!NT_SUCCESS(Status)) + { + DPRINT1("No data associated with file!\n"); + ExFreePoolWithTag(FileRecord, TAG_NTFS); + return Status; + } + + DPRINT1("Effective read: %lu at %lu\n", RealLength, RealReadOffset); + RealLengthRead = ReadAttribute(DeviceExt, DataContext, RealReadOffset, (PCHAR)ReadBuffer, RealLength); + if (RealLengthRead != RealLength) + { + DPRINT1("Read failure!\n"); + ReleaseAttributeContext(DataContext); + ExFreePoolWithTag(FileRecord, TAG_NTFS); + if (AllocatedBuffer) + { + ExFreePoolWithTag(ReadBuffer, TAG_NTFS); + } + return Status; + } + + ReleaseAttributeContext(DataContext); + ExFreePoolWithTag(FileRecord, TAG_NTFS); + + *LengthRead = ToRead; + + DPRINT1("%lu got read\n", *LengthRead); + + if (AllocatedBuffer) + { + RtlCopyMemory(Buffer, ReadBuffer + (ReadOffset - RealReadOffset), ToRead); + } + + if (ToRead != Length) + { + RtlZeroMemory(Buffer + ToRead, Length - ToRead); + } + + if (AllocatedBuffer) + { + ExFreePoolWithTag(ReadBuffer, TAG_NTFS); + } + + return STATUS_SUCCESS; }