📄 fdopnp.c
字号:
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
STATUS_SUCCESS - on success,
an appropriate error status - otherwise
--*/
{
PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;
ULONG filterResourceMethod = PPT_FORCE_USE_NO_IRQ;
PIO_RESOURCE_REQUIREMENTS_LIST pResourceRequirementsIn;
NTSTATUS status;
//
// DDK Rule: Add on the way down, modify on the way up. We are modifying
// the resource list so let the drivers beneath us handle this IRP first.
//
status = PptPnpBounceAndCatchPnpIrp(fdx, Irp);
if( !NT_SUCCESS(status) && (status != STATUS_NOT_SUPPORTED) ) {
// Someone below us in the driver stack explicitly failed the IRP.
goto targetExit;
}
//
// Find the "real" resource requirments list, either the PnP list
// or the list created by another driver in the stack.
//
if ( Irp->IoStatus.Information == 0 ) {
//
// No one else has created a new resource list. Use the original
// list from the PnP Manager.
//
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation( Irp );
pResourceRequirementsIn = IrpStack->Parameters.FilterResourceRequirements.IoResourceRequirementList;
if (pResourceRequirementsIn == NULL) {
//
// NULL list, nothing to do.
//
goto targetExit;
}
} else {
//
// Another driver has created a new resource list. Use the list that they created.
//
pResourceRequirementsIn = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
}
//
// Check the registry to find out the desired type of resource filtering.
//
// The following call sets the default value for filterResourceMethod
// if the registry query fails.
//
PptRegGetDeviceParameterDword( fdx->PhysicalDeviceObject,
(PWSTR)L"FilterResourceMethod",
&filterResourceMethod );
DD((PCE)fdx,DDT,"filterResourceMethod=%x\n",filterResourceMethod);
//
// Do filtering based on registry setting.
//
switch( filterResourceMethod ) {
case PPT_FORCE_USE_NO_IRQ:
//
// Registry setting dictates that we should refuse to accept IRQ resources.
//
// * This is the default behavior which means that we make the IRQ available
// for legacy net and sound cards that may not work if they cannot get
// the IRQ.
//
// - If we find a resource alternative that does not contain an IRQ resource
// then we remove those resource alternatives that do contain IRQ
// resources from the list of alternatives.
//
// - Otherwise we have to play hardball. Since all resource alternatives
// contain IRQ resources we simply "nuke" the IRQ resource descriptors
// by changing their resource Type from CmResourceTypeInterrupt to
// CmResourceTypeNull.
//
DD((PCE)fdx,DDT,"PPT_FORCE_USE_NO_IRQ\n");
if( PptPnpFilterExistsNonIrqResourceList( pResourceRequirementsIn ) ) {
DD((PCE)fdx,DDT,"Found Resource List with No IRQ - Filtering\n");
PptPnpFilterRemoveIrqResourceLists( pResourceRequirementsIn );
} else {
DD((PCE)fdx,DDT,"Did not find Resource List with No IRQ - Nuking IRQ resource descriptors\n");
PptPnpFilterNukeIrqResourceDescriptorsFromAllLists( pResourceRequirementsIn );
}
break;
case PPT_TRY_USE_NO_IRQ:
//
// Registry setting dictates that we should TRY to give up IRQ resources.
//
// - If we find a resource alternative that does not contain an IRQ resource
// then we remove those resource alternatives that do contain IRQ
// resources from the list of alternatives.
//
// - Otherwise we do nothing.
//
DD((PCE)fdx,DDT,"PPT_TRY_USE_NO_IRQ\n");
if( PptPnpFilterExistsNonIrqResourceList(pResourceRequirementsIn) ) {
DD((PCE)fdx,DDT,"Found Resource List with No IRQ - Filtering\n");
PptPnpFilterRemoveIrqResourceLists(pResourceRequirementsIn);
} else {
// leave the IO resource list as is
DD((PCE)fdx,DDT,"Did not find Resource List with No IRQ - Do nothing\n");
}
break;
case PPT_ACCEPT_IRQ:
//
// Registry setting dictates that we should NOT filter out IRQ resources.
//
// - Do nothing.
//
DD((PCE)fdx,DDT,"PPT_ACCEPT_IRQ\n");
break;
default:
//
// Invalid registry setting.
//
// - Do nothing.
//
// RMT dvdf - May be desirable to write an error log entry here.
//
DD((PCE)fdx,DDE,"ERROR:IGNORED: bad filterResourceMethod=%x\n", filterResourceMethod);
}
targetExit:
//
// Preserve Irp->IoStatus.Information because it may point to a
// buffer and we don't want to cause a memory leak.
//
P4CompleteRequest( Irp, status, Irp->IoStatus.Information );
PptReleaseRemoveLock(&fdx->RemoveLock, Irp);
return status;
}
NTSTATUS
PptFdoSurpriseRemoval(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf6
Routine Description:
This function handles PnP IRP_MN_SURPRISE_REMOVAL.
Set flags accordingly in our extension, notify those
listening on our device interface GUID that
we have gone away, and pass the IRP down the
driver stack.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
Status returned from IoCallDriver.
--*/
{
PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;
//
// Set flags in our extension to indicate that we have received
// IRP_MN_SURPRISE_REMOVAL so that we can fail new requests
// as appropriate.
//
ExAcquireFastMutex( &fdx->ExtensionFastMutex );
PptSetFlags( fdx->PnpState, PPT_DEVICE_SURPRISE_REMOVED );
ExReleaseFastMutex( &fdx->ExtensionFastMutex );
//
// Fail outstanding allocate/select requests for the port
//
{
PIRP nextIrp;
KIRQL cancelIrql;
IoAcquireCancelSpinLock(&cancelIrql);
while( !IsListEmpty( &fdx->WorkQueue ) ) {
nextIrp = CONTAINING_RECORD( fdx->WorkQueue.Blink, IRP, Tail.Overlay.ListEntry );
nextIrp->Cancel = TRUE;
nextIrp->CancelIrql = cancelIrql;
nextIrp->CancelRoutine = NULL;
PptCancelRoutine( DeviceObject, nextIrp );
// PptCancelRoutine() releases the cancel SpinLock so we need to reaquire
IoAcquireCancelSpinLock( &cancelIrql );
}
IoReleaseCancelSpinLock( cancelIrql );
}
//
// Tell those listening on our device interface GUID that we have
// gone away. Ignore status from the call since we can do
// nothing on failure.
//
IoSetDeviceInterfaceState( &fdx->DeviceInterface, FALSE );
fdx->DeviceInterfaceState = FALSE;
//
// Succeed, pass the IRP down the stack, and release the RemoveLock.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
return PptPnpPassThroughPnpIrpAndReleaseRemoveLock( fdx, Irp );
}
NTSTATUS
PptFdoDefaultPnpHandler(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf8
Routine Description:
This function is the default handler for PnP IRPs.
All PnP IRPs that are not explicitly handled by another
routine (via an entry in the PptPnpDispatchFunctionTable[]) are
handled by this routine.
- Pass the IRP down the stack to the device below us in the
driver stack and release our device RemoveLock.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
STATUS_SUCCESS - on success,
an appropriate error status - otherwise
--*/
{
return PptPnpPassThroughPnpIrpAndReleaseRemoveLock(DeviceObject->DeviceExtension, Irp);
}
PDRIVER_DISPATCH
PptFdoPnpDispatchTable[] =
{
PptFdoStartDevice, // IRP_MN_START_DEVICE 0x00
PptFdoQueryRemove, // IRP_MN_QUERY_REMOVE_DEVICE 0x01
PptFdoRemoveDevice, // IRP_MN_REMOVE_DEVICE 0x02
PptFdoCancelRemove, // IRP_MN_CANCEL_REMOVE_DEVICE 0x03
PptFdoStopDevice, // IRP_MN_STOP_DEVICE 0x04
PptFdoQueryStop, // IRP_MN_QUERY_STOP_DEVICE 0x05
PptFdoCancelStop, // IRP_MN_CANCEL_STOP_DEVICE 0x06
PptFdoQueryDeviceRelations, // IRP_MN_QUERY_DEVICE_RELATIONS 0x07
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_INTERFACE 0x08
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES 0x09
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_RESOURCES 0x0A
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT 0x0C
PptFdoFilterResourceRequirements, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
PptFdoDefaultPnpHandler, // no such PnP request 0x0E
PptFdoDefaultPnpHandler, // IRP_MN_READ_CONFIG 0x0F
PptFdoDefaultPnpHandler, // IRP_MN_WRITE_CONFIG 0x10
PptFdoDefaultPnpHandler, // IRP_MN_EJECT 0x11
PptFdoDefaultPnpHandler, // IRP_MN_SET_LOCK 0x12
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_ID 0x13
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE 0x14
PptFdoDefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION 0x15
PptFdoDefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16
PptFdoSurpriseRemoval, // IRP_MN_SURPRISE_REMOVAL 0x17
PptFdoDefaultPnpHandler // IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
};
NTSTATUS
PptFdoPnp(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp
)
{
PFDO_EXTENSION fdx = Fdo->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
NTSTATUS status;
// diagnostic
PptFdoDumpPnpIrpInfo( Fdo, Irp );
//
// Acquire RemoveLock to prevent DeviceObject from being REMOVED
// while we are using it. If we are unable to acquire the RemoveLock
// then the DeviceObject has already been REMOVED.
//
status = PptAcquireRemoveLock( &fdx->RemoveLock, Irp);
if( STATUS_SUCCESS != status ) {
return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
}
//
// RemoveLock is held. Forward the request to the appropriate handler.
//
// Note that the handler must release the RemoveLock prior to returning
// control to this function.
//
if( irpSp->MinorFunction < arraysize(PptFdoPnpDispatchTable) ) {
return PptFdoPnpDispatchTable[ irpSp->MinorFunction ]( Fdo, Irp );
} else {
return PptFdoDefaultPnpHandler( Fdo, Irp );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -