📄 dirsup.c
字号:
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
DirSup.c
Abstract:
This module implements the support for walking across on-disk directory
structures.
Author:
Dan Lovinger [DanLo] 11-Jun-1996
Revision History:
--*/
#include "UdfProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (UDFS_BUG_CHECK_DIRSUP)
//
// The local debug trace level
//
#define Dbg (UDFS_DEBUG_LEVEL_DIRSUP)
//
// Local support routines.
//
BOOLEAN
UdfLookupDirEntryPostProcessing (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PDIR_ENUM_CONTEXT DirContext,
IN BOOLEAN ReturnError
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, UdfCleanupDirContext)
#pragma alloc_text(PAGE, UdfFindDirEntry)
#pragma alloc_text(PAGE, UdfInitializeDirContext)
#pragma alloc_text(PAGE, UdfLookupDirEntryPostProcessing)
#pragma alloc_text(PAGE, UdfLookupInitialDirEntry)
#pragma alloc_text(PAGE, UdfLookupNextDirEntry)
#pragma alloc_text(PAGE, UdfUpdateDirNames)
#endif
VOID
UdfInitializeDirContext (
IN PIRP_CONTEXT IrpContext,
IN PDIR_ENUM_CONTEXT DirContext
)
/*++
Routine Description:
This routine initializes a directory enumeartion context.
Call this exactly once in the lifetime of a context.
Arguments:
DirContext - a context to initialize
Return Value:
None.
--*/
{
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
//
// Provide defaults for fields, nothing too special.
//
RtlZeroMemory( DirContext, sizeof(DIR_ENUM_CONTEXT) );
}
VOID
UdfCleanupDirContext (
IN PIRP_CONTEXT IrpContext,
IN PDIR_ENUM_CONTEXT DirContext
)
/*++
Routine Description:
This routine cleans up a directory enumeration context for reuse.
Arguments:
DirContext - a context to clean.
Return Value:
None.
--*/
{
PAGED_CODE();
//
// Check input.
//
ASSERT_IRP_CONTEXT( IrpContext );
//
// Dump the allocation we store the triple of names in.
//
UdfFreePool( &DirContext->NameBuffer );
//
// And the short name.
//
UdfFreePool( &DirContext->ShortObjectName.Buffer );
//
// Unpin the view.
//
UdfUnpinData( IrpContext, &DirContext->Bcb );
//
// Free a buffered Fid that may remain.
//
if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_FID_BUFFERED )) {
UdfFreePool( &DirContext->Fid );
}
//
// Zero everything else out.
//
RtlZeroMemory( DirContext, sizeof( DIR_ENUM_CONTEXT ) );
}
BOOLEAN
UdfLookupInitialDirEntry (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PDIR_ENUM_CONTEXT DirContext,
IN PLONGLONG InitialOffset OPTIONAL
)
/*++
Routine Description:
This routine begins the enumeration of a directory by setting the context
at the first avaliable directory entry.
Arguments:
Fcb - the directory being enumerated.
DirContext - a corresponding context for the enumeration.
InitialOffset - an optional starting byte offset to base the enumeration.
Return Value:
If InitialOffset is unspecified, TRUE will always be returned. Failure will result
in a raised status indicating corruption.
If InitialOffset is specified, TRUE will be returned if a valid entry is found at this
offset, FALSE otherwise.
--*/
{
BOOLEAN Result;
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_FCB_INDEX( Fcb );
//
// Create the internal stream if it isn't already in place.
//
if (Fcb->FileObject == NULL) {
UdfCreateInternalStream( IrpContext, Fcb->Vcb, Fcb );
}
//
// Reset the flags.
//
DirContext->Flags = 0;
if (InitialOffset) {
//
// If we are beginning in the middle of the stream, adjust the sanity check flags.
//
if (*InitialOffset != 0) {
DirContext->Flags = DIR_CONTEXT_FLAG_SEEN_NONCONSTANT | DIR_CONTEXT_FLAG_SEEN_PARENT;
}
//
// Now set up the range we will map. This is constrained by the size of a cache view.
//
DirContext->BaseOffset.QuadPart = GenericTruncate( *InitialOffset, VACB_MAPPING_GRANULARITY );
DirContext->ViewOffset = (ULONG) GenericOffset( *InitialOffset, VACB_MAPPING_GRANULARITY );
} else {
//
// Map at the beginning.
//
DirContext->BaseOffset.QuadPart = 0;
DirContext->ViewOffset = 0;
}
//
// Contain the view length by the size of the stream and map.
//
DirContext->ViewLength = VACB_MAPPING_GRANULARITY;
if (DirContext->BaseOffset.QuadPart + DirContext->ViewLength > Fcb->FileSize.QuadPart) {
DirContext->ViewLength = (ULONG) (Fcb->FileSize.QuadPart - DirContext->BaseOffset.QuadPart);
}
UdfUnpinData( IrpContext, &DirContext->Bcb );
CcMapData( Fcb->FileObject,
&DirContext->BaseOffset,
DirContext->ViewLength,
TRUE,
&DirContext->Bcb,
&DirContext->View );
DirContext->Fid = Add2Ptr( DirContext->View, DirContext->ViewOffset, PNSR_FID );
//
// The state of the context is now valid. Tail off into our common post-processor
// to finish the work.
//
return UdfLookupDirEntryPostProcessing( IrpContext,
Fcb,
DirContext,
(BOOLEAN) (InitialOffset != NULL));
}
BOOLEAN
UdfLookupNextDirEntry (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PDIR_ENUM_CONTEXT DirContext
)
/*++
Routine Description:
This routine advances the enumeration of a directory by one entry.
Arguments:
Fcb - the directory being enumerated.
DirContext - a corresponding context for the enumeration.
Return Value:
BOOLEAN True if another Fid is avaliable, False if we are at the end.
--*/
{
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_FCB_INDEX( Fcb );
//
// If we have reached the end, stop.
//
if (DirContext->BaseOffset.QuadPart + DirContext->NextFidOffset == Fcb->FileSize.QuadPart) {
return FALSE;
}
//
// If the previous Fid was buffered, dismantle it now.
//
if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_FID_BUFFERED )) {
ClearFlag( DirContext->Flags, DIR_CONTEXT_FLAG_FID_BUFFERED );
UdfFreePool( &DirContext->Fid );
}
//
// Move the pointers based on the knowledge generated in the previous iteration.
//
DirContext->ViewOffset = DirContext->NextFidOffset;
DirContext->Fid = Add2Ptr( DirContext->View, DirContext->ViewOffset, PNSR_FID );
//
// The state of the context is now valid. Tail off into our common post-processor
// to finish the work.
//
return UdfLookupDirEntryPostProcessing( IrpContext,
Fcb,
DirContext,
FALSE );
}
VOID
UdfUpdateDirNames (
IN PIRP_CONTEXT IrpContext,
IN PDIR_ENUM_CONTEXT DirContext,
IN BOOLEAN IgnoreCase
)
/*++
Routine Description:
This routine fills in the non-short names of a directory enumeration context
for the Fid currently referenced.
Arguments:
DirContext - a corresponding context to fill in.
IgnoreCase - whether the caller wants to be insensitive to case.
Return Value:
None.
--*/
{
PUCHAR NameDstring;
BOOLEAN ContainsIllegal;
USHORT NameLength;
USHORT BufferLength;
USHORT PresentLength;
PAGED_CODE();
//
// Check input.
//
ASSERT_IRP_CONTEXT( IrpContext );
DebugTrace(( +1, Dbg, "UdfUpdateDirNames\n" ));
//
// Handle the case of the self directory entry.
//
if (DirContext->Fid == NULL) {
//
// Simply synthesize
//
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -