dirctrl.c
来自「windows 2000中的UDF文件系统的驱动程序.只有读的功能,不支持未关闭」· C语言 代码 · 共 1,926 行 · 第 1/4 页
C
1,926 行
if (!Found) {
UdfCleanupDirContext( IrpContext, &CompoundDirContext->DirContext );
UdfInitializeDirContext( IrpContext, &CompoundDirContext->DirContext );
Found = UdfLookupInitialFileIndex( IrpContext, Fcb, CompoundDirContext, &LastFileIndex );
ASSERT( Found );
}
}
}
}
//
// Only update the dirent name if we will need it for some reason.
// Don't update this name if we are returning the next entry, and
// don't update it if it was already done.
//
if (!(*ReturnNextEntry) &&
CompoundDirContext->DirContext.PureObjectName.Buffer == NULL) {
//
// Update the names in the dirent.
//
UdfUpdateDirNames( IrpContext,
&CompoundDirContext->DirContext,
BooleanFlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE ));
}
//
// Look at the flag in the IrpSp indicating whether to return just
// one entry.
//
*ReturnSingleEntry = FALSE;
if (FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY )) {
*ReturnSingleEntry = TRUE;
}
return;
}
//
// Local support routine
//
BOOLEAN
UdfEnumerateIndex (
IN PIRP_CONTEXT IrpContext,
IN PCCB Ccb,
IN OUT PCOMPOUND_DIR_ENUM_CONTEXT CompoundDirContext,
IN BOOLEAN ReturnNextEntry
)
/*++
Routine Description:
This routine is the worker routine for index enumeration. We are positioned
at some dirent in the directory and will either return the first match
at that point or look to the next entry. The Ccb contains details about
the type of matching to do.
Arguments:
Ccb - Ccb for this directory handle.
CompoundDirContext - context already positioned at some entry in the directory.
ReturnNextEntry - Indicates if we are returning this entry or should start
with the next entry.
Return Value:
BOOLEAN - TRUE if next entry is found, FALSE otherwise.
--*/
{
BOOLEAN Found = FALSE;
PNSR_FID Fid;
PDIR_ENUM_CONTEXT DirContext;
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_CCB( Ccb );
//
// Directly reference the directory enumeration context for convenience.
//
DirContext = &CompoundDirContext->DirContext;
//
// Loop until we find a match or exaust the directory.
//
while (TRUE) {
//
// Move to the next entry unless we want to consider the current
// entry.
//
if (ReturnNextEntry) {
if (!UdfLookupNextFileIndex( IrpContext, Ccb->Fcb, CompoundDirContext )) {
break;
}
UdfUpdateDirNames( IrpContext,
DirContext,
BooleanFlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE ));
} else {
ReturnNextEntry = TRUE;
}
//
// Don't bother if we have a constant entry and are ignoring them.
//
if (!FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT ) &&
FlagOn( Ccb->Flags, CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY )) {
continue;
}
//
// Directly reference the Fid for convenience.
//
Fid = DirContext->Fid;
//
// Look at the current entry if it is pointing at real space on the disk. If the Fid is NULL, this
// means it is to be synthesized (and thus interesting to look at).
//
if (Fid == NULL || !FlagOn( Fid->Flags, NSR_FID_F_DELETED )) {
//
// If we match all names then return to our caller.
//
if (FlagOn( Ccb->Flags, CCB_FLAG_ENUM_MATCH_ALL )) {
DirContext->ShortObjectName.Length = 0;
Found = TRUE;
break;
}
//
// Check if the long name matches the search expression.
//
if (UdfIsNameInExpression( IrpContext,
&DirContext->CaseObjectName,
&Ccb->SearchExpression,
BooleanFlagOn( Ccb->Flags, CCB_FLAG_ENUM_NAME_EXP_HAS_WILD ))) {
//
// Let our caller know we found an entry.
//
DirContext->ShortObjectName.Length = 0;
Found = TRUE;
break;
}
//
// The long name didn't match so we need to check for a
// possible short name match. There is no match if the
// long name is one of the constant entries or already
// is 8dot3.
//
if (!(!FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT ) ||
UdfIs8dot3Name( IrpContext,
DirContext->CaseObjectName ))) {
//
// Allocate the shortname if it isn't already done.
//
if (DirContext->ShortObjectName.Buffer == NULL) {
DirContext->ShortObjectName.Buffer = FsRtlAllocatePoolWithTag( UdfPagedPool,
BYTE_COUNT_8_DOT_3,
TAG_SHORT_FILE_NAME );
DirContext->ShortObjectName.MaximumLength = BYTE_COUNT_8_DOT_3;
}
UdfGenerate8dot3Name( IrpContext,
&DirContext->PureObjectName,
&DirContext->ShortObjectName );
//
// Check if this name matches.
//
if (UdfIsNameInExpression( IrpContext,
&DirContext->ShortObjectName,
&Ccb->SearchExpression,
BooleanFlagOn( Ccb->Flags, CCB_FLAG_ENUM_NAME_EXP_HAS_WILD ))) {
//
// Let our caller know we found an entry.
//
Found = TRUE;
break;
}
}
}
}
return Found;
}
//
// Local support routine
//
VOID
UdfLookupFileEntryInEnumeration (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PCOMPOUND_DIR_ENUM_CONTEXT CompoundDirContext
)
/*++
Routine Description:
This routine retrieves the file entry associated with the current location in
the enumeration of a compound directory context.
Arguments:
Fcb - the directory being enumerated.
CompoundDirContext - a corresponding context for the enumeration.
Return Value:
None. Status may be raised on discovery of corruption.
--*/
{
PNSR_FID Fid;
PICBFILE Fe;
Fid = CompoundDirContext->DirContext.Fid;
//
// Figure out where the ICB we want is.
//
if (UdfIsFileIndexVirtual( CompoundDirContext->FileIndex.QuadPart )) {
//
// Synthesize! We only have to synthesize the self entry. The name is already done,
// so the remaining work is trivial.
//
ASSERT( Fid == NULL );
//
// Lift the FE corresponding to this directory
//
UdfCleanupIcbContext( IrpContext, &CompoundDirContext->IcbContext );
UdfInitializeIcbContextFromFcb( IrpContext,
&CompoundDirContext->IcbContext,
Fcb );
} else {
//
// Lift the FE corresponding to this FID.
//
ASSERT( Fid != NULL );
UdfCleanupIcbContext( IrpContext, &CompoundDirContext->IcbContext );
UdfInitializeIcbContext( IrpContext,
&CompoundDirContext->IcbContext,
Fcb->Vcb,
DESTAG_ID_NSR_FILE,
Fid->Icb.Start.Partition,
Fid->Icb.Start.Lbn,
Fid->Icb.Length.Length );
}
//
// Retrieve the ICB for inspection.
//
UdfLookupActiveIcb( IrpContext, &CompoundDirContext->IcbContext );
Fe = (PICBFILE) CompoundDirContext->IcbContext.Active.View;
//
// Perform some basic verification that the FE is of the proper type and that
// FID and FE agree as to the type of the object. We explicitly check that
// a legal filesystem-level FE type is discovered, even though we don't support
// them in other paths.
//
if (Fe->Destag.Ident != DESTAG_ID_NSR_FILE ||
(((Fid && FlagOn( Fid->Flags, NSR_FID_F_DIRECTORY )) ||
Fid == NULL) &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_DIRECTORY) ||
(Fe->Icbtag.FileType != ICBTAG_FILE_T_FILE &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_DIRECTORY &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_BLOCK_DEV &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_CHAR_DEV &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_FIFO &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_C_ISSOCK &&
Fe->Icbtag.FileType != ICBTAG_FILE_T_PATHLINK)) {
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
}
//
// Local support routine
//
BOOLEAN
UdfLookupInitialFileIndex (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PCOMPOUND_DIR_ENUM_CONTEXT CompoundDirContext,
IN PLONGLONG InitialIndex
)
/*++
Routine Description:
This routine begins the enumeration of a directory by setting the context
at the first avaliable virtual directory entry.
Arguments:
Fcb - the directory being enumerated.
CompoundDirContext - a corresponding context for the enumeration.
InitialIndex - an optional starting file index to base the enumeration.
Return Value:
TRUE will be returned if a valid entry is found at this offset, FALSE otherwise.
--*/
{
LONGLONG DirOffset;
if (UdfIsFileIndexVirtual( *InitialIndex )) {
//
// We only synthesize a single virtual directory entry. Position the context
// at the virtual self entry.
//
CompoundDirContext->FileIndex.QuadPart = UDF_FILE_INDEX_VIRTUAL_SELF;
return TRUE;
}
CompoundDirContext->FileIndex.QuadPart = *InitialIndex;
//
// Find the base offset in the directory and look it up.
//
DirOffset = UdfFileIndexToPhysicalOffset( *InitialIndex );
return UdfLookupInitialDirEntry( IrpContext,
Fcb,
&CompoundDirContext->DirContext,
&DirOffset );
}
//
// Local support routine
//
BOOLEAN
UdfLookupNextFileIndex (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PCOMPOUND_DIR_ENUM_CONTEXT CompoundDirContext
)
/*++
Routine Description:
This routine advances the enumeration of a virtual directory by one entry.
Arguments:
Fcb - the directory being enumerated.
CompoundDirContext - a corresponding context for the enumeration.
Return Value:
BOOLEAN True if another Fid is avaliable, False if we are at the end.
--*/
{
ULONG Advance;
BOOLEAN Result;
//
// Advance from the synthesized to the physical directory.
//
if (UdfIsFileIndexVirtual( CompoundDirContext->FileIndex.QuadPart )) {
Result = UdfLookupInitialDirEntry( IrpContext,
Fcb,
&CompoundDirContext->DirContext,
NULL );
if (Result) {
CompoundDirContext->FileIndex.QuadPart = UDF_FILE_INDEX_PHYSICAL;
}
return Result;
}
Advance = ISONsrFidSize( CompoundDirContext->DirContext.Fid );
//
// Advance to the next entry in this directory.
//
Result = UdfLookupNextDirEntry( IrpContext, Fcb, &CompoundDirContext->DirContext );
if (Result) {
CompoundDirContext->FileIndex.QuadPart += Advance;
}
return Result;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?