📄 dirsup.c
字号:
//
// 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 + -