📄 pnp.c
字号:
// status to STATUS_SUCCESS (default is STATUS_NOT_SUPPORTED)
// before passing it down the driver stack
//
irp->IoStatus.Status = STATUS_SUCCESS;
break;
#endif // HANDLE_DEVICE_USAGE
case IRP_MN_QUERY_DEVICE_RELATIONS:
default:
break;
}
if (justReturnStatus){
/*
* We've already sent this IRP down the stack.
*/
}
else if (completeIrpHere){
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
else {
IoCopyCurrentIrpStackLocationToNext(irp);
status = IoCallDriver(devExt->topDevObj, irp);
}
return status;
}
#ifdef HANDLE_DEVICE_USAGE
NTSTATUS
VA_DeviceUsageNotification(struct DEVICE_EXTENSION *devExt, PIRP irp)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
BOOLEAN fSetPagable = FALSE; // whether we set the PAGABLE bit
/// before we passed-on this IRP
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(irp);
DBGOUT(( "DEVICE_USAGE_NOTIFICATION (Type==%d , InPath==%d)"
, irpSp->Parameters.UsageNotification.Type
, irpSp->Parameters.UsageNotification.InPath
));
DBGOUT(( " [devExt=0x%08X fltrDevObj=0x%08X]", devExt, devExt->filterDevObj ));
//
// Wait on the paging path event (to prevent several instances of
// this IRP from being processed at once)
//
status = KeWaitForSingleObject( &devExt->deviceUsageNotificationEvent
, Executive // wait reason
, KernelMode
, FALSE // not alertable
, NULL // no timeout
);
/*
* IMPORTANT NOTE: When to modify our DO_POWER_PAGABLE bit depends
* on whether it needs to be set or cleared. If the IRP indicates
* our PAGABLE bit should be set, then we must set it _before_
* forwarding the IRP down the driver stack (and possibly clear it
* afterward, if lower drivers fail the IRP). But if the IRP
* indicates that our PAGABLE bit should be cleared, then we must
* first forward the IRP to lower drivers, and then clear our bit
* only if the lower drivers return STATUS_SUCCESS.
*/
//
// If removing last paging file from this device...
//
if( irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging
&& !irpSp->Parameters.UsageNotification.InPath
&& devExt->pagingFileCount == 1 )
{
//
// Set DO_POWER_PAGABLE bit (if it was set at startup).
// If lower drivers fail this IRP, we'll clear it later.
//
DBGOUT(( "Removing last paging file..." ));
if( devExt->initialFlags & DO_POWER_PAGABLE )
{
DBGOUT(( "...so RE-setting PAGABLE bit" ));
devExt->filterDevObj->Flags |= DO_POWER_PAGABLE;
fSetPagable = TRUE;
}
else
{
DBGOUT(( "...but PAGABLE bit wasn't set initially, so not setting it now." ));
}
}
//
// Forward the irp synchronously
//
IoCopyCurrentIrpStackLocationToNext( irp );
status = CallNextDriverSync( devExt, irp );
//
// Now deal with the failure and success cases.
//
if( ! NT_SUCCESS(status) )
{
//
// Lower drivers failed the IRP, so _undo_ any changes we
// made before passing-on the IRP to those drivers.
//
if( fSetPagable )
{
DBGOUT(( "IRP was failed, so UN-setting PAGABLE bit" ));
devExt->filterDevObj->Flags &= ~DO_POWER_PAGABLE;
}
}
else
{
//
// Lower drivers returned SUCCESS, so we can do everything
// that must be done in response to this IRP...
//
switch( irpSp->Parameters.UsageNotification.Type )
{
case DeviceUsageTypeHibernation:
// Adjust counter
IoAdjustPagingPathCount( &devExt->hibernationFileCount,
irpSp->Parameters.UsageNotification.InPath );
DBGOUT(( "Num. Hibernation files is now %d", devExt->hibernationFileCount ));
ASSERT( devExt->hibernationFileCount >= 0 );
break;
case DeviceUsageTypeDumpFile:
// Adjust counter
IoAdjustPagingPathCount( &devExt->crashdumpFileCount,
irpSp->Parameters.UsageNotification.InPath );
DBGOUT(( "Num. Crashdump files is now %d", devExt->crashdumpFileCount ));
ASSERT( devExt->crashdumpFileCount >= 0 );
break;
case DeviceUsageTypePaging:
// Adjust counter
IoAdjustPagingPathCount( &devExt->pagingFileCount,
irpSp->Parameters.UsageNotification.InPath );
DBGOUT(( "Num. Paging files is now %d", devExt->pagingFileCount ));
ASSERT( devExt->pagingFileCount >= 0 );
//
// If we've just switched between being pageable<->nonpageable...
//
if( irpSp->Parameters.UsageNotification.InPath
&& devExt->pagingFileCount == 1 )
{
//
// Just added a paging file, so clear the PAGABLE
// flag, and lock-down the code for all routines
// that could be called at IRQL >= DISPATCH_LEVEL
// (so that they're _non-pageable_).
//
DBGOUT(( "Just added first paging file..." ));
DBGOUT(( "...so clearing PAGABLE bit" ));
devExt->filterDevObj->Flags &= ~DO_POWER_PAGABLE;
DBGOUT(( "LOCKing some driver code (non-pageable) (b/c paging path)" ));
devExt->pagingPathUnlockHandle = MmLockPagableCodeSection( VA_Power ); // some func that's inside the code section that we want to lock
ASSERT( NULL != devExt->pagingPathUnlockHandle );
}
else if ( !irpSp->Parameters.UsageNotification.InPath
&& devExt->pagingFileCount == 0 )
{
//
// Just removed the last paging file, but we
// already set the PAGABLE flag (if necessary)
// before forwarding IRP, so just remove the
// _paging-path_ lock from this driver. (NOTE:
// initial-condition lock might still be in place,
// but that's what we want.)
//
DBGOUT(( "UNLOCKing some driver code (pageable) (b/c paging path)" ));
ASSERT( NULL != devExt->pagingPathUnlockHandle );
MmUnlockPagableImageSection( devExt->pagingPathUnlockHandle );
devExt->pagingPathUnlockHandle = NULL;
}
break;
default:
ASSERT( FALSE ); // should never get here (b/c checked for invalid Type earlier)
} //END: switch on Type of special-file
//
// Invalidate state, so that certain flags will get updated
//
IoInvalidateDeviceState( devExt->physicalDevObj );
}//END: handling of irp success/failure cases
//
// Set event so that the next DEVICE_USAGE_NOTIFICATION IRP that
// comes along can be processed.
//
KeSetEvent( &devExt->deviceUsageNotificationEvent
, IO_NO_INCREMENT
, FALSE
);
//
// Complete the irp
//
IoCompleteRequest( irp, IO_NO_INCREMENT );
return status;
}
#endif // HANDLE_DEVICE_USAGE
NTSTATUS GetDeviceCapabilities(struct DEVICE_EXTENSION *devExt)
/*++
Routine Description:
Function retrieves the DEVICE_CAPABILITIES descriptor from the device
Arguments:
devExt - device extension for targetted device object
Return Value:
NT status code
--*/
{
NTSTATUS status;
PIRP irp;
PAGED_CODE();
irp = IoAllocateIrp(devExt->topDevObj->StackSize, FALSE);
if (irp){
PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(irp);
// must initialize DeviceCapabilities before sending...
RtlZeroMemory( &devExt->deviceCapabilities,
sizeof(DEVICE_CAPABILITIES));
devExt->deviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
devExt->deviceCapabilities.Version = 1;
devExt->deviceCapabilities.Address = -1;
devExt->deviceCapabilities.UINumber = -1;
// setup irp stack location...
nextSp->MajorFunction = IRP_MJ_PNP;
nextSp->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
nextSp->Parameters.DeviceCapabilities.Capabilities =
&devExt->deviceCapabilities;
/*
* For any IRP you create, you must set the default status
* to STATUS_NOT_SUPPORTED before sending it.
*/
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
status = CallNextDriverSync(devExt, irp);
IoFreeIrp(irp);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
ASSERT(NT_SUCCESS(status));
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -