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

📄 cachesup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1990-2000 Microsoft Corporation

Module Name:

    Cache.c

Abstract:

    This module implements the cache management routines for the Cdfs
    FSD and FSP, by calling the Common Cache Manager.


--*/

#include "CdProcs.h"

//
//  The Bug check file id for this module
//

#define BugCheckFileId                   (CDFS_BUG_CHECK_CACHESUP)

//
//  Local debug trace level
//

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCompleteMdl)
#pragma alloc_text(PAGE, CdCreateInternalStream)
#pragma alloc_text(PAGE, CdDeleteInternalStream)
#pragma alloc_text(PAGE, CdPurgeVolume)
#endif


VOID
CdCreateInternalStream (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFCB Fcb,
    IN OPTIONAL PUNICODE_STRING Name
    )

/*++

Routine Description:

    This function creates an internal stream file for interaction
    with the cache manager.  The Fcb here can be for either a
    directory stream or for a path table stream.

Arguments:

    Vcb - Vcb for this volume.

    Fcb - Points to the Fcb for this file.  It is either an Index or
        Path Table Fcb.

Return Value:

    None.

--*/

{
    PFILE_OBJECT StreamFile = NULL;
    BOOLEAN DecrementReference = FALSE;

    BOOLEAN CleanupDirContext = FALSE;
    BOOLEAN UpdateFcbSizes = FALSE;

    DIRENT Dirent;
    DIRENT_ENUM_CONTEXT DirContext;

    PAGED_CODE();

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_FCB( Fcb );

    //
    //  We may only have the Fcb shared.  Lock the Fcb and do a
    //  safe test to see if we need to really create the file object.
    //

    CdLockFcb( IrpContext, Fcb );

    if (Fcb->FileObject != NULL) {

        CdUnlockFcb( IrpContext, Fcb );
        return;
    }

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Create the internal stream.  The Vpb should be pointing at our volume
        //  device object at this point.
        //

        StreamFile = IoCreateStreamFileObject( NULL, Vcb->Vpb->RealDevice );

        if (StreamFile == NULL) {

            CdRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
        }

        //
        //  Initialize the fields of the file object.
        //

        StreamFile->ReadAccess = TRUE;
        StreamFile->WriteAccess = FALSE;
        StreamFile->DeleteAccess = FALSE;

        StreamFile->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject;

        //
        //  Set the file object type and increment the Vcb counts.
        //

        CdSetFileObject( IrpContext,
                         StreamFile,
                         StreamFileOpen,
                         Fcb,
                         NULL );
        
        //
        //  We'll give stream file objects a name to aid IO profiling etc. We 
        //  NULL this in CdDeleteInternalStream before OB deletes the file object,
        //  and before CdRemovePrefix is called (which frees Fcb names).
        //

        StreamFile->FileName = *Name;

        //
        //  We will reference the current Fcb twice to keep it from going
        //  away in the error path.  Otherwise if we dereference it
        //  below in the finally clause a close could cause the Fcb to
        //  be deallocated.
        //

        CdLockVcb( IrpContext, Vcb );
        CdIncrementReferenceCounts( IrpContext, Fcb, 2, 0 );
        CdUnlockVcb( IrpContext, Vcb );
        DecrementReference = TRUE;

        //
        //  Initialize the cache map for the file.
        //

        CcInitializeCacheMap( StreamFile,
                              (PCC_FILE_SIZES)&Fcb->AllocationSize,
                              TRUE,
                              &CdData.CacheManagerCallbacks,
                              Fcb );

        //
        //  Go ahead and store the stream file into the Fcb.
        //

        Fcb->FileObject = StreamFile;
        StreamFile = NULL;

        //
        //  If this is the first file object for a directory then we need to
        //  read the self entry for this directory and update the sizes
        //  in the Fcb.  We know that the Fcb has been initialized so
        //  that we have a least one sector available to read.
        //

        if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) {

            ULONG NewDataLength;

            //
            //  Initialize the search structures.
            //

            CdInitializeDirContext( IrpContext, &DirContext );
            CdInitializeDirent( IrpContext, &Dirent );
            CleanupDirContext = TRUE;

            //
            //  Read the dirent from disk and transfer the data to the
            //  in-memory dirent.
            //

            CdLookupDirent( IrpContext,
                            Fcb,
                            Fcb->StreamOffset,
                            &DirContext );

            CdUpdateDirentFromRawDirent( IrpContext, Fcb, &DirContext, &Dirent );

            //
            //  Verify that this really for the self entry.  We do this by
            //  updating the name in the dirent and then checking that it matches
            //  one of the hard coded names.
            //

            CdUpdateDirentName( IrpContext, &Dirent, FALSE );

            if (Dirent.CdFileName.FileName.Buffer != CdUnicodeSelfArray) {

                CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
            }

            //
            //  If the data sizes are different then update the header
            //  and Mcb for this Fcb.
            //

            NewDataLength = BlockAlign( Vcb, Dirent.DataLength + Fcb->StreamOffset );

            if (NewDataLength == 0) {

                CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
            }

            if (NewDataLength != Fcb->FileSize.QuadPart) {

                Fcb->AllocationSize.QuadPart =
                Fcb->FileSize.QuadPart =
                Fcb->ValidDataLength.QuadPart = NewDataLength;

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

                CdTruncateAllocation( IrpContext, Fcb, 0 );
                CdAddInitialAllocation( IrpContext,
                                        Fcb,
                                        Dirent.StartingOffset,
                                        NewDataLength );

                UpdateFcbSizes = TRUE;
            }

            //
            //  Check for the existence flag and transform to hidden.
            //

            if (FlagOn( Dirent.DirentFlags, CD_ATTRIBUTE_HIDDEN )) {

                SetFlag( Fcb->FileAttributes, FILE_ATTRIBUTE_HIDDEN );
            }

            //
            //  Convert the time to NT time.
            //

            CdConvertCdTimeToNtTime( IrpContext,
                                     Dirent.CdTime,
                                     (PLARGE_INTEGER) &Fcb->CreationTime );

            //
            //  Update the Fcb flags to indicate we have read the
            //  self entry.
            //

            SetFlag( Fcb->FcbState, FCB_STATE_INITIALIZED );

            //
            //  If we updated the sizes then we want to purge the file.  Go
            //  ahead and unpin and then purge the first page.
            //

            CdCleanupDirContext( IrpContext, &DirContext );
            CdCleanupDirent( IrpContext, &Dirent );
            CleanupDirContext = FALSE;

            if (UpdateFcbSizes) {

                CcPurgeCacheSection( &Fcb->FcbNonpaged->SegmentObject,
                                     NULL,
                                     0,
                                     FALSE );
            }
        }

    } finally {

        //
        //  Cleanup any dirent structures we may have used.
        //

        if (CleanupDirContext) {

            CdCleanupDirContext( IrpContext, &DirContext );
            CdCleanupDirent( IrpContext, &Dirent );
        }

        //
        //  If we raised then we need to dereference the file object.
        //

        if (StreamFile != NULL) {

            ObDereferenceObject( StreamFile );
            Fcb->FileObject = NULL;
        }

        //
        //  Dereference and unlock the Fcb.
        //

        if (DecrementReference) {

            CdLockVcb( IrpContext, Vcb );
            CdDecrementReferenceCounts( IrpContext, Fcb, 1, 0 );
            CdUnlockVcb( IrpContext, Vcb );
        }

        CdUnlockFcb( IrpContext, Fcb );
    }

    return;
}


VOID
CdDeleteInternalStream (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

⌨️ 快捷键说明

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