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

📄 write.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 3 页
字号:
            BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
            BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
            BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

            if ( !CcCanIWrite( 
                      FileObject,
                      Length,
                      (bWait && bQueue),
                      bAgain ) ) {
                SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

                CcDeferWrite( FileObject,
                              (PCC_POST_DEFERRED_WRITE)RfsdDeferWrite,
                              IrpContext,
                              Irp,
                              Length,
                              bAgain );

                bDeferred = TRUE;

                DbgBreak();

                Status = STATUS_PENDING;
                __leave;
            }
        }

#endif

        if (IsEndOfFile(ByteOffset)) {
            bAppendFile = TRUE;
            ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
        }

        if ( FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        //
        //  Do flushing for such cases
        //
        if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL))  {

            ExAcquireResourceExclusive( &Fcb->MainResource, 
                    IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));

            MainResourceAcquired = TRUE;

            ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
            ExReleaseResource(&Fcb->PagingIoResource);

            CcFlushCache( &(Fcb->SectionObject),
                          &ByteOffset,
                          Length,
                          &(Irp->IoStatus));
            ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);

            if (!NT_SUCCESS(Irp->IoStatus.Status)) 
            {
                Status = Irp->IoStatus.Status;
                __leave;
            }

            ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
            ExReleaseResource(&Fcb->PagingIoResource);

            CcPurgeCacheSection( &(Fcb->SectionObject),
                                 (PLARGE_INTEGER)&(ByteOffset),
                                 Length,
                                 FALSE );

            ExReleaseResource(&Fcb->MainResource);
            MainResourceAcquired = FALSE;
        }
        
        if (!PagingIo) {

            if (!ExAcquireResourceExclusiveLite(
                &Fcb->MainResource,
                IrpContext->IsSynchronous )) {
                Status = STATUS_PENDING;
                __leave;
            }
            
            MainResourceAcquired = TRUE;

        } else {

/*
            ULONG ResShCnt, ResExCnt; 
            ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
            ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);

            RfsdPrint((DBG_USER, "RfsdWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
                       Fcb->RfsdMcb->Inode, Fcb->RfsdMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous));
*/
            if (!ExAcquireResourceSharedLite(
                 &Fcb->PagingIoResource,
                 IrpContext->IsSynchronous )) {
                Status = STATUS_PENDING;
                __leave;
            }

            PagingIoResourceAcquired = TRUE;
        }
        
        if (!PagingIo) {
            if (!FsRtlCheckLockForWriteAccess(
                &Fcb->FileLockAnchor,
                Irp         )) {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }
        }

        if (Nocache) {

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

                if ( ByteOffset.QuadPart >= 
                     Fcb->Header.AllocationSize.QuadPart) {

                    Status = STATUS_SUCCESS;
                    Irp->IoStatus.Information = 0;
                    __leave;

                } else {

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

        if (!Nocache) {

            if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
                __leave;
            }

            if (FileObject->PrivateCacheMap == NULL) {

                CcInitializeCacheMap(
                        FileObject,
                        (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
                        FALSE,
                        &RfsdGlobal->CacheManagerCallbacks,
                        Fcb );

                CcSetReadAheadGranularity(
                         FileObject,
                         READ_AHEAD_GRANULARITY );

                CcSetFileSizes(
                        FileObject, 
                        (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
            }

            CacheObject = FileObject;

            //
            //  Need extending the size of inode ?
            //
            if ( (bAppendFile) || ((ByteOffset.QuadPart + Length) >
                 (Fcb->Header.FileSize.QuadPart)) ) {

                LARGE_INTEGER   ExtendSize;
                LARGE_INTEGER   FileSize;

                bNeedExtending = TRUE;
                FileSize = Fcb->Header.FileSize;
                ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);

                if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) {
                    Status = RfsdExpandFile(IrpContext, Vcb, Fcb, &ExtendSize);
                    if (!NT_SUCCESS(Status)) {
                        __leave;
                    }
                }

                {
                    Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
                    Fcb->Inode->i_size = ExtendSize.LowPart;
                    Fcb->Inode->i_size_high = (ULONG) ExtendSize.HighPart;
                }

                if (FileObject->PrivateCacheMap) {

                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));

                    if (ByteOffset.QuadPart > FileSize.QuadPart) {
                        RfsdZeroHoles( IrpContext, Vcb, FileObject, FileSize.QuadPart, 
                                       ByteOffset.QuadPart - FileSize.QuadPart);
                    }

                    if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart) {
                        RfsdZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, 
                        Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
                    }
                }

                if (RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode)) {
                    Status = STATUS_SUCCESS;
                }

                RfsdNotifyReportChange(
                        IrpContext,
                        Vcb,
                        Fcb,
                        FILE_NOTIFY_CHANGE_SIZE,
                        FILE_ACTION_MODIFIED );
            }

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

            } else {

                Buffer = RfsdGetUserBuffer(Irp);
                
                if (Buffer == NULL) {
                    DbgBreak();
                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }
                
                if (!CcCopyWrite(
                        CacheObject,
                        (PLARGE_INTEGER)&ByteOffset,
                        Length,
                        IrpContext->IsSynchronous,
                        Buffer  )) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                
                Status = Irp->IoStatus.Status;
            }

            if (NT_SUCCESS(Status)) {

                Irp->IoStatus.Information = Length;

                if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
                    RfsdPrint((DBG_USER, "RfsdWriteFile is starting FlushingDpc...\n"));
                    RfsdStartFloppyFlushDpc(Vcb, Fcb, FileObject);
                }
            }

        } else {

            ReturnedLength = Length;

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

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = Length;
            
            Status = RfsdWriteInode(
                        IrpContext,
                        Vcb,
                        Fcb->RfsdMcb->Inode,
                        Fcb->Inode,
                        (ULONGLONG)(ByteOffset.QuadPart),
                        NULL,
                        Length,
                        TRUE,
                        &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) {
                    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);
                            SetFlag(Fcb->Flags, FCB_FILE_MODIFIED);
                        }
                    }

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

}

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

        ASSERT(IrpContext);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        FileObject = IrpContext->FileObject;
        
        Irp = IrpContext->Irp;
        IrpSp = IoGetCurrentIrpStackLocation(Irp);
        
        CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
        
        Irp->MdlAddress = NULL;
        
        Status = STATUS_SUCCESS;

    } __finally {

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


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

    __try {

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {

            Status =  RfsdWriteComplete(IrpContext);
            bCompleteRequest = FALSE;

        } else {

            DeviceObject = IrpContext->DeviceObject;

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

            Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;

            if (Vcb->Identifier.Type != RFSDVCB ||
                Vcb->Identifier.Size != sizeof(RFSD_VCB) ) {
                 Status = STATUS_INVALID_PARAMETER;
                __leave;
            }

            ASSERT(IsMounted(Vcb));

            if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
                Status = STATUS_TOO_LATE;
                __leave;
            }

            if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
                Status = STATUS_MEDIA_WRITE_PROTECTED;
                __leave;
            }

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

            if (FcbOrVcb->Identifier.Type == RFSDVCB) {

                Status = RfsdWriteVolume(IrpContext);

                if (!NT_SUCCESS(Status)) {
                    DbgBreak();
                }

                bCompleteRequest = FALSE;
            } else if (FcbOrVcb->Identifier.Type == RFSDFCB) {
                Status = RfsdWriteFile(IrpContext);

                if (!NT_SUCCESS(Status)) {
                    DbgBreak();
                }

                bCompleteRequest = FALSE;
            } else {
                Status = STATUS_INVALID_PARAMETER;
            }
        }

    } __finally {

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

⌨️ 快捷键说明

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