NTSTATUS VfatRead( PVFAT_IRP_CONTEXT IrpContext) { NTSTATUS Status; PVFATFCB Fcb; ULONG Length = 0; ULONG ReturnedLength = 0; PERESOURCE Resource = NULL; LARGE_INTEGER ByteOffset; PVOID Buffer; ULONG BytesPerSector; ASSERT(IrpContext); DPRINT("VfatRead(IrpContext %p)\n", IrpContext); ASSERT(IrpContext->DeviceObject); // This request is not allowed on the main device object if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) { DPRINT("VfatRead is called with the main device object.\n"); Status = STATUS_INVALID_DEVICE_REQUEST; goto ByeBye; } ASSERT(IrpContext->DeviceExt); ASSERT(IrpContext->FileObject); Fcb = IrpContext->FileObject->FsContext; ASSERT(Fcb); if (Fcb->Flags & FCB_IS_PAGE_FILE) { PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo; IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector; IoSkipCurrentIrpStackLocation(IrpContext->Irp); DPRINT("Read from page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart); Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp); VfatFreeIrpContext(IrpContext); return Status; } DPRINT("<%wZ>\n", &Fcb->PathNameU); ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset; Length = IrpContext->Stack->Parameters.Read.Length; BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector; /* fail if file is a directory and no paged read */ if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO)) { Status = STATUS_INVALID_PARAMETER; goto ByeBye; } DPRINT("'%wZ', Offset: %u, Length %u\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length); if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME)) { Status = STATUS_INVALID_PARAMETER; goto ByeBye; } if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart) { IrpContext->Irp->IoStatus.Information = 0; Status = STATUS_END_OF_FILE; goto ByeBye; } if (IrpContext->Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME)) { if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0) { DPRINT("%u %u\n", ByteOffset.u.LowPart, Length); // non cached read must be sector aligned Status = STATUS_INVALID_PARAMETER; goto ByeBye; } } if (Length == 0) { IrpContext->Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; goto ByeBye; } if (Fcb->Flags & FCB_IS_VOLUME) { Resource = &IrpContext->DeviceExt->DirResource; } else if (IrpContext->Irp->Flags & IRP_PAGING_IO) { Resource = &Fcb->PagingIoResource; } else { Resource = &Fcb->MainResource; } if (!ExAcquireResourceSharedLite(Resource, IrpContext->Flags & IRPCONTEXT_CANWAIT ? TRUE : FALSE)) { Resource = NULL; Status = STATUS_PENDING; goto ByeBye; } if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) && FsRtlAreThereCurrentFileLocks(&Fcb->FileLock)) { if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp)) { Status = STATUS_FILE_LOCK_CONFLICT; goto ByeBye; } } Buffer = VfatGetUserBuffer(IrpContext->Irp); if (!Buffer) { Status = STATUS_INVALID_USER_BUFFER; goto ByeBye; } if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) && !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME))) { // cached read Status = STATUS_SUCCESS; if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart) { Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart; Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS; } _SEH2_TRY { if (IrpContext->FileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap(IrpContext->FileObject, (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), FALSE, &(VfatGlobalData->CacheMgrCallbacks), Fcb); } if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length, (IrpContext->Flags & IRPCONTEXT_CANWAIT) != 0, Buffer, &IrpContext->Irp->IoStatus)) { ASSERT((IrpContext->Flags & IRPCONTEXT_CANWAIT) == 0); Status = STATUS_PENDING; goto ByeBye; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); goto ByeBye; } _SEH2_END; if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status)) { Status = IrpContext->Irp->IoStatus.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; __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 ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) || IsFileDeleted(Fcb->Mcb)) { Status = STATUS_FILE_DELETED; __leave; } if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; DbgBreak(); __leave; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; DbgBreak(); __leave; } if (!PagingIo && Nocache && (FileObject->SectionObjectPointer->DataSectionObject != NULL)) { CcFlushCache( FileObject->SectionObjectPointer, &ByteOffset, Length, &Irp->IoStatus ); if (!NT_SUCCESS(Irp->IoStatus.Status)) { __leave; } } ReturnedLength = Length; if (PagingIo) { if (!ExAcquireResourceSharedLite( &Fcb->PagingIoResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; } else { if (Nocache) { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; } else { if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; } if (!FsRtlCheckLockForReadAccess( &Fcb->FileLockAnchor, Irp )) { Status = STATUS_FILE_LOCK_CONFLICT; __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; __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; __leave; } // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } if (!Nocache) { if (IsDirectory(Fcb)) { __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(); __leave; } if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength, Ext2CanIWait(), Buffer, &Irp->IoStatus)) { if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset, ReturnedLength, TRUE, Buffer, &Irp->IoStatus)) { Status = STATUS_PENDING; DbgBreak(); __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; __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)) { __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)) { __leave; } /* pended by low level device */ if (Status == STATUS_PENDING) { IrpContext->Irp = Irp = NULL; __leave; } Irp = IrpContext->Irp; ASSERT(Irp); Status = Irp->IoStatus.Status; if (!NT_SUCCESS(Status)) { Ext2NormalizeAndRaiseStatus(IrpContext, Status); } } Irp->IoStatus.Information = ReturnedLength; } __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); } } } 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 DokanDispatchRead(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) /*++ Routine Description: This device control dispatcher handles read IRPs. Arguments: DeviceObject - Context for the activity. Irp - The device control argument block. Return Value: NTSTATUS --*/ { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; ULONG bufferLength; LARGE_INTEGER byteOffset; NTSTATUS status = STATUS_INVALID_PARAMETER; ULONG readLength = 0; PDokanCCB ccb; PDokanFCB fcb = NULL; PDokanVCB vcb; PVOID currentAddress = NULL; PEVENT_CONTEXT eventContext; ULONG eventLength; BOOLEAN fcbLocked = FALSE; BOOLEAN isPagingIo = FALSE; BOOLEAN isSynchronousIo = FALSE; BOOLEAN noCache = FALSE; __try { DDbgPrint("==> DokanRead\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; // // If this is a zero length read then return SUCCESS immediately. // if (irpSp->Parameters.Read.Length == 0) { DDbgPrint(" Parameters.Read.Length == 0 \n"); Irp->IoStatus.Information = 0; status = STATUS_SUCCESS; __leave; } if (irpSp->MinorFunction == IRP_MN_COMPLETE) { Irp->MdlAddress = NULL; status = STATUS_SUCCESS; __leave; } if (fileObject == NULL && Irp->MdlAddress != NULL) { DDbgPrint(" Reads by File System Recognizers\n"); currentAddress = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress); if (currentAddress == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } // here we could return the bootsector. If we don't have one // the requested read lenght must be returned as requested readLength = irpSp->Parameters.Read.Length; status = STATUS_SUCCESS; __leave; } if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_INVALID_DEVICE_REQUEST; __leave; } vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_INVALID_DEVICE_REQUEST; __leave; } bufferLength = irpSp->Parameters.Read.Length; if (irpSp->Parameters.Read.ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && irpSp->Parameters.Read.ByteOffset.HighPart == -1) { // irpSp->Parameters.Read.ByteOffset == NULL don't need check? DDbgPrint("use FileObject ByteOffset\n"); byteOffset = fileObject->CurrentByteOffset; } else { byteOffset = irpSp->Parameters.Read.ByteOffset; } DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); DDbgPrint(" ByteCount:%lu ByteOffset:%I64d\n", bufferLength, byteOffset.QuadPart); if (bufferLength == 0) { status = STATUS_SUCCESS; readLength = 0; __leave; } // make a MDL for UserBuffer that can be used later on another thread // context if (Irp->MdlAddress == NULL) { status = DokanAllocateMdl(Irp, irpSp->Parameters.Read.Length); if (!NT_SUCCESS(status)) { __leave; } } ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) { DDbgPrint(" DOKAN_FILE_DIRECTORY %p\n", fcb); status = STATUS_INVALID_PARAMETER; __leave; } if (Irp->Flags & IRP_PAGING_IO) { isPagingIo = TRUE; } if (fileObject->Flags & FO_SYNCHRONOUS_IO) { isSynchronousIo = TRUE; } if (Irp->Flags & IRP_NOCACHE) { noCache = TRUE; } if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) && (fileObject->SectionObjectPointer->DataSectionObject != NULL)) { ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE); CcFlushCache(&fcb->SectionObjectPointers, &irpSp->Parameters.Read.ByteOffset, irpSp->Parameters.Read.Length, NULL); ExReleaseResourceLite(&fcb->PagingIoResource); } DokanFCBLockRO(fcb); fcbLocked = TRUE; // length of EventContext is sum of file name length and itself eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } eventContext->Context = ccb->UserContext; // DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); if (isPagingIo) { DDbgPrint(" Paging IO\n"); eventContext->FileFlags |= DOKAN_PAGING_IO; } if (isSynchronousIo) { DDbgPrint(" Synchronous IO\n"); eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO; } if (noCache) { DDbgPrint(" Nocache\n"); eventContext->FileFlags |= DOKAN_NOCACHE; } // offset of file to read eventContext->Operation.Read.ByteOffset = byteOffset; // buffer size for read // user-mode file system application can return this size eventContext->Operation.Read.BufferLength = irpSp->Parameters.Read.Length; // copy the accessed file name eventContext->Operation.Read.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.Read.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // // We now check whether we can proceed based on the state of // the file oplocks. // if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) { // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking. status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, DokanOplockComplete, DokanPrePostIrp); // // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // if (status != STATUS_SUCCESS) { if (status == STATUS_PENDING) { DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); } else { DokanFreeEventContext(eventContext); } __leave; } // // We have to check for read access according to the current // state of the file locks, and set FileSize from the Fcb. // // FsRtlCheckLockForReadAccess does not block. if (!FsRtlCheckLockForReadAccess(&fcb->FileLock, Irp)) { status = STATUS_FILE_LOCK_CONFLICT; __leave; } } // register this IRP to pending IPR list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { if(fcbLocked) DokanFCBUnlock(fcb); DokanCompleteIrpRequest(Irp, status, readLength); DDbgPrint("<== DokanRead\n"); } return status; }
NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); UINT8* data; PFILE_OBJECT FileObject = IrpSp->FileObject; fcb* fcb = FileObject->FsContext; UINT64 start; ULONG length, bytes_read; NTSTATUS Status; BOOL top_level; FsRtlEnterFileSystem(); top_level = is_top_level(Irp); TRACE("read\n"); Irp->IoStatus.Information = 0; if (IrpSp->MinorFunction & IRP_MN_COMPLETE) { CcMdlReadComplete(IrpSp->FileObject, Irp->MdlAddress); Irp->MdlAddress = NULL; Status = STATUS_SUCCESS; bytes_read = 0; goto exit; } start = IrpSp->Parameters.Read.ByteOffset.QuadPart; length = IrpSp->Parameters.Read.Length; bytes_read = 0; if (!fcb || !fcb->Vcb || !fcb->subvol) { Status = STATUS_INTERNAL_ERROR; // FIXME - invalid param error? goto exit; } TRACE("file = %S (fcb = %p)\n", file_desc(FileObject), fcb); TRACE("offset = %llx, length = %x\n", start, length); TRACE("paging_io = %s, no cache = %s\n", Irp->Flags & IRP_PAGING_IO ? "TRUE" : "FALSE", Irp->Flags & IRP_NOCACHE ? "TRUE" : "FALSE"); if (fcb->type == BTRFS_TYPE_DIRECTORY) { Status = STATUS_INVALID_DEVICE_REQUEST; goto exit; } if (!(Irp->Flags & IRP_PAGING_IO) && !FsRtlCheckLockForReadAccess(&fcb->lock, Irp)) { WARN("tried to read locked region\n"); Status = STATUS_FILE_LOCK_CONFLICT; goto exit; } if (length == 0) { WARN("tried to read zero bytes\n"); Status = STATUS_SUCCESS; goto exit; } if (start >= fcb->Header.FileSize.QuadPart) { TRACE("tried to read with offset after file end (%llx >= %llx)\n", start, fcb->Header.FileSize.QuadPart); Status = STATUS_END_OF_FILE; goto exit; } TRACE("FileObject %p fcb %p FileSize = %llx st_size = %llx (%p)\n", FileObject, fcb, fcb->Header.FileSize.QuadPart, fcb->inode_item.st_size, &fcb->inode_item.st_size); // int3; if (Irp->Flags & IRP_NOCACHE || !(IrpSp->MinorFunction & IRP_MN_MDL)) { data = map_user_buffer(Irp); if (Irp->MdlAddress && !data) { ERR("MmGetSystemAddressForMdlSafe returned NULL\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto exit; } if (length + start > fcb->Header.ValidDataLength.QuadPart) { RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), length - (fcb->Header.ValidDataLength.QuadPart - start)); length = fcb->Header.ValidDataLength.QuadPart - start; } } if (!(Irp->Flags & IRP_NOCACHE)) { BOOL wait; Status = STATUS_SUCCESS; _SEH2_TRY { if (!FileObject->PrivateCacheMap) { CC_FILE_SIZES ccfs; ccfs.AllocationSize = fcb->Header.AllocationSize; ccfs.FileSize = fcb->Header.FileSize; ccfs.ValidDataLength = fcb->Header.ValidDataLength; TRACE("calling CcInitializeCacheMap (%llx, %llx, %llx)\n", ccfs.AllocationSize.QuadPart, ccfs.FileSize.QuadPart, ccfs.ValidDataLength.QuadPart); CcInitializeCacheMap(FileObject, &ccfs, FALSE, cache_callbacks, FileObject); CcSetReadAheadGranularity(FileObject, READ_AHEAD_GRANULARITY); } // FIXME - uncomment this when async is working // wait = IoIsOperationSynchronous(Irp) ? TRUE : FALSE; wait = TRUE; if (IrpSp->MinorFunction & IRP_MN_MDL) { CcMdlRead(FileObject,&IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus); } else { TRACE("CcCopyRead(%p, %llx, %x, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus); TRACE("sizes = %llx, %llx, %llx\n", fcb->Header.AllocationSize, fcb->Header.FileSize, fcb->Header.ValidDataLength); if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) { TRACE("CcCopyRead failed\n"); IoMarkIrpPending(Irp); Status = STATUS_PENDING; goto exit; } TRACE("CcCopyRead finished\n"); } } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (NT_SUCCESS(Status)) { Status = Irp->IoStatus.Status; bytes_read = Irp->IoStatus.Information; } else ERR("EXCEPTION - %08x\n", Status); } else {