/* * COPYRIGHT: See COPYRIGHT.TXT * PROJECT: Ext2 File System Driver for WinNT/2K/XP * FILE: read.c * PROGRAMMER: Matt Wu * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */ /* INCLUDES *****************************************************************/ #include "ext2fs.h" /* GLOBALS ***************************************************************/ extern PEXT2_GLOBAL Ext2Global; /* DEFINITIONS *************************************************************/ NTSTATUS Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext); NTSTATUS Ext2ReadFile (IN PEXT2_IRP_CONTEXT IrpContext); NTSTATUS Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext); /* FUNCTIONS *************************************************************/ NTSTATUS Ext2CompleteIrpContext ( IN PEXT2_IRP_CONTEXT IrpContext, IN NTSTATUS Status ) { PIRP Irp = NULL; BOOLEAN bPrint; Irp = IrpContext->Irp; if (Irp != NULL) { if (NT_ERROR(Status)) { Irp->IoStatus.Information = 0; } Irp->IoStatus.Status = Status; bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); Ext2CompleteRequest( Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IrpContext->Irp = NULL; } Ext2FreeIrpContext(IrpContext); return Status; } NTSTATUS Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_VCB Vcb = NULL; PEXT2_CCB Ccb = NULL; PEXT2_FCBVCB FcbOrVcb = NULL; PFILE_OBJECT FileObject = NULL; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; LARGE_INTEGER ByteOffset; BOOLEAN PagingIo; BOOLEAN Nocache; BOOLEAN SynchronousIo; BOOLEAN MainResourceAcquired = FALSE; PUCHAR Buffer = NULL; EXT2_EXTENT BlockArray; _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); FileObject = IrpContext->FileObject; FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; ASSERT(FcbOrVcb); if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Ccb = (PEXT2_CCB) FileObject->FsContext2; Irp = IrpContext->Irp; Irp->IoStatus.Information = 0; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Read.Length; ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL); SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); if (PagingIo) { ASSERT(Nocache); } if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; _SEH2_LEAVE; } if (ByteOffset.QuadPart >= Vcb->PartitionInformation.PartitionLength.QuadPart ) { Irp->IoStatus.Information = 0; Status = STATUS_END_OF_FILE; _SEH2_LEAVE; } if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) { Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); } /* * User direct volume access */ if (Ccb != NULL && !PagingIo) { if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; _SEH2_LEAVE; } MainResourceAcquired = TRUE; if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) { if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { Ext2FlushVolume(IrpContext, Vcb, FALSE); } SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE); } ExReleaseResourceLite(&Vcb->MainResource); MainResourceAcquired = FALSE; /* will do Nocache i/o */ } /* * I/O to volume StreamObject */ if (!Nocache) { if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcMdlRead( Vcb->Volume, &ByteOffset, Length, &Irp->MdlAddress, &Irp->IoStatus ); Status = Irp->IoStatus.Status; } else { Buffer = Ext2GetUserBuffer(Irp); if (Buffer == NULL) { DbgBreak(); Status = STATUS_INVALID_USER_BUFFER; _SEH2_LEAVE; } if (!CcCopyRead( Vcb->Volume, &ByteOffset, Length, Ext2CanIWait(), Buffer, &Irp->IoStatus )) { Status = STATUS_PENDING; _SEH2_LEAVE; } Status = Irp->IoStatus.Status; } } else { Length &= ~((ULONG)SECTOR_SIZE - 1); Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoWriteAccess ); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } BlockArray.Irp = NULL; BlockArray.Lba = ByteOffset.QuadPart; BlockArray.Offset = 0; BlockArray.Length = Length; BlockArray.Next = NULL; Status = Ext2ReadWriteBlocks(IrpContext, Vcb, &BlockArray, Length ); Irp = IrpContext->Irp; if (!Irp) { _SEH2_LEAVE; } } } _SEH2_FINALLY { if (MainResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING && !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) { Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoWriteAccess ); if (NT_SUCCESS(Status)) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } else { if (NT_SUCCESS(Status)) { if (!PagingIo) { if (SynchronousIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } FileObject->Flags |= FO_FILE_FAST_IO_READ; } } Ext2CompleteIrpContext(IrpContext, Status);; } } else { Ext2FreeIrpContext(IrpContext); } } } _SEH2_END; return Status; } #define SafeZeroMemory(AT,BYTE_COUNT) { \ _SEH2_TRY { \ if (AT) \ RtlZeroMemory((AT), (BYTE_COUNT)); \ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ Ext2RaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \ } _SEH2_END; \ } NTSTATUS Ext2ReadInode ( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONGLONG Offset, IN PVOID Buffer, IN ULONG Size, IN BOOLEAN bDirectIo, OUT PULONG BytesRead ) { PEXT2_EXTENT Chain = NULL; PEXT2_EXTENT Extent = NULL, Prev = NULL; IO_STATUS_BLOCK IoStatus; NTSTATUS Status = STATUS_UNSUCCESSFUL; ULONG RealSize ; if (BytesRead) { *BytesRead = 0; } _SEH2_TRY { Ext2ReferMcb(Mcb); ASSERT((Mcb->Identifier.Type == EXT2MCB) && (Mcb->Identifier.Size == sizeof(EXT2_MCB))); if ((Mcb->Identifier.Type != EXT2MCB) || (Mcb->Identifier.Size != sizeof(EXT2_MCB))) { _SEH2_LEAVE; } if (Buffer == NULL && IrpContext != NULL) Buffer = Ext2GetUserBuffer(IrpContext->Irp); /* handle fast symlinks */ if (S_ISLNK(Mcb->Inode.i_mode) && 0 == Mcb->Inode.i_blocks) { PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]); if (!Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } if (Offset < EXT2_LINKLEN_IN_INODE) { if ((ULONG)Offset + Size >= EXT2_LINKLEN_IN_INODE) Size = EXT2_LINKLEN_IN_INODE - (ULONG)Offset - 1; RtlCopyMemory(Buffer, Data + (ULONG)Offset, Size); Status = STATUS_SUCCESS; } else { Status = STATUS_END_OF_FILE; } _SEH2_LEAVE; } // // Build the scatterred block ranges to be read // if (bDirectIo) { RealSize = CEILING_ALIGNED(ULONG, Size, SECTOR_SIZE - 1); } else { RealSize = Size; } Status = Ext2BuildExtents( IrpContext, Vcb, Mcb, Offset, RealSize, FALSE, &Chain ); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (Chain == NULL) { SafeZeroMemory((PCHAR)Buffer, Size); Status = STATUS_SUCCESS; _SEH2_LEAVE; } /* for sparse file, we need zero the gaps */ for (Extent = Chain; Buffer != NULL && Extent != NULL; Extent = Extent->Next) { if (NULL == Prev) { ASSERT(Extent == Chain); if (Extent->Offset) { SafeZeroMemory((PCHAR)Buffer, Extent->Offset); } } else if (Extent->Offset > (Prev->Offset + Prev->Length)) { SafeZeroMemory((PCHAR)Buffer + Prev->Offset + Prev->Length, Extent->Offset - Prev->Offset - Prev->Length); } if (NULL == Extent->Next) { if (Extent->Offset + Extent->Length < Size) { SafeZeroMemory((PCHAR)Buffer + Extent->Offset + Extent->Length, Size - Extent->Offset - Extent->Length); } } Prev = Extent; } if (bDirectIo) { ASSERT(IrpContext != NULL); // Offset should be SECTOR_SIZE aligned ... Status = Ext2ReadWriteBlocks( IrpContext, Vcb, Chain, Size ); } else { for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { if (!CcCopyRead( Vcb->Volume, (PLARGE_INTEGER)(&(Extent->Lba)), Extent->Length, PIN_WAIT, (PVOID)((PUCHAR)Buffer + Extent->Offset), &IoStatus )) { Status = STATUS_CANT_WAIT; } else { Status = IoStatus.Status; } if (!NT_SUCCESS(Status)) { break; } } } } _SEH2_FINALLY { if (Chain) { Ext2DestroyExtentChain(Chain); } Ext2DerefMcb(Mcb); } _SEH2_END; if (NT_SUCCESS(Status)) { if (BytesRead) *BytesRead = Size; } return Status; } NTSTATUS Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; PFILE_OBJECT FileObject = NULL; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; ULONG ReturnedLength = 0; LARGE_INTEGER ByteOffset; BOOLEAN OpPostIrp = FALSE; BOOLEAN PagingIo; BOOLEAN Nocache; BOOLEAN SynchronousIo; BOOLEAN MainResourceAcquired = FALSE; BOOLEAN PagingIoResourceAcquired = FALSE; PUCHAR Buffer; _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext; ASSERT(Fcb); ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); Ccb = (PEXT2_CCB) FileObject->FsContext2; Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Read.Length; ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE); SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); if (PagingIo) { ASSERT(Nocache); } DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache)); if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) || IsFileDeleted(Fcb->Mcb)) { Status = STATUS_FILE_DELETED; _SEH2_LEAVE; } if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && ByteOffset.HighPart == -1) { ByteOffset = FileObject->CurrentByteOffset; } if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; DbgBreak(); _SEH2_LEAVE; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; DbgBreak(); _SEH2_LEAVE; } ReturnedLength = Length; if (PagingIo) { if (!ExAcquireResourceSharedLite( &Fcb->PagingIoResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; _SEH2_LEAVE; } PagingIoResourceAcquired = TRUE; } else { if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject) { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; _SEH2_LEAVE; } MainResourceAcquired = TRUE; CcFlushCache(&Fcb->SectionObject, &ByteOffset, Length, &Irp->IoStatus ); if (!NT_SUCCESS(Irp->IoStatus.Status)) _SEH2_LEAVE; ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { ExReleaseResourceLite(&(Fcb->PagingIoResource)); } CcPurgeCacheSection( &Fcb->SectionObject, NULL, 0, FALSE ); ExConvertExclusiveToShared(&Fcb->MainResource); } else { if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; _SEH2_LEAVE; } MainResourceAcquired = TRUE; } if (!FsRtlCheckLockForReadAccess( &Fcb->FileLockAnchor, Irp )) { Status = STATUS_FILE_LOCK_CONFLICT; _SEH2_LEAVE; } } if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.FileSize.QuadPart) { if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) { Irp->IoStatus.Information = 0; Status = STATUS_END_OF_FILE; _SEH2_LEAVE; } ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); } if (!IsDirectory(Fcb) && Ccb != NULL) { Status = FsRtlCheckOplock( &Fcb->Oplock, Irp, IrpContext, Ext2OplockComplete, Ext2LockIrp ); if (Status != STATUS_SUCCESS) { OpPostIrp = TRUE; _SEH2_LEAVE; } // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } if (!Nocache) { if (IsDirectory(Fcb)) { _SEH2_LEAVE; } if (FileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap( FileObject, (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), FALSE, &Ext2Global->CacheManagerCallbacks, Fcb ); CcSetReadAheadGranularity( FileObject, READ_AHEAD_GRANULARITY ); } if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcMdlRead( FileObject, (&ByteOffset), ReturnedLength, &Irp->MdlAddress, &Irp->IoStatus ); Status = Irp->IoStatus.Status; } else { Buffer = Ext2GetUserBuffer(Irp); if (Buffer == NULL) { Status = STATUS_INVALID_USER_BUFFER; DbgBreak(); _SEH2_LEAVE; } if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength, Ext2CanIWait(), Buffer, &Irp->IoStatus)) { if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset, ReturnedLength, TRUE, Buffer, &Irp->IoStatus)) { Status = STATUS_PENDING; DbgBreak(); _SEH2_LEAVE; } } Status = Irp->IoStatus.Status; } } else { ULONG BytesRead = ReturnedLength; PUCHAR SystemVA = Ext2GetUserBuffer(IrpContext->Irp); if (ByteOffset.QuadPart + BytesRead > Fcb->Header.ValidDataLength.QuadPart) { if (ByteOffset.QuadPart >= Fcb->Header.ValidDataLength.QuadPart) { if (SystemVA) { SafeZeroMemory(SystemVA, Length); } Irp->IoStatus.Information = ReturnedLength; Status = STATUS_SUCCESS; _SEH2_LEAVE; } else { BytesRead = (ULONG)(Fcb->Header.ValidDataLength.QuadPart - ByteOffset.QuadPart); if (SystemVA) { SafeZeroMemory(SystemVA + BytesRead, Length - BytesRead); } } } Status = Ext2LockUserBuffer( IrpContext->Irp, BytesRead, IoReadAccess ); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } Status = Ext2ReadInode( IrpContext, Vcb, Fcb->Mcb, ByteOffset.QuadPart, NULL, BytesRead, TRUE, NULL ); /* we need re-queue this request in case STATUS_CANT_WAIT and fail it in other failure cases */ if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } /* pended by low level device */ if (Status == STATUS_PENDING) { IrpContext->Irp = Irp = NULL; _SEH2_LEAVE; } Irp = IrpContext->Irp; ASSERT(Irp); Status = Irp->IoStatus.Status; if (!NT_SUCCESS(Status)) { Ext2NormalizeAndRaiseStatus(IrpContext, Status); } } Irp->IoStatus.Information = ReturnedLength; } _SEH2_FINALLY { if (Irp) { if (PagingIoResourceAcquired) { ExReleaseResourceLite(&Fcb->PagingIoResource); } if (MainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } } if (!OpPostIrp && !IrpContext->ExceptionInProgress) { if (Irp) { if ( Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoWriteAccess ); if (NT_SUCCESS(Status)) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } else { if (NT_SUCCESS(Status)) { if (!PagingIo) { if (SynchronousIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } FileObject->Flags |= FO_FILE_FAST_IO_READ; } } Ext2CompleteIrpContext(IrpContext, Status); } } else { Ext2FreeIrpContext(IrpContext); } } } _SEH2_END; DEBUG(DL_IO, ("Ext2ReadFile: %wZ fetch at Off=%I64xh Len=%xh Paging=%xh Nocache=%xh Returned=%xh Status=%xh\n", &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache, ReturnedLength, Status)); return Status; } NTSTATUS Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFILE_OBJECT FileObject; PIRP Irp; _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); FileObject = IrpContext->FileObject; Irp = IrpContext->Irp; CcMdlReadComplete(FileObject, Irp->MdlAddress); Irp->MdlAddress = NULL; Status = STATUS_SUCCESS; } _SEH2_FINALLY { if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; } NTSTATUS Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status; PEXT2_VCB Vcb; PEXT2_FCBVCB FcbOrVcb; PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; BOOLEAN bCompleteRequest; ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); _SEH2_TRY { if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { Status = Ext2ReadComplete(IrpContext); bCompleteRequest = FALSE; } else { DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; bCompleteRequest = TRUE; _SEH2_LEAVE; } Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; if (Vcb->Identifier.Type != EXT2VCB || Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { Status = STATUS_INVALID_DEVICE_REQUEST; bCompleteRequest = TRUE; _SEH2_LEAVE; } FileObject = IrpContext->FileObject; if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && Vcb->LockFile != FileObject ) { Status = STATUS_ACCESS_DENIED; #ifdef __REACTOS__ bCompleteRequest = TRUE; #endif _SEH2_LEAVE; } FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; if (FcbOrVcb->Identifier.Type == EXT2VCB) { Status = Ext2ReadVolume(IrpContext); bCompleteRequest = FALSE; } else if (FcbOrVcb->Identifier.Type == EXT2FCB) { if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Status = STATUS_TOO_LATE; bCompleteRequest = TRUE; _SEH2_LEAVE; } Status = Ext2ReadFile(IrpContext); bCompleteRequest = FALSE; } else { DEBUG(DL_ERR, ( "Ext2Read: Inavlid FileObject (Vcb or Fcb corrupted)\n")); DbgBreak(); Status = STATUS_INVALID_PARAMETER; bCompleteRequest = TRUE; } } } _SEH2_FINALLY { if (bCompleteRequest) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }