📄 isopnp.c
字号:
deviceExtension->SSEnable = 0;
//
// make sure that if a DPC was fired before we called cancel timer,
// then the DPC and work-time have run to their completion
//
KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
Executive,
KernelMode,
FALSE,
NULL);
//
// make sure that the selective suspend request has been completed.
//
KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
}
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
deviceExtension->QueueState = FailRequests;
SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved);
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
ProcessQueuedRequests(deviceExtension);
ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
FALSE);
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(1, ("IoSetDeviceInterfaceState::disable:failed\n"));
}
RtlFreeUnicodeString(&deviceExtension->InterfaceName);
IsoUsb_WmiDeRegistration(deviceExtension);
IsoUsb_AbortPipes(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
IsoUsb_DbgPrint(3, ("HandleSurpriseRemoval - ends\n"));
return ntStatus;
}
NTSTATUS
HandleRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services Irp of minor type IRP_MN_REMOVE_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
KEVENT event;
ULONG requestCount;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
IsoUsb_DbgPrint(3, ("HandleRemoveDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// The Plug & Play system has dictated the removal of this device. We
// have no choice but to detach and delete the device object.
// (If we wanted to express an interest in preventing this removal,
// we should have failed the query remove IRP).
//
if(SurpriseRemoved != deviceExtension->DeviceState) {
//
// we are here after QUERY_REMOVE
//
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
deviceExtension->QueueState = FailRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
if(deviceExtension->WaitWakeEnable) {
CancelWaitWake(deviceExtension);
}
if(WinXpOrBetter == deviceExtension->WdmVersion) {
if(deviceExtension->SSEnable) {
//
// Cancel the timer so that the DPCs are no longer fired.
// we do not need DPCs because the device has been removed
//
KeCancelTimer(&deviceExtension->Timer);
deviceExtension->SSEnable = 0;
//
// make sure that if a DPC was fired before we called cancel timer,
// then the DPC and work-time have run to their completion
//
KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
Executive,
KernelMode,
FALSE,
NULL);
//
// make sure that the selective suspend request has been completed.
//
KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
}
ProcessQueuedRequests(deviceExtension);
ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
FALSE);
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(1, ("IoSetDeviceInterfaceState::disable:failed\n"));
}
RtlFreeUnicodeString(&deviceExtension->InterfaceName);
IsoUsb_WmiDeRegistration(deviceExtension);
IsoUsb_AbortPipes(DeviceObject);
}
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(deviceExtension, Removed);
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
//
// need 2 decrements
//
IsoUsb_DbgPrint(3, ("HandleRemoveDevice::"));
requestCount = IsoUsb_IoDecrement(deviceExtension);
ASSERT(requestCount > 0);
IsoUsb_DbgPrint(3, ("HandleRemoveDevice::"));
requestCount = IsoUsb_IoDecrement(deviceExtension);
KeWaitForSingleObject(&deviceExtension->RemoveEvent,
Executive,
KernelMode,
FALSE,
NULL);
ReleaseMemory(DeviceObject);
//
// We need to send the remove down the stack before we detach,
// but we don't need to wait for the completion of this operation
// (and to register a completion routine).
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
//
// Detach the FDO from the device stack
//
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
IoDeleteDevice(DeviceObject);
IsoUsb_DbgPrint(3, ("HandleRemoveDevice - ends\n"));
return ntStatus;
}
NTSTATUS
HandleQueryCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services Irp of minor type IRP_MN_QUERY_CAPABILITIES
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
{
ULONG i;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_CAPABILITIES pdc;
PIO_STACK_LOCATION irpStack;
IsoUsb_DbgPrint(3, ("HandleQueryCapabilities - begins\n"));
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
//
// We will provide here an example of an IRP that is processed
// both on its way down and on its way up: there might be no need for
// a function driver process this Irp (the bus driver will do that).
// The driver will wait for the lower drivers (the bus driver among
// them) to process this IRP, then it processes it again.
//
if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES)) {
IsoUsb_DbgPrint(1, ("HandleQueryCapabilities::request failed\n"));
ntStatus = STATUS_UNSUCCESSFUL;
return ntStatus;
}
//
// Set some values in deviceCapabilities here...
//
//.............................................
//
//
// Prepare to pass the IRP down
//
//
// Add in the SurpriseRemovalOK bit before passing it down.
//
pdc->SurpriseRemovalOK = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = IsoUsb_SyncPassDownIrp(DeviceObject, Irp);
//
// initialize PowerDownLevel to disabled
//
deviceExtension->PowerDownLevel = PowerDeviceUnspecified;
if(NT_SUCCESS(ntStatus)) {
deviceExtension->DeviceCapabilities = *pdc;
for(i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++) {
if(deviceExtension->DeviceCapabilities.DeviceState[i] <
PowerDeviceD3) {
deviceExtension->PowerDownLevel =
deviceExtension->DeviceCapabilities.DeviceState[i];
}
}
//
// since its safe to surprise-remove this device, we shall
// set the SurpriseRemoveOK flag to supress any dialog to
// user.
//
pdc->SurpriseRemovalOK = 1;
}
if(deviceExtension->PowerDownLevel == PowerDeviceUnspecified ||
deviceExtension->PowerDownLevel <= PowerDeviceD0) {
deviceExtension->PowerDownLevel = PowerDeviceD2;
}
IsoUsb_DbgPrint(3, ("HandleQueryCapabilities - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_SyncPassDownIrp (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine synchronously passes an Irp down the driver stack.
This routine must be called at PASSIVE_LEVEL.
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
KEVENT localevent;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_SyncPassDownIrp\n"));
deviceExtension = DeviceObject->DeviceExtension;
// Initialize the event we'll wait on
//
KeInitializeEvent(&localevent,
SynchronizationEvent,
FALSE);
// Copy down Irp params for the next driver
//
IoCopyCurrentIrpStackLocationToNext(Irp);
// Set the completion routine, which will signal the event
//
IoSetCompletionRoutine(Irp,
IsoUsb_SyncCompletionRoutine,
&localevent,
TRUE, // InvokeOnSuccess
TRUE, // InvokeOnError
TRUE); // InvokeOnCancel
// Pass the Irp down the stack
//
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
// If the request is pending, block until it completes
//
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject(&localevent,
Executive,
KernelMode,
FALSE,
NULL);
ntStatus = Irp->IoStatus.Status;
}
IsoUsb_DbgPrint(2, ("exit: IsoUsb_SyncPassDownIrp %08X\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_SyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This is the completion routine used by IsoUsb_SyncPassDownIrp and
IsoUsb_SyncPassDownIrp
If the Irp is one we allocated ourself, DeviceObject is NULL.
--*/
{
PKEVENT kevent;
kevent = (PKEVENT)Context;
KeSetEvent(kevent,
IO_NO_INCREMENT,
FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
IsoUsb_SyncSendUsbRequest (
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
/*++
Routine Description:
This routine synchronously passes a URB down the driver stack.
This routine must be called at PASSIVE_LEVEL.
--*/
{
PDEVICE_EXTENSION deviceExtension;
KEVENT localevent;
PIRP irp;
PIO_STACK_LOCATION nextStack;
NTSTATUS ntStatus;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_SyncSendUsbRequest\n"));
deviceExtension = DeviceObject->DeviceExtension;
// Initialize the event we'll wait on
//
KeInitializeEvent(&localevent,
SynchronizationEvent,
FALSE);
// Allocate the Irp
//
irp = IoAllocateIrp(deviceExtension->TopOfStackDeviceObject->StackSize, FALSE);
if (irp == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
// Set the Irp parameters
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -