📄 fdopnp.c
字号:
for( daisyChainId = 0 ; daisyChainId <= daisyChainMaxId ; ++daisyChainId ) {
if( fdx->DaisyChainPdo[ daisyChainId ] ) {
PDEVICE_OBJECT pdo = fdx->DaisyChainPdo[ daisyChainId ];
DD((PCE)fdx,DDT,"PptFdoRemoveDevice - have DaisyChainPdo[%d] - cleaning up\n",daisyChainId);
P4DestroyPdo( pdo );
fdx->DaisyChainPdo[ daisyChainId ] = NULL;
}
}
}
//
// RMT - if fdx->DevDeletionListHead non-empty - clean it up?
//
PptAssert( IsListEmpty( &fdx->DevDeletionListHead) );
//
// Set flags in our extension to indicate that we have received
// IRP_MN_REMOVE_DEVICE so that we can fail new requests as appropriate.
//
ExAcquireFastMutex( &fdx->ExtensionFastMutex );
PptSetFlags( fdx->PnpState, PPT_DEVICE_REMOVED );
ExReleaseFastMutex( &fdx->ExtensionFastMutex );
//
// if we still have a worker thread, kill it
//
{
PVOID threadObjPointer = InterlockedExchangePointer( &fdx->ThreadObjectPointer, NULL );
if( threadObjPointer ) {
// set the flag for the worker thread to kill itself
fdx->TimeToTerminateThread = TRUE;
// wake thread so it can kill self
KeSetEvent( &fdx->FdoThreadEvent, 0, TRUE );
// wait for the thread to die
KeWaitForSingleObject( threadObjPointer, Executive, KernelMode, FALSE, NULL );
// allow the system to release the thread object
ObDereferenceObject( threadObjPointer );
}
}
//
// Unregister w/WMI
//
IoWMIRegistrationControl(Fdo, WMIREG_ACTION_DEREGISTER);
//
// 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;
//
// Pass the IRP down the stack and wait for all other IRPs
// that are being processed by the device to drain.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( fdx->ParentDeviceObject, Irp );
PptReleaseRemoveLockAndWait( &fdx->RemoveLock, Irp );
//
// Clean up pool allocations
//
RtlFreeUnicodeString( &fdx->DeviceName);
RtlFreeUnicodeString( &fdx->DeviceInterface );
if( fdx->PnpInfo.PortName ) {
ExFreePool( fdx->PnpInfo.PortName );
fdx->PnpInfo.PortName = NULL;
}
if( fdx->Location ) {
ExFreePool( fdx->Location );
fdx->Location = NULL;
}
//
// Detach and delete our device object.
//
IoDetachDevice( fdx->ParentDeviceObject );
IoDeleteDevice( Fdo );
return status;
}
NTSTATUS
PptFdoCancelRemove(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf8
Routine Description:
This function handles PnP IRP_MN_CANCEL_REMOVE_DEVICE.
If we previously SUCCEEDed a QUERY_REMOVE (PPT_DEVICE_REMOVE_PENDING
flag is set) then we reset the appropriate device state flags
and resume normal operation. Otherwise treat this as an
informational message.
This function is identical to PptPnpCancelStopDevice() except for
the fdx->PnpState.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
Status returned from IoCallDriver.
--*/
{
PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;
ExAcquireFastMutex( &fdx->ExtensionFastMutex );
if( fdx->PnpState & PPT_DEVICE_REMOVE_PENDING ) {
PptClearFlags( fdx->PnpState, ( PPT_DEVICE_REMOVE_PENDING | PPT_DEVICE_PAUSED ) );
}
ExReleaseFastMutex( &fdx->ExtensionFastMutex );
Irp->IoStatus.Status = STATUS_SUCCESS;
return PptPnpPassThroughPnpIrpAndReleaseRemoveLock( fdx, Irp );
}
NTSTATUS
PptFdoStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf8
Routine Description:
This function handles PnP IRP_MN_STOP_DEVICE.
We previously SUCCEEDed QUERY_STOP. Set flags
to indicate that we are now STOPPED.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
Status returned from IoCallDriver.
--*/
{
PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;
ExAcquireFastMutex( &fdx->ExtensionFastMutex );
//
// Assert that we are in a STOP_PENDING state.
//
ASSERT( fdx->PnpState & PPT_DEVICE_STOP_PENDING );
ASSERT( fdx->PnpState & PPT_DEVICE_PAUSED );
//
// PPT_DEVICE_PAUSED remains set
//
PptSetFlags( fdx->PnpState, PPT_DEVICE_STOPPED );
PptClearFlags( fdx->PnpState, ( PPT_DEVICE_STOP_PENDING | PPT_DEVICE_STARTED ) );
ExReleaseFastMutex( &fdx->ExtensionFastMutex );
Irp->IoStatus.Status = STATUS_SUCCESS;
return PptPnpPassThroughPnpIrpAndReleaseRemoveLock(fdx, Irp);
}
NTSTATUS
PptFdoQueryStop(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf8
Routine Description:
This function handles PnP IRP_MN_QUERY_STOP_DEVICE.
FAIL the request if there are open handles, SUCCEED otherwise.
Other drivers may cache pointers to the parallel port registers that
they obtained via IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO and there
is currently no mechanism to find and inform all such drivers that the
parallel port registers have changed and their their cached pointers are
now invalid without breaking legacy drivers.
This function is identical to PptPnpQueryStopDevice() except
for the flag that gets set in fdx->PnpState.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
STATUS_SUCCESS - No open handles - SUCCEED IRP
STATUS_DEVICE_BUSY - Open handles - FAIL IRP
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;
BOOLEAN handlesOpen;
//
// RMT - dvdf - race condition - small timing window - sequence:
// 1. Test indicates no open handles - decide to SUCCEED QUERY_STOP
// 2. CREATE arrives and is SUCCEEDED - open handle
// 3. We SUCCEED QUERY_STOP
// 4. Client obtains register addresses via IOCTL
// 5. PnP Rebalances us - registers change
// 6. Client acquires port via IOCTL
// 7. Client tries to access registers at pre-rebalance location
// 8. BOOM!!!
//
ExAcquireFastMutex( &fdx->OpenCloseMutex );
handlesOpen = (BOOLEAN)( fdx->OpenCloseRefCount > 0 );
ExReleaseFastMutex( &fdx->OpenCloseMutex );
if( handlesOpen ) {
status = STATUS_DEVICE_BUSY;
P4CompleteRequest( Irp, status, Irp->IoStatus.Information );
PptReleaseRemoveLock( &fdx->RemoveLock, Irp );
} else {
Irp->IoStatus.Status = STATUS_SUCCESS;
status = PptPnpPassThroughPnpIrpAndReleaseRemoveLock( fdx, Irp );
ExAcquireFastMutex( &fdx->ExtensionFastMutex );
PptSetFlags( fdx->PnpState, ( PPT_DEVICE_STOP_PENDING | PPT_DEVICE_PAUSED ) );
ExReleaseFastMutex( &fdx->ExtensionFastMutex );
}
return status;
}
NTSTATUS
PptFdoCancelStop(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf8
Routine Description:
This function handles PnP IRP_MN_CANCEL_STOP_DEVICE.
If we previously SUCCEEDed a QUERY_STOP (PPT_DEVICE_STOP_PENDING
flag is set) then we reset the appropriate device state flags
and resume normal operation. Otherwise treat this as an
informational message.
This function is identical to PptPnpCancelRemoveDevice() except for
the fdx->PnpState.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
Status returned from IoCallDriver.
--*/
{
PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;
ExAcquireFastMutex( &fdx->ExtensionFastMutex );
if( fdx->PnpState & PPT_DEVICE_STOP_PENDING ) {
PptClearFlags( fdx->PnpState, ( PPT_DEVICE_STOP_PENDING | PPT_DEVICE_PAUSED ) );
}
ExReleaseFastMutex( &fdx->ExtensionFastMutex );
Irp->IoStatus.Status = STATUS_SUCCESS;
return PptPnpPassThroughPnpIrpAndReleaseRemoveLock( fdx, Irp );
}
NTSTATUS
PptFdoQueryDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This function handles PnP IRP_MN_QUERY_DEVICE_RELATIONS.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
STATUS_SUCCESS - on success,
an appropriate error status - otherwise
--*/
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
DEVICE_RELATION_TYPE type = irpSp->Parameters.QueryDeviceRelations.Type;
if( BusRelations == type ) {
return PptFdoHandleBusRelations( DeviceObject, Irp );
} else {
return PptPnpPassThroughPnpIrpAndReleaseRemoveLock(DeviceObject->DeviceExtension, Irp);
}
}
NTSTATUS
PptFdoFilterResourceRequirements(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++dvdf8
Routine Description:
This function handles PnP IRP_MN_FILTER_RESOURCE_REQUIREMENTS IRPs.
- Wait for the bus driver and any drivers beneath
us in the driver stack to handle this first.
- Query the registry to find the type of filtering desired.
- Filter out IRQ resources as specified by the registry setting.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -