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

📄 write.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 3 页
字号:
                    &Irp->MdlAddress,
                    &Irp->IoStatus );
                
                Status = Irp->IoStatus.Status;

            } else {

                Buffer = RfsdGetUserBuffer(Irp);
                    
                if (Buffer == NULL) {
                    DbgBreak();

                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

                if (!CcCopyWrite( Vcb->StreamObj,
                                  (PLARGE_INTEGER)(&ByteOffset),
                                  Length,
                                  TRUE,
                                  Buffer )) {
                    Status = STATUS_PENDING;
                    __leave;
                }

                Status = Irp->IoStatus.Status;
                RfsdAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
            }

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
            }

        } else {

            PRFSD_BDL           rfsd_bdl = NULL;
            ULONG               Blocks = 0;

            LONGLONG            DirtyStart;
            LONGLONG            DirtyLba;
            LONGLONG            DirtyLength;
            LONGLONG            RemainLength;

            if ((ByteOffset.QuadPart + Length) >
                    Vcb->PartitionInformation.PartitionLength.QuadPart ) {
                Length = (ULONG) (
                    Vcb->PartitionInformation.PartitionLength.QuadPart -
                    ByteOffset.QuadPart);

                Length &= ~((ULONG)SECTOR_SIZE - 1);
            }

            Status = RfsdLockUserBuffer(
                IrpContext->Irp,
                Length,
                IoReadAccess );
                
            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            rfsd_bdl = ExAllocatePool( PagedPool, 
                                       (Length / Vcb->BlockSize) *
                                       sizeof(RFSD_BDL) );

            if (!rfsd_bdl) {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }

            DirtyLba = ByteOffset.QuadPart;
            RemainLength = (LONGLONG) Length;

            while (RemainLength > 0) {

                DirtyStart = DirtyLba;

                if (RfsdLookupMcbEntry( Vcb, 
                                        DirtyStart,
                                        &DirtyLba,
                                        &DirtyLength,
                                        (PLONGLONG)NULL,
                                        (PLONGLONG)NULL,
                                        (PULONG)NULL) ) {

                    if (DirtyLba == -1) {
                        DirtyLba = DirtyStart + DirtyLength;

                        RemainLength = ByteOffset.QuadPart + 
                                       (LONGLONG)Length -
                                       DirtyLba;
                        continue;
                    }
            
                    rfsd_bdl[Blocks].Irp = NULL;
                    rfsd_bdl[Blocks].Lba = DirtyLba;
                    rfsd_bdl[Blocks].Offset = (ULONG)( (LONGLONG)Length +
                                                       DirtyStart -
                                                       RemainLength - 
                                                       DirtyLba );

                    if (DirtyLba + DirtyLength > DirtyStart + RemainLength) {
                        rfsd_bdl[Blocks].Length = (ULONG)( DirtyStart +
                                                           RemainLength -
                                                           DirtyLba );
                        RemainLength = 0;
                    } else {
                        rfsd_bdl[Blocks].Length = (ULONG)DirtyLength;
                        RemainLength =  (DirtyStart + RemainLength) -
                                        (DirtyLba + DirtyLength);
                    }

                    DirtyLba = DirtyStart + DirtyLength;
                    Blocks++;

                } else {

                    if (Blocks == 0) {

                        if (rfsd_bdl)
                            ExFreePool(rfsd_bdl);

                        //
                        // Lookup fails at the first time, ie. 
                        // no dirty blocks in the run
                        //

                        DbgBreak();

                        if (RemainLength == (LONGLONG)Length)
                            Status = STATUS_SUCCESS;
                        else
                            Status = STATUS_UNSUCCESSFUL;

                        __leave;

                    } else {
                        break;
                    }
                }
            }

            if (Blocks > 0) {

                Status = RfsdReadWriteBlocks(IrpContext,
                                    Vcb,
                                    rfsd_bdl,
                                    Length,
                                    Blocks,
                                    FALSE   );
                Irp = IrpContext->Irp;

                if (NT_SUCCESS(Status)) {
                    ULONG   i;

                    for (i=0; i<Blocks;i++) {
                        RfsdRemoveMcbEntry( Vcb,
                                            rfsd_bdl[i].Lba,
                                            rfsd_bdl[i].Length );
                    }
                }

                if (rfsd_bdl)
                    ExFreePool(rfsd_bdl);

                if (!Irp)
                    __leave;

            } else {

                if (rfsd_bdl)
                    ExFreePool(rfsd_bdl);

                Irp->IoStatus.Information = Length;
    
                Status = STATUS_SUCCESS;
                __leave;
            }
        }
    } __finally {

        if (PagingIoResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->PagingIoResource,
                ExGetCurrentResourceThread());
        }
        
        if (MainResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread());
        }

        if (!IrpContext->ExceptionInProgress) {
            if (Irp) {
                if (Status == STATUS_PENDING) {
                    if(!bDeferred) {
                        Status = RfsdLockUserBuffer(
                            IrpContext->Irp,
                            Length,
                            IoReadAccess );
                    
                        if (NT_SUCCESS(Status)) {
                            Status = RfsdQueueRequest(IrpContext);
                        } else {
                            RfsdCompleteIrpContext(IrpContext, Status);
                        }
                    }

                } else {

                    if (NT_SUCCESS(Status)) {
                        if (SynchronousIo && !PagingIo) {
                            FileObject->CurrentByteOffset.QuadPart =
                                ByteOffset.QuadPart + Irp->IoStatus.Information;
                        }

                        if (!PagingIo) {
                            SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                        }
                    }

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

    return Status;
}

NTSTATUS
RfsdWriteInode (
    IN PRFSD_IRP_CONTEXT    IrpContext,
    IN PRFSD_VCB            Vcb,
    IN ULONG                InodeNo,
    IN PRFSD_INODE          Inode,
    IN ULONGLONG            Offset,
    IN PVOID                Buffer,
    IN ULONG                Size,
    IN BOOLEAN              bWriteToDisk,
    OUT PULONG              dwRet
    )
{
    PRFSD_BDL       rfsd_bdl = NULL;
    ULONG           blocks, i;
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;

    ULONGLONG       FileSize;
    ULONGLONG       AllocSize;

    BOOLEAN         bAlloc = FALSE;

    if (dwRet) {
        *dwRet = 0;
    }

    //
    // For file/non pagingio, we support the allocation on writing.
    //

    if (S_ISREG(Inode->i_mode)) {

        if (!(IrpContext->Irp->Flags  & IRP_PAGING_IO)) {
            bAlloc = TRUE;
        }
    }

    //
    // Initialize the FileSize / AllocationSize ...
    //

    FileSize  = (ULONGLONG) Inode->i_size;
    if (S_ISREG(Inode->i_mode))
        FileSize |= ((ULONGLONG)(Inode->i_size_high) << 32);
    AllocSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);


    //
    // Check the inputed parameters ...
    //

    if (!bAlloc) {

        if (Offset >= AllocSize) {
            RfsdPrint((DBG_ERROR, "RfsdWritenode: beyond the file range.\n"));
            return STATUS_SUCCESS;
        }

        if (Offset + Size > AllocSize) {
            Size = (ULONG)(AllocSize - Offset);
        }
    }

    Status = RfsdBuildBDL (
                IrpContext,
                Vcb,
                InodeNo,
                Inode,
                Offset,
                Size,
                bAlloc,
                &rfsd_bdl,
                &blocks
                );

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

    if (bWriteToDisk) {

        //
        // We assume the offset is aligned.
        //

        Status = RfsdReadWriteBlocks(
                    IrpContext,
                    Vcb,
                    rfsd_bdl,
                    Size,
                    blocks,
                    FALSE
                    );

    } else {

        for(i = 0; i < blocks; i++) {

            if( !RfsdSaveBuffer(
                    IrpContext,
                    Vcb,
                    rfsd_bdl[i].Lba,
                    rfsd_bdl[i].Length,
                    (PVOID)((PUCHAR)Buffer + rfsd_bdl[i].Offset)
                   )) {
                goto errorout;
            }
        }

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

            RfsdPrint((DBG_USER, "RfsdWriteInode is starting FlushingDpc...\n"));
            RfsdStartFloppyFlushDpc(Vcb, NULL, NULL);
        }

        Status = STATUS_SUCCESS;
    }

errorout:

    if (rfsd_bdl)
        ExFreePool(rfsd_bdl);

    if (NT_SUCCESS(Status)) {
        if (dwRet) *dwRet = Size;
    }

    return Status;
}

NTSTATUS
RfsdWriteFile(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;

    BOOLEAN             bNeedExtending = FALSE;
    BOOLEAN             bAppendFile = FALSE;

    BOOLEAN             bDeferred = 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.Write.Length;
        ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
        
        PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
        Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
        SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

        RfsdPrint((DBG_INFO, "RfsdWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
                             ByteOffset.QuadPart, Length, PagingIo, Nocache));

/*
        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;
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            __leave;
        }

#if FALSE
        if (!Nocache) {

⌨️ 快捷键说明

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