⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (!NT_SUCCESS(Status)) {
        goto errorout;
    }

    if (blocks <= 0) {
        Status = STATUS_SUCCESS;
        goto errorout;
    }

	
	{
	  ULONGLONG bufferPos = 0;

      for(i = 0, j = 0; i < blocks; i++) {
		  if ( // The block is needed for the user's requested contents
			   // (The user's requested offset lies within the block, or the block's start is within the user's requested range)
			  ( (Offset >= Bdl[i].Offset) && (Offset < (Bdl[i].Offset + Bdl[i].Length)) ) ||		// The user's offset is within the block's range
			  ( (Bdl[i].Offset >= Offset) && (Bdl[i].Offset < (Offset + Size)) )					// The block's offset is within the user's range
		      )
		  {
			  ULONGLONG	offsetFromDisk	= Bdl[i].Lba;			  
			  ULONGLONG	lengthToRead	= min(Size - bufferPos, Bdl[i].Length);
			  j++;

			  //KdPrint(("Rfsd: blocks = %u, i = %u, j = %u\n", blocks, i, j));
			  //KdPrint(("Rfsd: Bdl[%u].Lba = %I64u, Bdl[%u].Offset = %I64u, Bdl[%u].Length = %u\n", i, Bdl[i].Lba, i, Bdl[i].Offset, i, Bdl[i].Length));
			  //KdPrint(("Rfsd: offsetFromDisk = %I64u, lengthToRead = %I64u\n", offsetFromDisk, lengthToRead));
			  //KdPrint(("Rfsd: Buffer = %p, bufferPos = %I64u\n", Buffer, bufferPos));

			  IoStatus.Information = 0;				

			  RfsdCopyRead(
					  Vcb->StreamObj, 
					  (PLARGE_INTEGER) (&offsetFromDisk),	// offset (relative to partition)
					  (ULONG) lengthToRead,					// length to read
					  PIN_WAIT,								// 
					  (PVOID)((PUCHAR)Buffer + bufferPos),	// buffer to read into
					  &IoStatus   );

			  Status = IoStatus.Status;
			  bufferPos += IoStatus.Information;
			  //KdPrint(("Rfsd: IoStatus.Status = %#x, IoStatus.Information = %u\n", IoStatus.Status, IoStatus.Information));
		  }
      }

	}

errorout:

    if (Bdl)				ExFreePool(Bdl);

    if (NT_SUCCESS(Status)) {

        if (dwRet) *dwRet = Size;
    }

    return Status;
}


NTSTATUS
RfsdReadFile(IN PRFSD_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PRFSD_VCB           Vcb;
    PRFSD_FCB           Fcb;
    PRFSD_CCB           Ccb;
    PFILE_OBJECT        FileObject;
    PFILE_OBJECT        CacheObject;

    PDEVICE_OBJECT      DeviceObject;

    PIRP                Irp;
    PIO_STACK_LOCATION  IoStackLocation;

    ULONG               Length;
    ULONG               ReturnedLength;
    LARGE_INTEGER       ByteOffset;

    BOOLEAN             PagingIo;
    BOOLEAN             Nocache;
    BOOLEAN             SynchronousIo;
    BOOLEAN             MainResourceAcquired = FALSE;
    BOOLEAN             PagingIoResourceAcquired = FALSE;

    PUCHAR              Buffer;

    __try {

        ASSERT(IrpContext);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
    
        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);
        
        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
            (Vcb->Identifier.Size == sizeof(RFSD_VCB)));
        
        FileObject = IrpContext->FileObject;
        
        Fcb = (PRFSD_FCB) FileObject->FsContext;
        
        ASSERT(Fcb);
    
        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
            (Fcb->Identifier.Size == sizeof(RFSD_FCB)));		

        Ccb = (PRFSD_CCB) FileObject->FsContext2;

        Irp = IrpContext->Irp;
        
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
        
        Length = IoStackLocation->Parameters.Read.Length;
        ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
        
		KdPrint(("$$$ " __FUNCTION__ " on key: %x,%xh to read %i bytes at the offset %xh in the file\n", 
			Fcb->RfsdMcb->Key.k_dir_id, Fcb->RfsdMcb->Key.k_objectid,
			Length, ByteOffset.QuadPart));

        PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
        Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
        SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

/*
        if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
            Status = STATUS_FILE_DELETED;
            __leave;
        }

        if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
            Status = STATUS_DELETE_PENDING;
            __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) {
            if (!ExAcquireResourceSharedLite(
                &Fcb->MainResource,
                IrpContext->IsSynchronous )) {
                Status = STATUS_PENDING;
                __leave;
            }
            
            MainResourceAcquired = TRUE;

            if (!FsRtlCheckLockForReadAccess(
                &Fcb->FileLockAnchor,
                Irp         )) {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }
        } else {
            if (!ExAcquireResourceSharedLite(
                &Fcb->PagingIoResource,
                IrpContext->IsSynchronous )) {
                Status = STATUS_PENDING;
                __leave;
            }
            
            PagingIoResourceAcquired = TRUE;
        }
        
		if (!Nocache) {
			// Attempt cached access...

            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;
                }

                Length =
                    (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);

            }

            ReturnedLength = Length;

            if (IsDirectory(Fcb)) {
                __leave;
            }

            {
                if (FileObject->PrivateCacheMap == NULL) {
                    CcInitializeCacheMap(
                        FileObject,
                        (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
                        FALSE,
                        &RfsdGlobal->CacheManagerCallbacks,
                        Fcb );
                }

                CacheObject = FileObject;
            }

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
                CcMdlRead(
                    CacheObject,
                    (&ByteOffset),
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );
                
                Status = Irp->IoStatus.Status;

            } else {
                Buffer = RfsdGetUserBuffer(Irp);
                
                if (Buffer == NULL) {
                    Status = STATUS_INVALID_USER_BUFFER;
                    DbgBreak();
                    __leave;
                }
                
                if (!CcCopyRead(
                    CacheObject,						// the file object (representing the open operation performed by the thread)
                    (PLARGE_INTEGER)&ByteOffset,		// starting offset IN THE FILE, from where the read should be performed
                    Length,								// number of bytes requested in the read operation
                    IrpContext->IsSynchronous,
                    Buffer,								// < buffer to read the contents to
                    &Irp->IoStatus )) {
                    Status = STATUS_PENDING;
                    DbgBreak();
                    __leave;
                }
                
                Status = Irp->IoStatus.Status;
            }

        } else {
			// Attempt access without the cache...

            if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.AllocationSize.QuadPart) {

                if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
                    Irp->IoStatus.Information = 0;
                    Status = STATUS_END_OF_FILE;
                    DbgBreak();
                    __leave;
                }

                Length =
                     (ULONG)(Fcb->Header.AllocationSize.QuadPart- ByteOffset.QuadPart);
            }

            ReturnedLength = Length;

            /* lock the user buffer into MDL and make them paged-in */
            Status = RfsdLockUserBuffer(
                        IrpContext->Irp,
                        Length,
                        IoWriteAccess );
                
            if (NT_SUCCESS(Status)) {

                /* Zero the total buffer */
                PVOID SystemVA = RfsdGetUserBuffer(IrpContext->Irp);
                if (SystemVA) {

                    RtlZeroMemory(SystemVA, Length);

                    RfsdPrint((DBG_INFO, "RfsdReadFile: Zero read buffer: Offset=%I64xh Size=%xh ... \n",
                               ByteOffset.QuadPart, Length));
                }

            } else {
                __leave;
            }

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = Length;

            
            Status = RfsdReadInode(
                        IrpContext,
                        Vcb,
                        &(Fcb->RfsdMcb->Key),
                        Fcb->Inode,
                        ByteOffset.QuadPart,
                        RfsdGetUserBuffer(IrpContext->Irp),		//  NOTE: Ext2fsd just passes NULL for the buffer, and relies on the initial cache call to retrieve tha data.  We'll instead be explicitly putting it into the user's buffer, via a much different mechanism.
                        Length,
                        &ReturnedLength);

            Irp = IrpContext->Irp;

        }

    } __finally {

        if (PagingIoResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->PagingIoResource,
                ExGetCurrentResourceThread());
        }
        
        if (MainResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread());
        }
        
        if (!IrpContext->ExceptionInProgress) {
            if (Irp) {
                if (Status == STATUS_PENDING) {

                    Status = RfsdLockUserBuffer(
                        IrpContext->Irp,
                        Length,
                        IoWriteAccess );
                    
                    if (NT_SUCCESS(Status)) {
                        Status = RfsdQueueRequest(IrpContext);
                    } else {
                        RfsdCompleteIrpContext(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;
                        }
                    }

                    RfsdCompleteIrpContext(IrpContext, Status);
                }
            } else {
                RfsdFreeIrpContext(IrpContext);
            }
        }
    }
    
    return Status;

}

NTSTATUS
RfsdReadComplete (IN PRFSD_IRP_CONTEXT IrpContext)
{
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;
    PFILE_OBJECT    FileObject;
    PIRP            Irp;
    
    __try {

        ASSERT(IrpContext);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        FileObject = IrpContext->FileObject;
        
        Irp = IrpContext->Irp;
        
        CcMdlReadComplete(FileObject, Irp->MdlAddress);
        
        Irp->MdlAddress = NULL;
        
        Status = STATUS_SUCCESS;

    } __finally {

        if (!IrpContext->ExceptionInProgress) {
            RfsdCompleteIrpContext(IrpContext, Status);
        }
    }
    
    return Status;
}


NTSTATUS
RfsdRead (IN PRFSD_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status;
    PRFSD_VCB           Vcb;
    PRFSD_FCBVCB        FcbOrVcb;
    PDEVICE_OBJECT      DeviceObject;
    PFILE_OBJECT        FileObject;
    BOOLEAN             bCompleteRequest;
    
    ASSERT(IrpContext);
    
    ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
        (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));

    __try {

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
			// Caller wants to tell the Cache Manager that a previously allocated MDL can be freed.
            Status =  RfsdReadComplete(IrpContext);
            bCompleteRequest = FALSE;

        } else {

            DeviceObject = IrpContext->DeviceObject;

            if (DeviceObject == RfsdGlobal->DeviceObject) {
                Status = STATUS_INVALID_DEVICE_REQUEST;
                bCompleteRequest = TRUE;
                __leave;
            }

            Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;

            if (Vcb->Identifier.Type != RFSDVCB ||
                Vcb->Identifier.Size != sizeof(RFSD_VCB) ) {
                Status = STATUS_INVALID_DEVICE_REQUEST;
                bCompleteRequest = TRUE;

                __leave;
            }

            if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {

                Status = STATUS_TOO_LATE;
                bCompleteRequest = TRUE;
                __leave;
            }

            FileObject = IrpContext->FileObject;
            
            FcbOrVcb = (PRFSD_FCBVCB) FileObject->FsContext;

            if (FcbOrVcb->Identifier.Type == RFSDVCB) {
                Status = RfsdReadVolume(IrpContext);
                bCompleteRequest = FALSE;
            } else if (FcbOrVcb->Identifier.Type == RFSDFCB) {
                Status = RfsdReadFile(IrpContext);
                bCompleteRequest = FALSE;
            } else {
                RfsdPrint((DBG_ERROR, "RfsdRead: INVALID PARAMETER ... \n"));
                DbgBreak();

                Status = STATUS_INVALID_PARAMETER;
                bCompleteRequest = TRUE;
            }
        }

    } __finally {
        if (bCompleteRequest) {
            RfsdCompleteIrpContext(IrpContext, Status);
        }
    }
    
    return Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -