📄 pnp.c
字号:
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
pnp.c
Abstract: NULL filter driver -- boilerplate code
Author:
ervinp
Environment:
Kernel mode
Revision History:
--*/
#include <WDM.H>
#include "filter.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, VA_PnP)
#pragma alloc_text(PAGE, GetDeviceCapabilities)
#ifdef HANDLE_DEVICE_USAGE
#pragma alloc_text(PAGE, VA_DeviceUsageNotification)
#endif // HANDLE_DEVICE_USAGE
#endif
NTSTATUS VA_PnP(struct DEVICE_EXTENSION *devExt, PIRP irp)
/*++
Routine Description:
Dispatch routine for PnP IRPs (MajorFunction == IRP_MJ_PNP)
Arguments:
devExt - device extension for the targetted device object
irp - IO Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN completeIrpHere = FALSE;
BOOLEAN justReturnStatus = FALSE;
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(irp);
DBGOUT(("VA_PnP, minorFunc = %d ", (ULONG)irpSp->MinorFunction));
switch (irpSp->MinorFunction){
case IRP_MN_START_DEVICE:
DBGOUT(("START_DEVICE"));
devExt->state = STATE_STARTING;
/*
* First, send the START_DEVICE irp down the stack
* synchronously to start the lower stack.
* We cannot do anything with our device object
* before propagating the START_DEVICE this way.
*/
IoCopyCurrentIrpStackLocationToNext(irp);
status = CallNextDriverSync(devExt, irp);
if (NT_SUCCESS(status)){
/*
* Now that the lower stack is started,
* do any initialization required by this device object.
*/
status = GetDeviceCapabilities(devExt);
if (NT_SUCCESS(status)){
devExt->state = STATE_STARTED;
}
else {
devExt->state = STATE_START_FAILED;
}
}
else {
devExt->state = STATE_START_FAILED;
}
completeIrpHere = TRUE;
break;
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
#ifdef HANDLE_DEVICE_USAGE
//
// Need to fail these IRPs if a paging, hibernation, or crashdump
// file is currently open on this device
//
if( devExt->pagingFileCount != 0
|| devExt->hibernationFileCount != 0
|| devExt->crashdumpFileCount != 0 )
{
// Fail the IRP
DBGOUT(( "Failing QUERY_(STOP,REMOVE)_DEVICE request b/c "
"paging, hiber, or crashdump file is present on device." ));
status = STATUS_UNSUCCESSFUL;
completeIrpHere = TRUE;
}
else
{
// We'll just pass this IRP down the driver stack. But
// first, must change the IRP's status to STATUS_SUCCESS
// (default is STATUS_NOT_SUPPORTED)
irp->IoStatus.Status = STATUS_SUCCESS;
}
#else
/*
* We will pass this IRP down the driver stack.
* However, we need to change the default status
* from STATUS_NOT_SUPPORTED to STATUS_SUCCESS.
*/
irp->IoStatus.Status = STATUS_SUCCESS;
#endif
break;
case IRP_MN_STOP_DEVICE:
if (devExt->state == STATE_SUSPENDED){
status = STATUS_DEVICE_POWER_FAILURE;
completeIrpHere = TRUE;
}
else {
/*
* Only set state to STOPPED if the device was
* previously started successfully.
*/
if (devExt->state == STATE_STARTED){
devExt->state = STATE_STOPPED;
}
}
break;
case IRP_MN_SURPRISE_REMOVAL:
DBGOUT(("SURPRISE_REMOVAL"));
/*
* We will pass this IRP down the driver stack.
* However, we need to change the default status
* from STATUS_NOT_SUPPORTED to STATUS_SUCCESS.
*/
irp->IoStatus.Status = STATUS_SUCCESS;
/*
* For now just set the STATE_REMOVING state so that
* we don't do any more IO. We are guaranteed to get
* IRP_MN_REMOVE_DEVICE soon; we'll do the rest of
* the remove processing there.
*/
devExt->state = STATE_REMOVING;
break;
case IRP_MN_REMOVE_DEVICE:
/*
* Check the current state to guard against multiple
* REMOVE_DEVICE IRPs.
*/
DBGOUT(("REMOVE_DEVICE"));
if (devExt->state != STATE_REMOVED){
devExt->state = STATE_REMOVED;
/*
* Send the REMOVE IRP down the stack asynchronously.
* Do not synchronize sending down the REMOVE_DEVICE
* IRP, because the REMOVE_DEVICE IRP must be sent
* down and completed all the way back up to the sender
* before we continue.
*/
IoCopyCurrentIrpStackLocationToNext(irp);
status = IoCallDriver(devExt->topDevObj, irp);
justReturnStatus = TRUE;
DBGOUT(("REMOVE_DEVICE - waiting for %d irps to complete...",
devExt->pendingActionCount));
/*
* We must for all outstanding IO to complete before
* completing the REMOVE_DEVICE IRP.
*
* First do an extra decrement on the pendingActionCount.
* This will cause pendingActionCount to eventually
* go to -1 once all asynchronous actions on this
* device object are complete.
* Then wait on the event that gets set when the
* pendingActionCount actually reaches -1.
*/
DecrementPendingActionCount(devExt);
KeWaitForSingleObject( &devExt->removeEvent,
Executive, // wait reason
KernelMode,
FALSE, // not alertable
NULL ); // no timeout
DBGOUT(("REMOVE_DEVICE - ... DONE waiting. "));
#ifdef HANDLE_DEVICE_USAGE
/*
* If we locked-down certain paged code sections earlier
* because of this device, then need to unlock them now
* (before calling IoDeleteDevice)
*/
if( NULL != devExt->pagingPathUnlockHandle )
{
DBGOUT(( "UNLOCKing some driver code (non-pageable) (b/c paging path)" ));
MmUnlockPagableImageSection( devExt->pagingPathUnlockHandle );
devExt->pagingPathUnlockHandle = NULL;
}
if( NULL != devExt->initUnlockHandle )
{
DBGOUT(( "UNLOCKing some driver code (non-pageable) (b/c init conditions)" ));
MmUnlockPagableImageSection( devExt->initUnlockHandle );
devExt->initUnlockHandle = NULL;
}
#endif // HANDLE_DEVICE_USAGE
/*
* Detach our device object from the lower
* device object stack.
*/
IoDetachDevice(devExt->topDevObj);
/*
* Delete our device object.
* This will also delete the associated device extension.
*/
IoDeleteDevice(devExt->filterDevObj);
}
break;
#ifdef HANDLE_DEVICE_USAGE
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
//
// Make sure the Type of this UsageNotification is one that we handle
//
if( irpSp->Parameters.UsageNotification.Type != DeviceUsageTypePaging
&& irpSp->Parameters.UsageNotification.Type != DeviceUsageTypeHibernation
&& irpSp->Parameters.UsageNotification.Type != DeviceUsageTypeDumpFile )
{
break; // out of the big switch statement (and just forward this IRP)
}
status = VA_DeviceUsageNotification(devExt, irp);
justReturnStatus = TRUE;
break;
#endif // HANDLE_DEVICE_USAGE
#ifdef HANDLE_DEVICE_USAGE
case IRP_MN_QUERY_PNP_DEVICE_STATE:
//
// If a paging, hibernation, or crashdump file is currently open
// on this device, must set NOT_DISABLEABLE flag in DeviceState
//
if( devExt->pagingFileCount != 0
|| devExt->hibernationFileCount != 0
|| devExt->crashdumpFileCount != 0 )
{
// Mark the device as not disableable
PPNP_DEVICE_STATE pDeviceState;
pDeviceState = (PPNP_DEVICE_STATE) &irp->IoStatus.Information;
*pDeviceState |= PNP_DEVICE_NOT_DISABLEABLE;
}
//
// We _did_ handle this IRP (as best we could), so set IRP's
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -