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

📄 cachesup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:
    Status - Returns the status of the operation.

--*/

{
    LARGE_INTEGER Vbo;
    ULONG InitialAllocation;
    BOOLEAN UnwindWeAllocatedDiskSpace = FALSE;
    ULONG ClusterSize;

    PVOID LocalBuffer;

    PAGED_CODE();
    
    DebugTrace(+1, Dbg, "FatPrepareWriteDirectoryFile\n", 0);
    DebugTrace( 0, Dbg, "Dcb         = %08lx\n", Dcb);
    DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", (ULONG)StartingVbo);
    DebugTrace( 0, Dbg, "ByteCount   = %08lx\n", ByteCount);
    DebugTrace( 0, Dbg, "Zero        = %08lx\n", Zero);

    *Bcb = NULL;
    *Buffer = NULL;

    //
    //  If we need to create a directory file and initialize the
    //  cachemap, do so.
    //

    FatOpenDirectoryFile( IrpContext, Dcb );

    //
    //  If the transfer is beyond the allocation size we need to
    //  extend the directory's allocation.  The call to
    //  AddFileAllocation will raise a condition if
    //  it runs out of disk space.  Note that the root directory
    //  cannot be extended.
    //

    Vbo.QuadPart = StartingVbo;

    try {

        if (StartingVbo + ByteCount > Dcb->Header.AllocationSize.LowPart) {

            if (NodeType(Dcb) == FAT_NTC_ROOT_DCB &&
                !FatIsFat32(Dcb->Vcb)) {

                FatRaiseStatus( IrpContext, STATUS_DISK_FULL );
            }

            DebugTrace(0, Dbg, "Try extending normal directory\n", 0);

            InitialAllocation = Dcb->Header.AllocationSize.LowPart;

            FatAddFileAllocation( IrpContext,
                                  Dcb,
                                  Dcb->Specific.Dcb.DirectoryFile,
                                  StartingVbo + ByteCount );

            UnwindWeAllocatedDiskSpace = TRUE;

            //
            //  Inform the cache manager of the new allocation
            //

            Dcb->Header.FileSize.LowPart =
                Dcb->Header.AllocationSize.LowPart;

            CcSetFileSizes( Dcb->Specific.Dcb.DirectoryFile,
                            (PCC_FILE_SIZES)&Dcb->Header.AllocationSize );

            //
            //  Set up the Bitmap buffer if it is not big enough already
            //

            FatCheckFreeDirentBitmap( IrpContext, Dcb );

            //
            //  The newly allocated clusters should be zeroed starting at
            //  the previous allocation size
            //

            Zero = TRUE;
            Vbo.QuadPart = InitialAllocation;
            ByteCount = Dcb->Header.AllocationSize.LowPart - InitialAllocation;
        }

        //
        // Call the Cache Manager to attempt the transfer, going one cluster
        // at a time to avoid pinning across a page boundary.
        //

        ClusterSize =
            1 << Dcb->Vcb->AllocationSupport.LogOfBytesPerCluster;

        while (ByteCount > 0) {

            ULONG BytesToPin;

            *Bcb = NULL;

            if (ByteCount > ClusterSize) {
                BytesToPin = ClusterSize;
            } else {
                BytesToPin = ByteCount;
            }

            ASSERT( (Vbo.QuadPart / ClusterSize) ==
                    (Vbo.QuadPart + BytesToPin - 1)/ClusterSize );

            if (!CcPinRead( Dcb->Specific.Dcb.DirectoryFile,
                            &Vbo,
                            BytesToPin,
                            BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
                            Bcb,
                            &LocalBuffer )) {
    
                //
                // Could not read the data without waiting (cache miss).
                //

                FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
            }

            //
            //  Update our caller with the beginning of their request.
            //
            
            if (*Buffer == NULL) {

                *Buffer = LocalBuffer;
            }

            DbgDoit( IrpContext->PinCount += 1 )

            if (Zero) {
                
                //
                //  We set this guy dirty right now so that we can raise CANT_WAIT when
                //  it needs to be done.  It'd be beautiful if we could noop the read IO
                //  since we know we don't care about it.
                //
                
                RtlZeroMemory( LocalBuffer, BytesToPin );
                CcSetDirtyPinnedData( *Bcb, NULL );
            }

            ByteCount -= BytesToPin;
            Vbo.QuadPart += BytesToPin;


            if (ByteCount > 0) {

                FatUnpinBcb( IrpContext, *Bcb );
            }
        }

        //
        //  This lets us get the data pinned until we complete the request
        //  and writes the dirty bit through to the disk.
        //

        FatSetDirtyBcb( IrpContext, *Bcb, Dcb->Vcb, Reversible );

        *Status = STATUS_SUCCESS;

    } finally {

        DebugUnwind( FatPrepareWriteDirectoryFile );

        if (AbnormalTermination()) {

            //
            //  These steps are carefully arranged - FatTruncateFileAllocation can raise.
            //  Make sure we unpin the buffer.  If FTFA raises, the effect should be benign.
            //
            
            FatUnpinBcb(IrpContext, *Bcb);
            
            if (UnwindWeAllocatedDiskSpace == TRUE) {

                //
                //  Inform the cache manager of the change.
                //

                FatTruncateFileAllocation( IrpContext, Dcb, InitialAllocation );

                Dcb->Header.FileSize.LowPart =
                    Dcb->Header.AllocationSize.LowPart;

                CcSetFileSizes( Dcb->Specific.Dcb.DirectoryFile,
                                (PCC_FILE_SIZES)&Dcb->Header.AllocationSize );
            }
        }

        DebugTrace(-1, Dbg, "FatPrepareWriteDirectoryFile -> (VOID), *Bcb = %08lx\n", *Bcb);
    }

    return;
}


#if DBG
BOOLEAN FatDisableParentCheck = 0;

BOOLEAN
FatIsCurrentOperationSynchedForDcbTeardown (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB Dcb
    )
{
    PIRP Irp = IrpContext->OriginatingIrp;
    PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation( Irp ) ;
    PFILE_OBJECT FileObject = Stack->FileObject;
    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    PFILE_OBJECT ToCheck[3];
    ULONG Index = 0;

    PAGED_CODE();
    
    //
    //  While mounting, we're OK without having to own anything.
    //
    
    if (Stack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
        Stack->MinorFunction == IRP_MN_MOUNT_VOLUME) {

        return TRUE;
    }
    
    //
    //  With the Vcb held, the close path is blocked out.
    //
    
    if (ExIsResourceAcquiredSharedLite( &Dcb->Vcb->Resource ) ||
        ExIsResourceAcquiredExclusiveLite( &Dcb->Vcb->Resource )) {

        return TRUE;
    }
    
    //
    //  Accept this assertion at face value.  It comes from GetDirentForFcbOrDcb,
    //  and is reliable.
    //
    
    if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_PARENT_BY_CHILD )) {

        return TRUE;
    }

    //
    //  Determine which fileobjects are around on this operation.
    //

    if (Stack->MajorFunction == IRP_MJ_SET_INFORMATION &&
        Stack->Parameters.SetFile.FileObject) {

        ToCheck[Index++] = Stack->Parameters.SetFile.FileObject;
    }

    if (Stack->FileObject) {
        
        ToCheck[Index++] = Stack->FileObject;
    }

    ToCheck[Index] = NULL;
    
    //
    //  If the fileobjects we have are for this dcb or a child of it, we are
    //  also guaranteed that this dcb isn't going anywhere (even without
    //  the Vcb).
    //
    
    for (Index = 0; ToCheck[Index] != NULL; Index++) {
    
        (VOID) FatDecodeFileObject( ToCheck[Index], &Vcb, &Fcb, &Ccb );

        while ( Fcb ) {
    
            if (Fcb == Dcb) {
    
                return TRUE;
            }
    
            Fcb = Fcb->ParentDcb;
        }
    }

    return FatDisableParentCheck;
}
#endif // DBG

VOID
FatOpenDirectoryFile (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB Dcb
    )

/*++

Routine Description:

    This routine opens a new directory file if one is not already open.

Arguments:

    Dcb - Pointer to the DCB for the directory

Return Value:

    None.

--*/

{
    PAGED_CODE();
    
    DebugTrace(+1, Dbg, "FatOpenDirectoryFile\n", 0);
    DebugTrace( 0, Dbg, "Dcb = %08lx\n", Dcb);

    //
    //  If we don't have some hold on this Dcb (there are several ways), there is nothing
    //  to prevent child files from closing and tearing this branch of the tree down in the
    //  midst of our slapping this reference onto it.
    //
    //  I really wish we had a proper Fcb synchronization model (like CDFS/UDFS/NTFS).
    //
    
    ASSERT( FatIsCurrentOperationSynchedForDcbTeardown( IrpContext, Dcb ));

    //
    //  If we haven't yet set the correct AllocationSize, do so.
    //

    if (Dcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT) {

        FatLookupFileAllocationSize( IrpContext, Dcb );

        Dcb->Header.FileSize.LowPart =
        Dcb->Header.AllocationSize.LowPart;
    }

    //
    //  Setup the Bitmap buffer if it is not big enough already
    //

    FatCheckFreeDirentBitmap( IrpContext, Dcb );

    //
    //  Check if we need to create a directory file.
    //
    //  We first do a spot check and then synchronize and check again.
    //

    if (Dcb->Specific.Dcb.DirectoryFile == NULL) {

        PFILE_OBJECT DirectoryFileObject = NULL;

        FatAcquireDirectoryFileMutex( Dcb->Vcb );

        try {

            if (Dcb->Specific.Dcb.DirectoryFile == NULL) {

                PDEVICE_OBJECT RealDevice;

                //
                //  Create the special file object for the directory file, and set
                //  up its pointers back to the Dcb and the section object pointer.
                //  Note that setting the DirectoryFile pointer in the Dcb has
                //  to be the last thing done.
                //
                //  Preallocate a close context since we have no Ccb for this object.
                //

                RealDevice = Dcb->Vcb->CurrentDevice;

                DirectoryFileObject = IoCreateStreamFileObject( NULL, RealDevice );
                FatPreallocateCloseContext( Dcb->Vcb);

                FatSetFileObject( DirectoryFileObject,
                                  DirectoryFile,
                                  Dcb,
                                  NULL );

                //
                //  Remember this internal open.
                //

                InterlockedIncrement( &(Dcb->Vcb->InternalOpenCount) );

                //
                //  If this is the root directory, it is also a residual open.
                //

                if (NodeType( Dcb ) == FAT_NTC_ROOT_DCB) {

                    InterlockedIncrement( &(Dcb->Vcb->ResidualOpenCount) );
                }

                DirectoryFileObject->SectionObjectPointer = &Dcb->NonPaged->SectionObjectPointers;

                DirectoryFileObject->ReadAccess = TRUE;
                DirectoryFileObject->WriteAccess = TRUE;
                DirectoryFileObject->DeleteAccess = TRUE;

                InterlockedIncrement( &Dcb->Specific.Dcb.DirectoryFileOpenCount );

                Dcb->Specific.Dcb.DirectoryFile = DirectoryFileObject;
                
                //
                //  Indicate we're happy with the fileobject now.
                //

                DirectoryFileObject = NULL;
            }

        } finally {

            FatReleaseDirectoryFileMutex( Dcb->Vcb );

            //
            //  Rip the object up if we couldn't get the close context.
            //
            
            if (DirectoryFileObject) {
                
                ObDereferenceObject( DirectoryFileObject );
            }
        }
    }

    //
    //  Finally check if we need to initialize the Cache Map for the
    //  directory file.  The size of the section we are going to map
    //  the current allocation size for the directory.  Note that the
    //  cache manager will provide syncronization for us.
    //

    if ( Dcb->Specific.Dcb.DirectoryFile->PrivateCacheMap == NULL ) {

        Dcb->Header.ValidDataLength = FatMaxLarge;
        Dcb->ValidDataToDisk = MAXULONG;

        CcInitializeCacheMap( Dcb->Specific.Dcb.DirectoryFile,

⌨️ 快捷键说明

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