mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[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 ;-)) svn path=/trunk/; revision=65192
This commit is contained in:
parent
6ea5fe3e43
commit
ffa40006ae
1 changed files with 107 additions and 75 deletions
|
@ -52,84 +52,116 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt,
|
|||
ULONG IrpFlags,
|
||||
PULONG LengthRead)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PUCHAR TempBuffer;
|
||||
ULONG TempLength;
|
||||
PCCB Ccb;
|
||||
PFCB Fcb;
|
||||
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;
|
||||
|
||||
DPRINT("CdfsReadFile(ReadOffset %lu Length %lu)\n", ReadOffset, Length);
|
||||
DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt, FileObject, Buffer, Length, ReadOffset, IrpFlags, LengthRead);
|
||||
|
||||
*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);
|
||||
*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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue