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

📄 dirsup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
    //
    //  Only do this when we are in Chicago Mode.
    //

    Bcb = NULL;

    if (FatData.ChicagoMode &&
        (DirentsNeeded == 1) &&
        (ByteOffset > (NodeType(ParentDirectory) == FAT_NTC_ROOT_DCB ?
                       0 : 2 * sizeof(DIRENT)))) {
        try {

            FatReadDirent( IrpContext,
                           ParentDirectory,
                           ByteOffset - sizeof(DIRENT),
                           &Bcb,
                           &Dirent,
                           &Status );

            if ((Status != STATUS_SUCCESS) ||
                (Dirent->FileName[0] == FAT_DIRENT_NEVER_USED)) {

                FatPopUpFileCorrupt( IrpContext, ParentDirectory );

                FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
            }

            if ((Dirent->Attributes == FAT_DIRENT_ATTR_LFN) &&
                (Dirent->FileName[0] != FAT_DIRENT_DELETED)) {

                //
                //  Pin it, mark it, and set it dirty.
                //

                FatPinMappedData( IrpContext,
                                  ParentDirectory,
                                  ByteOffset - sizeof(DIRENT),
                                  sizeof(DIRENT),
                                  &Bcb );

                Dirent->FileName[0] = FAT_DIRENT_DELETED;

                FatSetDirtyBcb( IrpContext, Bcb, ParentDirectory->Vcb, TRUE );

                ASSERT( RtlAreBitsSet( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
                                       (ByteOffset - sizeof(DIRENT))/ sizeof(DIRENT),
                                       DirentsNeeded ) );

                RtlClearBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
                              (ByteOffset - sizeof(DIRENT))/ sizeof(DIRENT),
                              DirentsNeeded );

            }

        } finally {

            FatUnpinBcb( IrpContext, Bcb );
        }
    }

    //
    //  Assert that the dirents are in fact unused
    //

    try {

        ULONG i;

        Bcb = NULL;

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

            FatReadDirent( IrpContext,
                           ParentDirectory,
                           ByteOffset + i*sizeof(DIRENT),
                           &Bcb,
                           &Dirent,
                           &Status );

            if ((Status != STATUS_SUCCESS) ||
                ((Dirent->FileName[0] != FAT_DIRENT_NEVER_USED) &&
                 (Dirent->FileName[0] != FAT_DIRENT_DELETED))) {

                FatPopUpFileCorrupt( IrpContext, ParentDirectory );
                FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
            }
        }

    } finally {

        FatUnpinBcb( IrpContext, Bcb );
    }

    //
    //  Set the Bits in the bitmap and move the Unused Dirent Vbo.
    //

    ASSERT( RtlAreBitsClear( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
                             ByteOffset / sizeof(DIRENT),
                             DirentsNeeded ) );

    RtlSetBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
                ByteOffset / sizeof(DIRENT),
                DirentsNeeded );

    //
    //  Save the newly computed values in the Parent Directory Fcb
    //

    ParentDirectory->Specific.Dcb.UnusedDirentVbo = UnusedVbo;
    ParentDirectory->Specific.Dcb.DeletedDirentHint = DeletedHint;

    DebugTrace(-1, Dbg, "FatCreateNewDirent -> (VOID)\n", 0);

    return ByteOffset;
}


VOID
FatInitializeDirectoryDirent (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB Dcb,
    IN PDIRENT ParentDirent
    )

/*++

Routine Description:

    This routine converts a dirent into a directory on the disk.  It does this
    setting the directory flag in the dirent, and by allocating the necessary
    space for the "." and ".." dirents and initializing them.

    If a new dirent cannot be allocated (i.e., because the disk is full) then
    it raises the appropriate status.

Arguments:

    Dcb - Supplies the Dcb denoting the file that is to be made into a
        directory.  This must be input a completely empty file with
        an allocation size of zero.

    ParentDirent - Provides the parent Dirent for a time-stamp model.

Return Value:

    None.

--*/

{
    PBCB Bcb;
    PVOID Buffer;
    NTSTATUS DontCare;

    PAGED_CODE();

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

    DebugTrace( 0, Dbg, "  Dcb = %08lx\n", Dcb);

    //
    //  Assert that we are not attempting this on the root directory.
    //

    ASSERT( NodeType(Dcb) != FAT_NTC_ROOT_DCB );

    //
    //  Assert that this is only attempted on newly created directories.
    //

    ASSERT( Dcb->Header.AllocationSize.LowPart == 0 );

    //
    //  Prepare the directory file for writing.  Note that we can use a single
    //  Bcb for these two entries because we know they are the first two in
    //  the directory, and thus together do not span a page boundry.  Also
    //  note that we prepare write 2 entries: one for "." and one for "..".
    //  The end of directory marker is automatically set since the whole
    //  directory is initially zero (DIRENT_NEVER_USED).
    //

    FatPrepareWriteDirectoryFile( IrpContext,
                                  Dcb,
                                  0,
                                  2 * sizeof(DIRENT),
                                  &Bcb,
                                  &Buffer,
                                  FALSE,
                                  TRUE,
                                  &DontCare );

    ASSERT( NT_SUCCESS( DontCare ));

    //
    //  Add the . and .. entries
    //

    try {

        FatConstructDot( IrpContext, Dcb, ParentDirent, (PDIRENT)Buffer + 0);

        FatConstructDotDot( IrpContext, Dcb, ParentDirent, (PDIRENT)Buffer + 1);

    //
    //  Unpin the buffer and return to the caller.
    //

    } finally {

        FatUnpinBcb( IrpContext, Bcb );
    }

    DebugTrace(-1, Dbg, "FatInitializeDirectoryDirent -> (VOID)\n", 0);
    return;
}


VOID
FatTunnelFcbOrDcb (
    IN PFCB FcbOrDcb,
    IN PCCB Ccb OPTIONAL
    )
/*++

Routine Description:

    This routine handles tunneling of an Fcb or Dcb associated with
    an object whose name is disappearing from a directory.

Arguments:

    FcbOrDcb - Supplies the Fcb/Dcb whose name will be going away

    Ccb - Supplies the Ccb for the Fcb (not reqired for a Dcb) so
        that we know which name the Fcb was opened by

Return Value:

    None.

--*/
{
    UNICODE_STRING ShortNameWithCase;
    UNICODE_STRING DownCaseSeg;
    WCHAR ShortNameBuffer[8+1+3];
    NTSTATUS Status;
    USHORT i;

    PAGED_CODE();

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

    if (NodeType(FcbOrDcb) == FAT_NTC_DCB) {

        //
        //  Directory deletion. Flush all entries from this directory in
        //  the cache for this volume
        //

        FsRtlDeleteKeyFromTunnelCache( &FcbOrDcb->Vcb->Tunnel,
                                       FatDirectoryKey(FcbOrDcb) );

    } else {

        //
        //  Was a file, so throw it into the tunnel cache
        //

        //
        //  Get the short name into UNICODE
        //

        ShortNameWithCase.Length = 0;
        ShortNameWithCase.MaximumLength = sizeof(ShortNameBuffer);
        ShortNameWithCase.Buffer = ShortNameBuffer;

        Status = RtlOemStringToCountedUnicodeString( &ShortNameWithCase,
                                                     &FcbOrDcb->ShortName.Name.Oem,
                                                     FALSE);

        ASSERT(ShortNameWithCase.Length != 0);

        ASSERT(NT_SUCCESS(Status));

        if (FlagOn(FcbOrDcb->FcbState, FCB_STATE_8_LOWER_CASE | FCB_STATE_3_LOWER_CASE)) {

            //
            //  Have to repair the case of the short name
            //

            for (i = 0; i < (ShortNameWithCase.Length/sizeof(WCHAR)) &&
                        ShortNameWithCase.Buffer[i] != L'.'; i++);

            //
            //  Now pointing at the '.', or otherwise the end of name component
            //

            if (FlagOn(FcbOrDcb->FcbState, FCB_STATE_8_LOWER_CASE)) {

                DownCaseSeg.Buffer = ShortNameWithCase.Buffer;
                DownCaseSeg.MaximumLength = DownCaseSeg.Length = i*sizeof(WCHAR);

                RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
            }

            i++;

            //
            //  Now pointing at first wchar of the extension.
            //

            if (FlagOn(FcbOrDcb->FcbState, FCB_STATE_3_LOWER_CASE)) {

                //
                //  It is not neccesarily the case that we can rely on the flag
                //  indicating that we really have an extension.
                //

                if ((i*sizeof(WCHAR)) < ShortNameWithCase.Length) {
                    DownCaseSeg.Buffer = &ShortNameWithCase.Buffer[i];
                    DownCaseSeg.MaximumLength = DownCaseSeg.Length = ShortNameWithCase.Length - i*sizeof(WCHAR);
    
                    RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
                }
            }
        }

        //
        //  ... and add it in
        //

        FsRtlAddToTunnelCache( &FcbOrDcb->Vcb->Tunnel,
                               FatDirectoryKey(FcbOrDcb->ParentDcb),
                               &ShortNameWithCase,
                               &FcbOrDcb->ExactCaseLongName,
                               BooleanFlagOn(Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME),
                               sizeof(LARGE_INTEGER),
                               &FcbOrDcb->CreationTime );
    }

    DebugTrace(-1, Dbg, "FatTunnelFcbOrDcb -> (VOID)\n", 0);

    return;
}


VOID
FatDeleteDirent (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB FcbOrDcb,
    IN PDELETE_CONTEXT DeleteContext OPTIONAL,
    IN BOOLEAN DeleteEa
    )

/*++

Routine Description:

    This routine Deletes on the disk the indicated dirent.  It does
    this by marking the dirent as deleted.

Arguments:

    FcbOrDcb - Supplies the FCB/DCB for the file/directory being
        deleted.  For a file the file size and allocation must be zero.
        (Zero allocation is implied by a zero cluster index).
        For a directory the allocation must be zero.

    DeleteContext - This variable, if speicified, may be used to preserve
        the file size and first cluster of file information in the dirent
        fot the benefit of unerase utilities.

    DeleteEa - Tells us whether to delete the EA and whether to check
        for no allocation/  Mainly TRUE.  FALSE passed in from rename.

Return Value:

    None.

--*/

{
    PBCB Bcb = NULL;
    PDIRENT Dirent;
    NTSTATUS DontCare;
    ULONG Offset;
    ULONG DirentsToDelete;

    PAGED_CODE();

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

    DebugTrace( 0, Dbg, "  FcbOrDcb = %08lx\n", FcbOrDcb);

    //
    //  We must be holding the vcb exclusive here to deal with the locate dirent
    //  cases where it cannot be holding the parent simply.  This is actually
    //  a true statement from olden daze, lets just wire in our assertion.
    //
    //  Among other reasons, it'd be unfortunate if this raced with the
    //  rename path.
    //
    
    ASSERT( ExIsResourceAcquiredExclusiveLite( &FcbOrDcb->Vcb->Resource ));

    //
    //  Assert that we are not attempting this on the root directory.
    //

    ASSERT( NodeType(FcbOrDcb) != FAT_NTC_ROOT_DCB );

    //
    //  Make sure all requests have zero allocation/file size
    //

    if (DeleteEa &&
        ((FcbOrDcb->Header.AllocationSize.LowPart != 0) ||
         ((NodeType(FcbOrDcb) == FAT_NTC_FCB) &&
          (FcbOrDcb->Header.FileSize.LowPart != 0)))) {

        DebugTrace( 0, Dbg, "Called with non zero allocation/file size.\n", 0);
        FatBugCheck( 0, 0, 0 );
    }

    //

⌨️ 快捷键说明

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