📄 strucsup.c
字号:
DebugTrace(-1, Dbg, "FatCreateCcb -> %08lx\n", Ccb);
UNREFERENCED_PARAMETER( IrpContext );
return Ccb;
}
VOID
FatDeallocateCcbStrings(
IN PCCB Ccb
)
/*++
Routine Description:
This routine deallocates CCB query templates
Arguments:
Ccb - Supplies the CCB
Return Value:
None
--*/
{
//
// If we allocated query template buffers, deallocate them now.
//
if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_UNICODE)) {
ASSERT( Ccb->UnicodeQueryTemplate.Buffer);
ASSERT( !FlagOn( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT));
RtlFreeUnicodeString( &Ccb->UnicodeQueryTemplate );
}
if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT)) {
ASSERT( Ccb->OemQueryTemplate.Wild.Buffer );
ASSERT( !FlagOn( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT));
RtlFreeOemString( &Ccb->OemQueryTemplate.Wild );
}
ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT | CCB_FLAG_FREE_UNICODE);
}
VOID
FatDeleteCcb (
IN PIRP_CONTEXT IrpContext,
IN PCCB *Ccb
)
/*++
Routine Description:
This routine deallocates and removes the specified CCB record
from the Fat in memory data structures
Arguments:
Ccb - Supplies the CCB to remove
Return Value:
None
--*/
{
DebugTrace(+1, Dbg, "FatDeleteCcb, Ccb = %08lx\n", *Ccb);
FatDeallocateCcbStrings( *Ccb);
//
// Deallocate the Ccb record
//
FatFreeCcb( *Ccb );
*Ccb = NULL;
//
// return and tell the caller
//
DebugTrace(-1, Dbg, "FatDeleteCcb -> VOID\n", 0);
UNREFERENCED_PARAMETER( IrpContext );
}
PIRP_CONTEXT
FatCreateIrpContext (
IN PIRP Irp,
IN BOOLEAN Wait
)
/*++
Routine Description:
This routine creates a new IRP_CONTEXT record
Arguments:
Irp - Supplies the originating Irp.
Wait - Supplies the wait value to store in the context
Return Value:
PIRP_CONTEXT - returns a pointer to the newly allocate IRP_CONTEXT Record
--*/
{
PIRP_CONTEXT IrpContext;
PIO_STACK_LOCATION IrpSp;
DebugTrace(+1, Dbg, "FatCreateIrpContext\n", 0);
IrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// The only operations a filesystem device object should ever receive
// are create/teardown of fsdo handles and operations which do not
// occur in the context of fileobjects (i.e., mount).
//
if (FatDeviceIsFatFsdo( IrpSp->DeviceObject)) {
if (IrpSp->FileObject != NULL &&
IrpSp->MajorFunction != IRP_MJ_CREATE &&
IrpSp->MajorFunction != IRP_MJ_CLEANUP &&
IrpSp->MajorFunction != IRP_MJ_CLOSE) {
ExRaiseStatus( STATUS_INVALID_DEVICE_REQUEST );
}
ASSERT( IrpSp->FileObject != NULL ||
(IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST &&
IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_INVALIDATE_VOLUMES) ||
(IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
IrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME ) ||
IrpSp->MajorFunction == IRP_MJ_SHUTDOWN );
}
//
// Attemtp to allocate from the region first and failing that allocate
// from pool.
//
DebugDoit( FatFsdEntryCount += 1);
IrpContext = FatAllocateIrpContext();
//
// Zero out the irp context.
//
RtlZeroMemory( IrpContext, sizeof(IRP_CONTEXT) );
//
// Set the proper node type code and node byte size
//
IrpContext->NodeTypeCode = FAT_NTC_IRP_CONTEXT;
IrpContext->NodeByteSize = sizeof(IRP_CONTEXT);
//
// Set the originating Irp field
//
IrpContext->OriginatingIrp = Irp;
//
// Major/Minor Function codes
//
IrpContext->MajorFunction = IrpSp->MajorFunction;
IrpContext->MinorFunction = IrpSp->MinorFunction;
//
// Copy RealDevice for workque algorithms, and also set Write Through
// and Removable Media if there is a file object. Only file system
// control Irps won't have a file object, and they should all have
// a Vpb as the first IrpSp location.
//
if (IrpSp->FileObject != NULL) {
PVCB Vcb;
PFILE_OBJECT FileObject = IrpSp->FileObject;
IrpContext->RealDevice = FileObject->DeviceObject;
Vcb = IrpContext->Vcb = &((PVOLUME_DEVICE_OBJECT)(IrpSp->DeviceObject))->Vcb;
//
// See if the request is Write Through.
//
if (IsFileWriteThrough( FileObject, Vcb )) {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
}
} else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {
IrpContext->RealDevice = IrpSp->Parameters.MountVolume.Vpb->RealDevice;
}
//
// Set the wait parameter
//
if (Wait) { SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); }
//
// Set the recursive file system call parameter. We set it true if
// the TopLevelIrp field in the thread local storage is not the current
// irp, otherwise we leave it as FALSE.
//
if ( IoGetTopLevelIrp() != Irp) {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL);
}
//
// return and tell the caller
//
DebugTrace(-1, Dbg, "FatCreateIrpContext -> %08lx\n", IrpContext);
return IrpContext;
}
VOID
FatDeleteIrpContext_Real (
IN PIRP_CONTEXT IrpContext
)
/*++
Routine Description:
This routine deallocates and removes the specified IRP_CONTEXT record
from the Fat in memory data structures. It should only be called
by FatCompleteRequest.
Arguments:
IrpContext - Supplies the IRP_CONTEXT to remove
Return Value:
None
--*/
{
DebugTrace(+1, Dbg, "FatDeleteIrpContext, IrpContext = %08lx\n", IrpContext);
ASSERT( IrpContext->NodeTypeCode == FAT_NTC_IRP_CONTEXT );
ASSERT( IrpContext->PinCount == 0 );
//
// If there is a FatIoContext that was allocated, free it.
//
if (IrpContext->FatIoContext != NULL) {
if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT)) {
if (IrpContext->FatIoContext->ZeroMdl) {
IoFreeMdl( IrpContext->FatIoContext->ZeroMdl );
}
ExFreePool( IrpContext->FatIoContext );
}
}
//
// Drop the IrpContext.
//
FatFreeIrpContext( IrpContext );
//
// return and tell the caller
//
DebugTrace(-1, Dbg, "FatDeleteIrpContext -> VOID\n", 0);
return;
}
PFCB
FatGetNextFcbBottomUp (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb OPTIONAL,
IN PFCB TerminationFcb
)
/*++
Routine Description:
This routine is used to iterate through Fcbs in a tree. In order to match
the lockorder for getting multiple Fcbs (so this can be used for acquiring
all Fcbs), this version does a bottom-up enumeration.
This is different than the old one, now called TopDown. The problem with
lockorder was very well hidden.
The transition rule is still pretty simple:
A) If you have an adjacent sibling, go to it
1) Descend to its leftmost child
B) Else go to your parent
If this routine is called with in invalid TerminationFcb it will fail,
badly.
The TerminationFcb is the last Fcb returned in the enumeration.
This method is incompatible with the possibility that ancestors may vanish
based on operations done on the last returned node. For instance,
FatPurgeReferencedFileObjects cannot use BottomUp enumeration.
Arguments:
Fcb - Supplies the current Fcb. This is NULL if enumeration is starting.
TerminationFcb - The root Fcb of the tree in which the enumeration starts
and at which it inclusively stops.
Return Value:
The next Fcb in the enumeration, or NULL if Fcb was the final one.
--*/
{
PFCB NextFcb;
ASSERT( FatVcbAcquiredExclusive( IrpContext, TerminationFcb->Vcb ) ||
FlagOn( TerminationFcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );
//
// Do we need to begin the enumeration?
//
if (Fcb != NULL) {
//
// Did we complete?
//
if (Fcb == TerminationFcb) {
return NULL;
}
//
// Do we have a sibling to return?
//
NextFcb = FatGetNextSibling( Fcb );
//
// If not, return our parent. We are done with this branch.
//
if (NextFcb == NULL) {
return Fcb->ParentDcb;
}
} else {
NextFcb = TerminationFcb;
}
//
// Decend to its furthest child (if it exists) and return it.
//
for (;
NodeType( NextFcb ) != FAT_NTC_FCB && FatGetFirstChild( NextFcb ) != NULL;
NextFcb = FatGetFirstChild( NextFcb )) {
}
return NextFcb;
}
PFCB
FatGetNextFcbTopDown (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFCB TerminationFcb
)
/*++
Routine Description:
This routine is used to iterate through Fcbs in a tree, from the top down.
The rule is very simple:
A) If you have a child, go to it, else
B) If you have an older sibling, go to it, else
C) Go to your parent's older sibling.
If this routine is called with in invalid TerminationFcb it will fail,
badly.
The Termination Fcb is never returned. If it is the root of the tree you
are traversing, visit it first.
This routine never returns direct ancestors of Fcb, and thus is useful when
making Fcb's go away (which may tear up the tree).
Arguments:
Fcb - Supplies the current Fcb
TerminationFcb - The Fcb at which the enumeration should (non-inclusivly)
stop. Assumed to be a directory.
Return Value:
The next Fcb in the enumeration, or NULL if Fcb was the final one.
--*/
{
PFCB Sibling;
ASSERT( FatVcbAcquiredExclusive( IrpContext, Fcb->Vcb ) ||
FlagOn( Fcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );
//
// If this was a directory (ie. not a file), get the child. If
// there aren't any children and this is our termination Fcb,
// return NULL.
//
if ( ((NodeType(Fcb) == FAT_NTC_DCB) ||
(NodeType(Fcb) == FAT_NTC_ROOT_DCB)) &&
!IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) ) {
return FatGetFirstChild( Fcb );
}
//
// Were we only meant to do one iteration?
//
if ( Fcb == TerminationFcb ) {
return NULL;
}
Sibling = FatGetNextSibling(Fcb);
while (TRUE) {
//
// Do we still have an "older" sibling in this directory who is
// not the termination Fcb?
//
if ( Sibling != NULL ) {
return (Sibling != TerminationFcb) ? Sibling : NULL;
}
//
// OK, let's move on to out parent and see if he is the termination
// node or has any older siblings.
//
if ( Fcb->ParentDcb == TerminationFcb ) {
return NULL;
}
Fcb = F
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -