📄 pnp.c
字号:
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
Pnp.c
Abstract:
This module implements the Plug and Play routines for FAT called by
the dispatch driver.
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_PNP)
#define Dbg (DEBUG_TRACE_PNP)
NTSTATUS
FatPnpQueryRemove (
PIRP_CONTEXT IrpContext,
PIRP Irp,
PVCB Vcb
);
NTSTATUS
FatPnpRemove (
PIRP_CONTEXT IrpContext,
PIRP Irp,
PVCB Vcb
);
NTSTATUS
FatPnpSurpriseRemove (
PIRP_CONTEXT IrpContext,
PIRP Irp,
PVCB Vcb
);
NTSTATUS
FatPnpCancelRemove (
PIRP_CONTEXT IrpContext,
PIRP Irp,
PVCB Vcb
);
NTSTATUS
FatPnpCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatCommonPnp)
#pragma alloc_text(PAGE, FatFsdPnp)
#pragma alloc_text(PAGE, FatPnpCancelRemove)
#pragma alloc_text(PAGE, FatPnpQueryRemove)
#pragma alloc_text(PAGE, FatPnpRemove)
#pragma alloc_text(PAGE, FatPnpSurpriseRemove)
#endif
NTSTATUS
FatFsdPnp (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of PnP operations
Arguments:
VolumeDeviceObject - Supplies the volume device object where the
file exists
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The FSD status for the IRP
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
BOOLEAN Wait;
DebugTrace(+1, Dbg, "FatFsdPnp\n", 0);
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
//
// We expect there to never be a fileobject, in which case we will always
// wait. Since at the moment we don't have any concept of pending Pnp
// operations, this is a bit nitpicky.
//
if (IoGetCurrentIrpStackLocation( Irp )->FileObject == NULL) {
Wait = TRUE;
} else {
Wait = CanFsdWait( Irp );
}
IrpContext = FatCreateIrpContext( Irp, Wait );
Status = FatCommonPnp( IrpContext, Irp );
} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdPnp -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatCommonPnp (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for doing PnP operations called
by both the fsd and fsp threads
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PVOLUME_DEVICE_OBJECT OurDeviceObject;
PVCB Vcb;
//
// Force everything to wait.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
//
// Get the current Irp stack location.
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Find our Vcb. This is tricky since we have no file object in the Irp.
//
OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject;
//
// Take the global lock to synchronise against volume teardown.
//
FatAcquireExclusiveGlobal( IrpContext );
//
// Make sure this device object really is big enough to be a volume device
// object. If it isn't, we need to get out before we try to reference some
// field that takes us past the end of an ordinary device object.
//
if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) ||
NodeType( &OurDeviceObject->Vcb ) != FAT_NTC_VCB) {
//
// We were called with something we don't understand.
//
FatReleaseGlobal( IrpContext );
Status = STATUS_INVALID_PARAMETER;
FatCompleteRequest( IrpContext, Irp, Status );
return Status;
}
Vcb = &OurDeviceObject->Vcb;
//
// Case on the minor code.
//
switch ( IrpSp->MinorFunction ) {
case IRP_MN_QUERY_REMOVE_DEVICE:
Status = FatPnpQueryRemove( IrpContext, Irp, Vcb );
break;
case IRP_MN_SURPRISE_REMOVAL:
Status = FatPnpSurpriseRemove( IrpContext, Irp, Vcb );
break;
case IRP_MN_REMOVE_DEVICE:
Status = FatPnpRemove( IrpContext, Irp, Vcb );
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
Status = FatPnpCancelRemove( IrpContext, Irp, Vcb );
break;
default:
FatReleaseGlobal( IrpContext );
//
// Just pass the IRP on. As we do not need to be in the
// way on return, ellide ourselves out of the stack.
//
IoSkipCurrentIrpStackLocation( Irp );
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
//
// Cleanup our Irp Context. The driver has completed the Irp.
//
FatCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
break;
}
return Status;
}
VOID
FatPnpAdjustVpbRefCount(
IN PVCB Vcb,
IN ULONG Delta
)
{
KIRQL OldIrql;
IoAcquireVpbSpinLock( &OldIrql);
Vcb->Vpb->ReferenceCount += Delta;
IoReleaseVpbSpinLock( OldIrql);
}
NTSTATUS
FatPnpQueryRemove (
PIRP_CONTEXT IrpContext,
PIRP Irp,
PVCB Vcb
)
/*++
Routine Description:
This routine handles the PnP query remove operation. The filesystem
is responsible for answering whether there are any reasons it sees
that the volume can not go away (and the device removed). Initiation
of the dismount begins when we answer yes to this question.
Query will be followed by a Cancel or Remove.
Arguments:
Irp - Supplies the Irp to process
Vcb - Supplies the volume being queried.
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
KEVENT Event;
BOOLEAN VcbDeleted = FALSE;
BOOLEAN GlobalHeld = TRUE;
//
// Having said yes to a QUERY, any communication with the
// underlying storage stack is undefined (and may block)
// until the bounding CANCEL or REMOVE is sent.
//
FatAcquireExclusiveVcb( IrpContext, Vcb );
FatReleaseGlobal( IrpContext);
GlobalHeld = FALSE;
try {
Status = FatLockVolumeInternal( IrpContext, Vcb, NULL );
//
// Drop an additional reference on the Vpb so that the volume cannot be
// torn down when we drop all the locks below.
//
FatPnpAdjustVpbRefCount( Vcb, 1);
//
// Drop and reacquire the resources in the right order.
//
FatReleaseVcb( IrpContext, Vcb );
FatAcquireExclusiveGlobal( IrpContext );
GlobalHeld = TRUE;
FatAcquireExclusiveVcb( IrpContext, Vcb );
//
// Drop the reference we added above.
//
FatPnpAdjustVpbRefCount( Vcb, -1);
if (NT_SUCCESS( Status )) {
//
// With the volume held locked, note that we must finalize as much
// as possible right now.
//
FatFlushAndCleanVolume( IrpContext, Irp, Vcb, Flush );
//
// We need to pass this down before starting the dismount, which
// could disconnect us immediately from the stack.
//
//
// Get the next stack location, and copy over the stack location
//
IoCopyCurrentIrpStackLocationToNext( Irp );
//
// Set up the completion routine
//
KeInitializeEvent( &Event, NotificationEvent, FALSE );
IoSetCompletionRoutine( Irp,
FatPnpCompletionRoutine,
&Event,
TRUE,
TRUE,
TRUE );
//
// Send the request and wait.
//
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject( &Event,
Executive,
KernelMode,
FALSE,
NULL );
Status = Irp->IoStatus.Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -