📄 pnp.c
字号:
ntS = SelectInterfaces(DeviceObject, configurationDescriptor);
} else {
DevExt->UsbConfigurationDescriptor = NULL;
}
ConfigureDevice_Exit:
if (urb) {
ExFreePool(urb);
}
DPRINT(("<usb> <- ConfigureDevice\n"));
return(ntS);
}
NTSTATUS DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject) {
PURB urb;
ULONG siz;
NTSTATUS ntS;
DPRINT(("<usb> DeconfigureDevice()\n"));
siz = sizeof(struct _URB_SELECT_CONFIGURATION);
urb = ExAllocatePool(NonPagedPool, siz);
if (urb) {
UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
ntS = CallUSBD(DeviceObject, urb);
if (!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: CallUSBD %x (deconfig device)\n", ntS));
}
ExFreePool(urb);
} else {
DPRINT(("<usb> error: allocating urb\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
}
return(ntS);
}
/*********************************************************************
*
* Routine Description:
* This routine synchronously submits an urb down the stack.
* Arguments:
* DeviceObject - pointer to device object
* Urb - USB request block
*
* Return Value:
--*/
NTSTATUS CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb) {
PIRP irp;
KEVENT event;
NTSTATUS ntS;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
DEVICE_EXTENSION * DevExt;
DPRINT(("<usb> -> CallUSBD"));
//
// initialize the variables
//
irp = NULL;
DevExt = DeviceObject->DeviceExtension;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, DevExt->TopOfStackDeviceObject,
NULL, 0, NULL, 0, TRUE, &event, &ioStatus);
if (!irp) {
DPRINT(("IoBuildDeviceIoControlRequest failed\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
} else {
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = Urb;
DevIoIncrement(DevExt);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, irp);
if(ntS == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ntS = ioStatus.Status;
}
DevIoDecrement(DevExt);
}
DPRINT(("<usb> <- CallUSBD"));
return ntS;
}
/*********************************************************************
*
* Routine Description:
* This routine services the Irps of minor type IRP_MN_QUERY_STOP_DEVICE
* Arguments:
* DeviceObject - pointer to device object
* Irp - I/O request packet sent by the pnp manager.
* Return Value:
* NT status value
*/
NTSTATUS HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
KIRQL oldIrql;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DPRINT(("HandleQueryStopDevice - begins\n"));
//
// initialize variables
//
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
//
// If we can stop the device, we need to set the QueueState to
// HoldRequests so further requests will be queued.
//
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(DevExt, PendingStop);
DevExt->QueueState = HoldRequests;
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
//
// wait for the existing ones to be finished.
// first, decrement this operation
//
DPRINT(("HandleQueryStopDevice::"));
DevIoDecrement(DevExt);
KeWaitForSingleObject(&DevExt->StopEvent, Executive, KernelMode, FALSE, NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
DPRINT(("HandleQueryStopDevice - ends\n"));
return ntS;
}
/*********************************************************************
*
* Routine Description:
* This routine services Irp of minor type IRP_MN_CANCEL_STOP_DEVICE
* Arguments:
* DeviceObject - pointer to device object
* Irp - I/O request packet sent by the pnp manager.
* Return Value:
* NT value
*
*/
NTSTATUS HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
KIRQL oldIrql;
KEVENT event;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DPRINT(("HandleCancelStopDevice - begins\n"));
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
//
// Send this IRP down and wait for it to come back.
// Set the QueueState flag to AllowRequests,
// and process all the previously queued up IRPs.
//
// First check to see whether you have received cancel-stop
// without first receiving a query-stop. This could happen if someone
// above us fails a query-stop and passes down the subsequent
// cancel-stop.
//
if (PendingStop == DevExt->DeviceState) {
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
if(ntS == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ntS = Irp->IoStatus.Status;
}
if (NT_SUCCESS(ntS)) {
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
RESTORE_PREVIOUS_PNP_STATE(DevExt);
DevExt->QueueState = AllowRequests;
ASSERT(DevExt->DeviceState == Working);
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
ProcessQueuedRequests(DevExt);
}
} else {
// spurious Irp
ntS = STATUS_SUCCESS;
}
DPRINT(("HandleCancelStopDevice - ends\n"));
return ntS;
}
/*++
Routine Description:
This routine services Irp of minor type IRP_MN_STOP_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
KIRQL oldIrql;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DPRINT(("HandleStopDevice - begins\n"));
//
// initialize variables
//
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
//
// after the stop Irp is sent to the lower driver object,
// the driver must not send any more Irps down that touch
// the device until another Start has occurred.
//
if(DevExt->WaitWakeEnable) {
CancelWaitWake(DevExt);
}
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(DevExt, Stopped);
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
//
// This is the right place to actually give up all the resources used
// This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace,
// etc.
//
ReleaseMemory(DeviceObject);
ntS = DeconfigureDevice(DeviceObject);
Irp->IoStatus.Status = ntS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
DPRINT(("HandleStopDevice - ends\n"));
return ntS;
}
/*++
Routine Description:
This routine services Irp of minor type IRP_MN_QUERY_REMOVE_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
NTSTATUS HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
KIRQL oldIrql;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DPRINT(("HandleQueryRemoveDevice - begins\n"));
//
// initialize variables
//
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
//
// If we can allow removal of the device, we should set the QueueState
// to HoldRequests so further requests will be queued. This is required
// so that we can process queued up requests in cancel-remove just in
// case somebody else in the stack fails the query-remove.
//
ntS = _CanRemoveDevice(DeviceObject, Irp);
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
DevExt->QueueState = HoldRequests;
SET_NEW_PNP_STATE(DevExt, PendingRemove);
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
DPRINT(("HandleQueryRemoveDevice::"));
DevIoDecrement(DevExt);
//
// wait for all the requests to be completed
//
KeWaitForSingleObject(&DevExt->StopEvent, Executive, KernelMode, FALSE, NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
DPRINT(("HandleQueryRemoveDevice - ends\n"));
return ntS;
}
/*********************************************************************
*
* Routine Description:
* This routine services Irp of minor type IRP_MN_CANCEL_REMOVE_DEVICE
* Arguments:
* DeviceObject - pointer to device object
* Irp - I/O request packet sent by the pnp manager.
* Return Value:
* NT status value
--*/
NTSTATUS HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
KIRQL oldIrql;
KEVENT event;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DPRINT(("HandleCancelRemoveDevice - begins\n"));
//
// initialize variables
//
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
//
// We need to reset the QueueState flag to ProcessRequest,
// since the device resume its normal activities.
//
//
// First check to see whether you have received cancel-remove
// without first receiving a query-remove. This could happen if
// someone above us fails a query-remove and passes down the
// subsequent cancel-remove.
//
if(PendingRemove == DevExt->DeviceState) {
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
if(ntS == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ntS = Irp->IoStatus.Status;
}
if(NT_SUCCESS(ntS)) {
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
DevExt->QueueState = AllowRequests;
RESTORE_PREVIOUS_PNP_STATE(DevExt);
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
// process the queued requests that arrive between QUERY_REMOVE and CANCEL_REMOVE
ProcessQueuedRequests(DevExt);
}
} else {
//
// spurious cancel-remove
//
ntS = STATUS_SUCCESS;
}
DPRINT(("HandleCancelRemoveDevice - ends\n"));
return ntS;
}
/*
* 1. block & fail pending requests
* 2. signal new PNP state
* 3. call lower drivers
*/
NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
KIRQL oldIrql;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
if (DevExt->WaitWakeEnable) {
CancelWaitWake(DevExt);
}
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
DevExt->QueueState = FailRequests;
SET_NEW_PNP_STATE(DevExt, SurpriseRemoved);
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
ProcessQueuedRequests(DevExt);
ntS = IoSetDeviceInterfaceState(&DevExt->InterfaceName, FALSE);
if (!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: HandleSurpriseRemoval::IoSetDeviceInterfaceState %x\n", ntS));
}
BulkUsb_AbortPipes(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
return(ntS);
}
NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
KIRQL oldIrql;
ULONG requestCount;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
if(SurpriseRemoved != DevExt->DeviceState) {
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
DevExt->QueueState = FailRequests;
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
if(DevExt->WaitWakeEnable) {
CancelWaitWake(DevExt);
}
ProcessQueuedRequests(DevExt);
ntS = IoSetDeviceInterfaceState(&DevExt->InterfaceName, FALSE);
if(!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: HandleRemoveDevice::IoSetDeviceInterfaceState %x\n", ntS));
}
BulkUsb_AbortPipes(DeviceObject);
}
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(DevExt, Removed);
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
DPRINT(("HandleRemoveDevice::"));
requestCount = DevIoDecrement(DevExt);
ASSERT(requestCount > 0);
DPRINT(("HandleRemoveDevice::"));
requestCount = DevIoDecrement(DevExt);
KeWaitForSingleObject(&DevExt->RemoveEvent, Executive, KernelMode, FALSE, NULL);
ReleaseMemory(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
//
// Detach the FDO from the device stack
//
IoDetachDevice(DevExt->TopOfStackDeviceObject);
_DeleteDevice(DeviceObject);
return(ntS);
}
/*++
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
--*/
NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
ULONG i;
KEVENT event;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
PDEVICE_CAPABILITIES pdc;
PIO_STACK_LOCATION irpStack;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -