📄 dirsup.c
字号:
FatStringTo8dot3( IrpContext,
*FileName,
&LocalCcb.OemQueryTemplate.Constant );
LocalCcb.ContainsWildCards = FALSE;
LocalCcb.Flags = 0;
FatLocateDirent( IrpContext,
ParentDirectory,
&LocalCcb,
0,
Dirent,
Bcb,
ByteOffset,
NULL,
NULL);
return;
}
VOID
FatLocateVolumeLabel (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
OUT PDIRENT *Dirent,
OUT PBCB *Bcb,
OUT PVBO ByteOffset
)
/*++
Routine Description:
This routine locates on the disk a dirent representing the volume
label. It does this by searching the root directory for a special
volume label dirent.
Arguments:
Vcb - Supplies the VCB for the volume to search
Dirent - Receives a pointer to the located dirent if one was found
or NULL otherwise.
Bcb - Receives the Bcb for the located dirent if one was found or
NULL otherwise.
ByteOffset - Receives the VBO within the Parent directory for
the located dirent if one was found, or 0 otherwise.
Return Value:
None.
--*/
{
NTSTATUS Status;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatLocateVolumeLabel\n", 0);
DebugTrace( 0, Dbg, " Vcb = %08lx\n", Vcb);
DebugTrace( 0, Dbg, " Dirent = %08lx\n", Dirent);
DebugTrace( 0, Dbg, " Bcb = %08lx\n", Bcb);
DebugTrace( 0, Dbg, " ByteOffset = %08lx\n", ByteOffset);
//
// The algorithm here is really simple. We just walk through the
// root directory until we:
//
// A) Find the non-deleted volume label
// B) Can't Wait
// C) Hit the End of Directory
// D) Hit Eof
//
// In the first case we found it, in the latter three cases we did not.
//
*Bcb = NULL;
*ByteOffset = 0;
while ( TRUE ) {
//
// Try to read in the dirent
//
FatReadDirent( IrpContext,
Vcb->RootDcb,
*ByteOffset,
Bcb,
Dirent,
&Status );
//
// If End Directory dirent or EOF, set all out parameters to
// indicate volume label not found and, like, bail.
//
// Note that the order of evaluation here is important since we cannot
// check the first character of the dirent until after we know we
// are not beyond EOF
//
if ((Status == STATUS_END_OF_FILE) ||
((*Dirent)->FileName[0] == FAT_DIRENT_NEVER_USED)) {
DebugTrace( 0, Dbg, "Volume label not found.\n", 0);
//
// If there is a Bcb, unpin it and set it to null
//
FatUnpinBcb( IrpContext, *Bcb );
*Dirent = NULL;
*ByteOffset = 0;
break;
}
//
// If the entry is the non-deleted volume label break from the loop.
//
// Note that all out parameters are already correctly set.
//
if ((((*Dirent)->Attributes & ~FAT_DIRENT_ATTR_ARCHIVE) == FAT_DIRENT_ATTR_VOLUME_ID) &&
((*Dirent)->FileName[0] != FAT_DIRENT_DELETED)) {
DebugTrace( 0, Dbg, "Volume label found at VBO = %08lx\n", *ByteOffset);
//
// We may set this dirty, so pin it.
//
FatPinMappedData( IrpContext,
Vcb->RootDcb,
*ByteOffset,
sizeof(DIRENT),
Bcb );
break;
}
//
// Move on to the next dirent.
//
*ByteOffset += sizeof(DIRENT);
*Dirent += 1;
}
DebugTrace(-1, Dbg, "FatLocateVolumeLabel -> (VOID)\n", 0);
return;
}
VOID
FatGetDirentFromFcbOrDcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN BOOLEAN ReturnOnFailure,
OUT PDIRENT *Dirent,
OUT PBCB *Bcb
)
/*++
Routine Description:
This routine reads locates on the disk the dirent denoted by the
specified Fcb/Dcb.
Arguments:
FcbOrDcb - Supplies the FCB/DCB for the file/directory whose dirent
we are trying to read in. This must not be the root dcb.
Dirent - Receives a pointer to the dirent
Bcb - Receives the Bcb for the dirent
Return Value:
None.
--*/
{
NTSTATUS DontCare;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatGetDirentFromFcbOrDcb\n", 0);
DebugTrace( 0, Dbg, " FcbOrDcb = %08lx\n", FcbOrDcb);
DebugTrace( 0, Dbg, " Dirent = %08lx\n", Dirent);
DebugTrace( 0, Dbg, " Bcb = %08lx\n", Bcb);
//
// Assert that we are not attempting this on the root directory.
//
ASSERT( NodeType(FcbOrDcb) != FAT_NTC_ROOT_DCB );
//
// We know the offset of the dirent within the directory file,
// so we just read it (with pinning).
//
FatReadDirectoryFile( IrpContext,
FcbOrDcb->ParentDcb,
FcbOrDcb->DirentOffsetWithinDirectory,
sizeof(DIRENT),
TRUE,
Bcb,
(PVOID *)Dirent,
&DontCare );
//
// Previous call can fail. We used to assert success, but we use this
// as part of volume verification (DetermineAndMarkFcbCondition) after
// media has been removed. Clearly the directory could shrink and we
// would try to read beyond filesize.
//
// The caller will note this via NULL pointers for Bcb/Buffer. Note that
// both asserts below are OK since this should never happen fixed media.
//
// This was a Prefix catch.
//
ASSERT( FlagOn( FcbOrDcb->Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) ||
NT_SUCCESS( DontCare ));
//
// Note also that the only way this could fail is if the Fcb was being
// verified. This can't happen if the Fcb is in good condition.
//
// Also a Prefix catch.
//
ASSERT( NT_SUCCESS( DontCare ) || FcbOrDcb->FcbCondition == FcbNeedsToBeVerified );
//
// This should never happen except in very specific cases (during volume
// verify) but we'll handle and raise here to save all callers checking the
// pointers.
//
if ((NULL == *Dirent) && !ReturnOnFailure) {
ASSERT( FALSE);
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR);
}
DebugTrace(-1, Dbg, "FatGetDirentFromFcbOrDcb -> (VOID)\n", 0);
}
BOOLEAN
FatIsDirectoryEmpty (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb
)
/*++
Routine Description:
This routine indicates to the caller if the specified directory
is empty. (i.e., it is not the root dcb and it only contains
the "." and ".." entries, or deleted files).
Arguments:
Dcb - Supplies the DCB for the directory being queried.
Return Value:
BOOLEAN - Returns TRUE if the directory is empty and
FALSE if the directory and is not empty.
--*/
{
PBCB Bcb;
ULONG ByteOffset;
PDIRENT Dirent;
BOOLEAN IsDirectoryEmpty = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatIsDirectoryEmpty\n", 0);
DebugTrace( 0, Dbg, " Dcb = %08lx\n", Dcb);
DebugTrace( 0, Dbg, " IsDirectoryEmpty = %08lx\n", IsDirectoryEmpty);
//
// Check to see if the first entry is an and of directory marker.
// For the root directory we check at Vbo = 0, for normal directories
// we check after the "." and ".." entries.
//
ByteOffset = (NodeType(Dcb) == FAT_NTC_ROOT_DCB) ? 0 : 2*sizeof(DIRENT);
//
// We just march through the directory looking for anything other
// than deleted files, LFNs, an EOF, or end of directory marker.
//
Bcb = NULL;
try {
while ( TRUE ) {
//
// Try to read in the dirent
//
FatReadDirent( IrpContext,
Dcb,
ByteOffset,
&Bcb,
&Dirent,
&Status );
//
// If End Directory dirent or EOF, set IsDirectoryEmpty to TRUE and,
// like, bail.
//
// Note that the order of evaluation here is important since we cannot
// check the first character of the dirent until after we know we
// are not beyond EOF
//
if ((Status == STATUS_END_OF_FILE) ||
(Dirent->FileName[0] == FAT_DIRENT_NEVER_USED)) {
DebugTrace( 0, Dbg, "Empty. Last exempt entry at VBO = %08lx\n", ByteOffset);
IsDirectoryEmpty = TRUE;
break;
}
//
// If this dirent is NOT deleted or an LFN set IsDirectoryEmpty to
// FALSE and, like, bail.
//
if ((Dirent->FileName[0] != FAT_DIRENT_DELETED) &&
(Dirent->Attributes != FAT_DIRENT_ATTR_LFN)) {
DebugTrace( 0, Dbg, "Not Empty. First entry at VBO = %08lx\n", ByteOffset);
IsDirectoryEmpty = FALSE;
break;
}
//
// Move on to the next dirent.
//
ByteOffset += sizeof(DIRENT);
Dirent += 1;
}
} finally {
FatUnpinBcb( IrpContext, Bcb );
}
DebugTrace(-1, Dbg, "FatIsDirectoryEmpty -> %ld\n", IsDirectoryEmpty);
return IsDirectoryEmpty;
}
VOID
FatConstructDirent (
IN PIRP_CONTEXT IrpContext,
IN OUT PDIRENT Dirent,
IN POEM_STRING FileName,
IN BOOLEAN ComponentReallyLowercase,
IN BOOLEAN ExtensionReallyLowercase,
IN PUNICODE_STRING Lfn OPTIONAL,
IN UCHAR Attributes,
IN BOOLEAN ZeroAndSetTimeFields,
IN PLARGE_INTEGER SetCreationTime OPTIONAL
)
/*++
Routine Description:
This routine modifies the fields of a dirent.
Arguments:
Dirent - Supplies the dirent being modified.
FileName - Supplies the name to store in the Dirent. This
name must not contain wildcards.
ComponentReallyLowercase - This boolean indicates that the User Specified
compoent name was really all a-z and < 0x80 characters. We set the
magic bit in this case.
ExtensionReallyLowercase - Same as above, but for the extension.
Lfn - May supply a long file name.
Attributes - Supplies the attributes to store in the dirent
ZeroAndSetTimeFields - Tells whether or not to initially zero the dirent
and update the time fields.
SetCreationTime - If specified, contains a timestamp to us
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -