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

📄 strucsup.c

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

        //
        //  Initialize the Mcb, and setup its mapping.  Note that the root
        //  directory is a fixed size so we can set it everything up now.
        //

        FsRtlInitializeLargeMcb( &Dcb->Mcb, NonPagedPool );
        UnwindMcb = &Dcb->Mcb;

        if (FatIsFat32(Vcb)) {

            //
            //  The first cluster of fat32 roots comes from the BPB
            //

            Dcb->FirstClusterOfFile = Vcb->Bpb.RootDirFirstCluster;

        } else {

            FatAddMcbEntry( Vcb, &Dcb->Mcb,
                            0,
                            FatRootDirectoryLbo( &Vcb->Bpb ),
                            FatRootDirectorySize( &Vcb->Bpb ));
        }

        if (FatIsFat32(Vcb)) {

            //
            //  Find the size of the fat32 root. As a side-effect, this will create
            //  MCBs for the entire root. In the process of doing this, we may
            //  discover that the FAT chain is bogus and raise corruption.
            //

            Dcb->Header.AllocationSize.LowPart = 0xFFFFFFFF;
            FatLookupFileAllocationSize( IrpContext, Dcb);

            Dcb->Header.FileSize.QuadPart =
                    Dcb->Header.AllocationSize.QuadPart;
        } else {

            //
            //  set the allocation size to real size of the root directory
            //

            Dcb->Header.FileSize.QuadPart =
            Dcb->Header.AllocationSize.QuadPart = FatRootDirectorySize( &Vcb->Bpb );

        }

        //
        //  Set our two create dirent aids to represent that we have yet to
        //  enumerate the directory for never used or deleted dirents.
        //

        Dcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
        Dcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;

        //
        //  Setup the free dirent bitmap buffer.
        //

        RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
                             NULL,
                             0 );

        FatCheckFreeDirentBitmap( IrpContext, Dcb );

    } finally {

        DebugUnwind( FatCreateRootDcb );

        //
        //  If this is an abnormal termination then undo our work
        //

        if (AbnormalTermination()) {

            ULONG i;

            if (UnwindFileObject != NULL) { ObDereferenceObject( UnwindFileObject ); }
            if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
            if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
            if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }

            for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
                if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
            }

            //
            //  Re-zero the entry in the Vcb.
            //

            Vcb->RootDcb = NULL;
        }

        DebugTrace(-1, Dbg, "FatCreateRootDcb -> %8lx\n", Dcb);
    }

    return;
}


PFCB
FatCreateFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PDCB ParentDcb,
    IN ULONG LfnOffsetWithinDirectory,
    IN ULONG DirentOffsetWithinDirectory,
    IN PDIRENT Dirent,
    IN PUNICODE_STRING Lfn OPTIONAL,
    IN BOOLEAN IsPagingFile,
    IN BOOLEAN SingleResource
    )

/*++

Routine Description:

    This routine allocates, initializes, and inserts a new Fcb record into
    the in-memory data structures.

Arguments:

    Vcb - Supplies the Vcb to associate the new FCB under.

    ParentDcb - Supplies the parent dcb that the new FCB is under.

    LfnOffsetWithinDirectory - Supplies the offset of the LFN.  If there is
        no LFN associated with this file then this value is same as
        DirentOffsetWithinDirectory.

    DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
        start of the directory file where the dirent for the fcb is located

    Dirent - Supplies the dirent for the fcb being created

    Lfn - Supplies a long UNICODE name associated with this file.

    IsPagingFile - Indicates if we are creating an FCB for a paging file
        or some other type of file.

    SingleResource - Indicates if this Fcb should share a single resource
        as both main and paging.

Return Value:

    PFCB - Returns a pointer to the newly allocated FCB

--*/

{
    PFCB Fcb;
    POOL_TYPE PoolType;

    //
    //  The following variables are used for abnormal unwind
    //

    PVOID UnwindStorage[2] = { NULL, NULL };
    PERESOURCE UnwindResource = NULL;
    PERESOURCE UnwindResource2 = NULL;
    PLIST_ENTRY UnwindEntryList = NULL;
    PLARGE_MCB UnwindMcb = NULL;
    PFILE_LOCK UnwindFileLock = NULL;
    POPLOCK UnwindOplock = NULL;

    DebugTrace(+1, Dbg, "FatCreateFcb\n", 0);

    try {

        //
        //  Determine the pool type we should be using for the fcb and the
        //  mcb structure
        //

        if (IsPagingFile) {

            PoolType = NonPagedPool;
            Fcb = UnwindStorage[0] = FsRtlAllocatePoolWithTag( NonPagedPool,
                                                               sizeof(FCB),
                                                               TAG_FCB );
        } else {

            PoolType = PagedPool;
            Fcb = UnwindStorage[0] = FatAllocateFcb();

        }

        //
        //  ... and zero it out
        //

        RtlZeroMemory( Fcb, sizeof(FCB) );

        UnwindStorage[1] =
        Fcb->NonPaged = FatAllocateNonPagedFcb();

        RtlZeroMemory( Fcb->NonPaged, sizeof( NON_PAGED_FCB ) );

        //
        //  Set the proper node type code, node byte size, and call backs
        //

        Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
        Fcb->Header.NodeByteSize = sizeof(FCB);

        Fcb->FcbCondition = FcbGood;

        //
        //  Check to see if we need to set the Fcb state to indicate that this
        //  is a paging/system file.  This will prevent it from being opened
        //  again.
        //

        if (IsPagingFile) {

            SetFlag( Fcb->FcbState, FCB_STATE_PAGING_FILE | FCB_STATE_SYSTEM_FILE );
        }

        //
        //  The initial state, open count, and segment objects fields are already
        //  zero so we can skip setting them
        //

        //
        //  Initialize the resource variable
        //


        UnwindResource =
        Fcb->Header.Resource = FatAllocateResource();

        //
        //  Initialize the PagingIo Resource.  We no longer use the FsRtl common
        //  shared pool because this led to a) deadlocks due to cases where files
        //  and their parent directories shared a resource and b) there is no way
        //  to anticipate inter-driver induced deadlock via recursive operation.
        //

        if (SingleResource) {

            Fcb->Header.PagingIoResource = Fcb->Header.Resource;

        } else {

            UnwindResource2 =
            Fcb->Header.PagingIoResource = FatAllocateResource();
        }

        //
        //  Insert this fcb into our parent dcb's queue.
        //
        //  There is a deep reason why this goes on the tail, to allow us
        //  to easily enumerate all child directories before child files.
        //  This is important to let us maintain whole-volume lockorder
        //  via BottomUp enumeration.
        //

        InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
                        &Fcb->ParentDcbLinks );
        UnwindEntryList = &Fcb->ParentDcbLinks;

        //
        //  Point back to our parent dcb
        //

        Fcb->ParentDcb = ParentDcb;

        //
        //  Set the Vcb
        //

        Fcb->Vcb = Vcb;

        //
        //  Set the dirent offset within the directory
        //

        Fcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
        Fcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;

        //
        //  Set the DirentFatFlags and LastWriteTime
        //

        Fcb->DirentFatFlags = Dirent->Attributes;

        Fcb->LastWriteTime = FatFatTimeToNtTime( IrpContext,
                                                 Dirent->LastWriteTime,
                                                 0 );

        //
        //  These fields are only non-zero when in Chicago mode.
        //

        if (FatData.ChicagoMode) {

            LARGE_INTEGER FatSystemJanOne1980;

            //
            //  If either date is possibly zero, get the system
            //  version of 1/1/80.
            //

            if ((((PUSHORT)Dirent)[9] & ((PUSHORT)Dirent)[8]) == 0) {

                ExLocalTimeToSystemTime( &FatJanOne1980,
                                         &FatSystemJanOne1980 );
            }

            //
            //  Only do the really hard work if this field is non-zero.
            //

            if (((PUSHORT)Dirent)[9] != 0) {

                Fcb->LastAccessTime =
                    FatFatDateToNtTime( IrpContext,
                                        Dirent->LastAccessDate );

            } else {

                Fcb->LastAccessTime = FatSystemJanOne1980;
            }

            //
            //  Only do the really hard work if this field is non-zero.
            //

            if (((PUSHORT)Dirent)[8] != 0) {

                Fcb->CreationTime =
                    FatFatTimeToNtTime( IrpContext,
                                        Dirent->CreationTime,
                                        Dirent->CreationMSec );

            } else {

                Fcb->CreationTime = FatSystemJanOne1980;
            }
        }

        //
        //  Initialize Advanced FCB Header fields
        //

        ExInitializeFastMutex( &Fcb->NonPaged->AdvancedFcbHeaderMutex );
        FsRtlSetupAdvancedHeader( &Fcb->Header,
                                  &Fcb->NonPaged->AdvancedFcbHeaderMutex );

        //
        //  To make FAT match the present functionality of NTFS, disable
        //  stream contexts on paging files
        //

        if (IsPagingFile) {

            SetFlag( Fcb->Header.Flags2, FSRTL_FLAG2_IS_PAGING_FILE );
            ClearFlag( Fcb->Header.Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS );
        }

        //
        //  Initialize the Mcb
        //

        FsRtlInitializeLargeMcb( &Fcb->Mcb, PoolType );
        UnwindMcb = &Fcb->Mcb;

        //
        //  Set the file size, valid data length, first cluster of file,
        //  and allocation size based on the information stored in the dirent
        //

        Fcb->Header.FileSize.LowPart = Dirent->FileSize;

        Fcb->Header.ValidDataLength.LowPart = Dirent->FileSize;

        Fcb->ValidDataToDisk = Dirent->FileSize;

        Fcb->FirstClusterOfFile = (ULONG)Dirent->FirstClusterOfFile;

        if ( FatIsFat32(Vcb) ) {

            Fcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
        }

        if ( Fcb->FirstClusterOfFile == 0 ) {

            Fcb->Header.AllocationSize.QuadPart = 0;

        } else {

            Fcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
        }

        //
        //  Initialize the Fcb's file lock record
        //

        FsRtlInitializeFileLock( &Fcb->Specific.Fcb.FileLock, NULL, NULL );
        UnwindFileLock = &Fcb->Specific.Fcb.FileLock;

        //
        //  Initialize the oplock structure.
        //

        FsRtlInitializeOplock( &Fcb->Specific.Fcb.Oplock );
        UnwindOplock = &Fcb->Specific.Fcb.Oplock;

        //
        //  Indicate that Fast I/O is possible
        //

        Fcb->Header.IsFastIoPossible = TRUE;

        //
        //  Set the file names.  This must be the last thing we do.
        //

        FatConstructNamesInFcb( IrpContext,
                                Fcb,
                                Dirent,
                                Lfn );

        //
        //  Drop the shortname hint so prefix searches can figure out
        //  what they found
        //

        Fcb->ShortName.FileNameDos = TRUE;

    } finally {

        DebugUnwind( FatCreateFcb );

        //
        //  If this is an abnormal termination then undo our work
        //

        if (AbnormalTermination()) {

            ULONG i;

            if (UnwindOplock != NULL) { FsRtlUninitializeOplock( UnwindOplock ); }
            if (UnwindFileLock != NULL) { FsRtlUninitializeFileLock( UnwindFileLock ); }
            if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
            if (UnwindEntryList != NULL) { RemoveEntryList( UnwindEntryList ); }
            if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
            if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }

            for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
                if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
            }
        }

        DebugTrace(-1, Dbg, "FatCreateFcb -> %08lx\n", Fcb);
    }

    //
    //  return and tell the caller
    //

    return Fcb;
}


PDCB
FatCreateDcb (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PDCB ParentDcb,
    IN ULONG LfnOffsetWithinDirectory,
    IN ULONG DirentOffsetWithinDirectory,
    IN PDIRENT Dirent,
    IN PUNICODE_STRING Lfn OPTIONAL
    )

/*++

Routine Description:

    This routine allocates, initializes, and inserts a new Dcb record into
    the in memory data structures.

Arguments:

    Vcb - Supplies the Vcb to associate the new DCB under.

    ParentDcb - Supplies the parent dcb that the new DCB is under.

    LfnOffsetWithinDirectory - Supplies the offset of the LFN.  If there is
        no LFN associated with this file then this value is same as
        DirentOffsetWithinDirectory.

    DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
        start of the directory file where the dirent for the fcb is located

    Dirent - Supplies the dirent for the dcb being created

    FileName - Supplies the file name of the file relative to the directory
        it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
        the preceding backslash).

    Lfn - Supplies a long UNICODE name associated with this directory.

⌨️ 快捷键说明

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