📄 pnp.c
字号:
// Reset this flag so new IOCTL and IO Irp processing will be re-enabled
deviceExtension->StopDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_CANCEL_STOP_DEVICE
case IRP_MN_QUERY_CAPABILITIES: {
PDEVICE_CAPABILITIES pdc;
KEVENT event;
//
// Send this down to the PDO first
//
KeInitializeEvent (&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine (Irp,
UsbCom_IrpCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE);
ntStatus = IoCallDriver (stackDeviceObject, Irp);
if (STATUS_PENDING == ntStatus) {
// wait for it...
ntStatus = KeWaitForSingleObject (&event,
Executive,
KernelMode,
FALSE, // Not allertable
NULL); // No timeout structure
ASSERT (STATUS_SUCCESS == ntStatus);
ntStatus = Irp->IoStatus.Status;
}
if (NT_SUCCESS(ntStatus)) {
//irpStack = IoGetCurrentIrpStackLocation(Irp);
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
// Allow surprise removals...
DbgPrint("[ss] Allow surprise removals -- \n");
pdc->SurpriseRemovalOK = TRUE;
}
UsbCom_DecrementIoCount(DeviceObject);
DbgPrint("Allow surprise removals\n");
return ntStatus;
}
case IRP_MN_STOP_DEVICE:
// The PnP Manager sends this IRP to stop a device so it can reconfigure
// its hardware resources. The PnP Manager only sends this IRP if a prior
// IRP_MN_QUERY_STOP_DEVICE completed successfully.
// Cancel any pending io requests. (there shouldn't be any)
//UsbCom_CancelPendingIo( DeviceObject );
//
// If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
// This call will also close the pipes; if any user close calls get through,
// they will be noops
UsbCom_AbortPipes( DeviceObject );
//
// Send the select configuration urb with a NULL pointer for the configuration
// handle, this closes the configuration and puts the device in the 'unconfigured'
// state.
//
ntStatus = UsbCom_StopDevice(DeviceObject);
Irp->IoStatus.Status = ntStatus;
break; // end, case IRP_MN_STOP_DEVICE
case IRP_MN_QUERY_REMOVE_DEVICE:
// In response to this IRP, drivers indicate whether the device can be
// removed without disrupting the system.
// If a driver determines it is safe to remove the device,
// the driver completes any outstanding I/O requests, arranges to hold any subsequent
// read/write requests, and sets Irp->IoStatus.Status to STATUS_SUCCESS. Function
// and filter drivers then pass the IRP to the next-lower driver in the device stack.
// The underlying bus driver calls IoCompleteRequest.
// If a driver sets STATUS_SUCCESS for this IRP, the driver must not start any
// operations on the device that would prevent that driver from successfully completing
// an IRP_MN_REMOVE_DEVICE for the device. If a driver in the device stack determines
// that the device cannot be removed, the driver is not required to pass the
// query-remove IRP down the device stack. If a query-remove IRP fails, the PnP Manager
// sends an IRP_MN_CANCEL_REMOVE_DEVICE to the device stack, notifying the drivers for
// the device that the query has been cancelled and that the device will not be removed.
// It is possible to receive this irp when the device has not been started
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
UsbCom_DecrementIoCount(DeviceObject);
return ntStatus;
}
// Once RemoveDeviceRequested is set no new IOCTL or read/write irps will be passed
// down the stack to lower drivers; all will be quickly failed
deviceExtension->RemoveDeviceRequested = TRUE;
// Wait for any io request pending in our driver to
// complete before returning success.
// This event is set when deviceExtension->PendingIoCount goes to 1
waitStatus = KeWaitForSingleObject(
&deviceExtension->NoPendingIoEvent,
Suspended,
KernelMode,
FALSE,
NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_QUERY_REMOVE_DEVICE
case IRP_MN_CANCEL_REMOVE_DEVICE:
// The PnP Manager uses this IRP to inform the drivers
// for a device that the device will not be removed.
// It is sent only after a successful IRP_MN_QUERY_REMOVE_DEVICE.
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_CANCEL_REMOVE_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
UsbCom_DecrementIoCount(DeviceObject);
return ntStatus;
}
// Reset this flag so new IOCTL and IO Irp processing will be re-enabled
deviceExtension->RemoveDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_CANCEL_REMOVE_DEVICE
#if 1
case IRP_MN_SURPRISE_REMOVAL: {
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_SURPRISE_REMOVAL FDO=%08x\n", DeviceObject );
IoSetDeviceInterfaceState ( &deviceExtension->DeviceNameLink, FALSE);
// For a surprise-style device removal ( i.e. sudden cord yank ),
// the physical device has already been removed so the PnP Manager sends
// the remove IRP without a prior query-remove. A device can be in any state
// when it receives a remove IRP as a result of a surprise-style removal.
// match the inc at the begining of the dispatch routine
UsbCom_DecrementIoCount(DeviceObject);
//
// Once DeviceRemoved is set no new IOCTL or read/write irps will be passed
// down the stack to lower drivers; all will be quickly failed
//
deviceExtension->DeviceRemoved = TRUE;
// Cancel any pending io requests; we may not have gotten a query first!
//UsbCom_CancelPendingIo( DeviceObject );
// If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
// This call will also close the pipes; if any user close calls get through,
// they will be noops
//UsbCom_AbortPipes( DeviceObject );
//
// Mark this handled
//
Irp->IoStatus.Status = STATUS_SUCCESS;
// We don't explicitly wait for the below driver to complete, but just make
// the call and go on, finishing cleanup
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
return ntStatus;
}
break;
#else
case IRP_MN_SURPRISE_REMOVAL:
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_SURPRISE_REMOVAL\n");
GlobalPdaCount = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(stackDeviceObject, Irp);
break;
#endif
case IRP_MN_REMOVE_DEVICE:
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_REMOVE_DEVICE FDO=%08x\n", DeviceObject );
// The PnP Manager uses this IRP to direct drivers to remove a device.
// For a "polite" device removal, the PnP Manager sends an
// IRP_MN_QUERY_REMOVE_DEVICE prior to the remove IRP. In this case,
// the device is in the remove-pending state when the remove IRP arrives.
// For a surprise-style device removal ( i.e. sudden cord yank ),
// the physical device has already been removed and the PnP Manager may not
// have sent IRP_MN_SURPRISE_REMOVAL. A device can be in any state
// when it receives a remove IRP as a result of a surprise-style removal.
// match the inc at the begining of the dispatch routine
UsbCom_DecrementIoCount(DeviceObject);
//
// Once DeviceRemoved is set no new IOCTL or read/write irps will be passed
// down the stack to lower drivers; all will be quickly failed
//
deviceExtension->DeviceRemoved = TRUE;
// Cancel any pending io requests; we may not have gotten a query first!
UsbCom_CancelPendingIo( DeviceObject );
// If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
// This call will also close the pipes; if any user close calls get through,
// they will be noops
UsbCom_AbortPipes( DeviceObject );
// We don't explicitly wait for the below driver to complete, but just make
// the call and go on, finishing cleanup
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
//
// The final decrement to device extension PendingIoCount == 0
// will set deviceExtension->RemoveEvent, enabling device removal.
// If there is no pending IO at this point, the below decrement will be it.
//
UsbCom_DecrementIoCount(DeviceObject);
// wait for any io request pending in our driver to
// complete for finishing the remove
KeWaitForSingleObject(
&deviceExtension->RemoveEvent,
Suspended,
KernelMode,
FALSE,
NULL);
//
// Delete the link and FDO we created
//
UsbCom_RemoveDevice(DeviceObject);
DbgPrint("UsbCom_ProcessPnPIrp() Detaching from %08X\n",
deviceExtension->TopOfStackDeviceObject);
//
// We're cleaning up here. One reason we're cleaning up
// is that we couldn't allocate space for the directory
// name or the symbolic link.
//
if (deviceExtension->SymbolicLinkName.Buffer &&
deviceExtension->CreatedSymbolicLink) {
IoDeleteSymbolicLink (&deviceExtension->SymbolicLinkName);
}
//
// We're cleaning up here. One reason we're cleaning up
// is that we couldn't allocate space for the NtNameOfPort.
//
if ((deviceExtension->DeviceName.Buffer != NULL)
&& deviceExtension->CreatedSerialCommEntry) {
ntStatus = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
deviceExtension->DeviceName.Buffer);
if (!NT_SUCCESS(ntStatus)) {
DbgPrint("Couldn't delete value entry \n");
}
}
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
DbgPrint("UsbCom_ProcessPnPIrp() Deleting %08X\n",
DeviceObject);
if (deviceExtension->DeviceName.Buffer != NULL) {
ExFreePool(deviceExtension->DeviceName.Buffer);
}
if (deviceExtension->SymbolicLinkName.Buffer != NULL) {
ExFreePool(deviceExtension->SymbolicLinkName.Buffer);
}
IoDeleteDevice (DeviceObject);
return ntStatus; // end, case IRP_MN_REMOVE_DEVICE
default:
//
// In this case we must not touch the status. As ntstatus is
// STATUS_SUCCESS, we will skip the failure case and pass down the IRP
// untouched.
//
DbgPrint("UsbCom_ProcessPnPIrp() Minor PnP IOCTL not handled\n");
} /* case MinorFunction */
if (!NT_SUCCESS(ntStatus)) {
// if anything went wrong, return failure without passing Irp down
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
UsbCom_DecrementIoCount(DeviceObject);
DbgPrint("UsbCom_ProcessPnPIrp() Exit UsbCom_ProcessPnPIrp FAILURE %x\n", ntStatus);
return ntStatus;
}
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// All PNP_POWER messages get passed to the TopOfStackDeviceObject
// we were given in PnPAddDevice
//
DbgPrint("UsbCom_ProcessPnPIrp() Passing PnP Irp down, status = %x\n", ntStatus);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
UsbCom_DecrementIoCount(DeviceObject);
DbgPrint("UsbCom_ProcessPnPIrp() Exit UsbCom_ProcessPnPIrp %x\n", ntStatus);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -