📄 usbfx2lk_pnp.cpp
字号:
OsrCsqCompleteCancelledIoIrp);
#else // W2K3
status = IoCsqInitialize(&devExt->CancelSafeIoQueue,
OsrCsqInsertIoIrp,
OsrCsqRemoveIoIrp,
OsrCsqPeekNextIoIrp,
OsrCsqAcquireIoLock,
OsrCsqReleaseIoLock,
OsrCsqCompleteCancelledIoIrp);
#endif // W2K3
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: IoCsqInitialize Error 0x%x (%s)\n",status,OsrNtStatusToString(status)));
IoDeleteDevice(devExt->FunctionalDeviceObject);
return status;
}
//
// Register the Device Interface for the Device. This will allow users to use the
// SetupDi interface API to connect to these devices.
//
status = IoRegisterDeviceInterface(PPhysicalDeviceObject,&GUID_OSR_USBFX2LK_INTERFACE,
NULL,
&devExt->InterfaceName);
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: IoRegisterDeviceInterface Error 0x%x (%s)\n",status,OsrNtStatusToString(status)));
IoDeleteDevice(pFunctionalDeviceObject);
return status;
}
//
// Attach the FDO to the PDO. Remember to save the returned Device Object Address. This
// is the address of the Underlying PDO to which PnP and Power requests should be sent.
//
devExt->DeviceToSendIrpsTo = IoAttachDeviceToDeviceStack(devExt->FunctionalDeviceObject,
devExt->PhysicalDeviceObject);
if(!devExt->DeviceToSendIrpsTo) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: IoAttachDeviceToDeviceStack Error 0x%x (%s)\n",status,OsrNtStatusToString(status)));
RtlFreeUnicodeString(&devExt->InterfaceName);
IoDeleteDevice(devExt->FunctionalDeviceObject);
return status;
}
//
// Tell the I/O Manager to user Direct I/O for our reads/writes
//
devExt->FunctionalDeviceObject->Flags |= DO_DIRECT_IO;
//
// See if we can set the Power pageable flag. We should because
// we are not in the power pageable Path.
//
if(devExt->DeviceToSendIrpsTo->Flags & DO_POWER_PAGABLE) {
devExt->FunctionalDeviceObject->Flags |= DO_POWER_PAGABLE;
}
//
// Clear the Device Initializing bit. This indicates to the I/O
// manager that we are now ready to begin processing requests on
// this device
//
devExt->FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// Register with WMI after having cleared the DO_DEVICE_INITIALIZING
// flag. This is to ensure that our device is prepared to receive
// WMI IRPs as soon as the system wants to start sending them
//
status = UsbFx2LkWmiRegistration(devExt);
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("UsbFx2LkAddDevice: UsbFx2LkWmiRegistration Error 0x%x (%s)\n",status,OsrNtStatusToString(status)));
RtlFreeUnicodeString(&devExt->InterfaceName);
IoDetachDevice(devExt->DeviceToSendIrpsTo);
IoDeleteDevice(pFunctionalDeviceObject);
return status;
}
//
// You need to include this function call only when WPP tracing
// is enabled on and we're built for Win2K. Do NOT call this until
// we have successfully registered with WMI, as this call will
// begin sending WMI requests to the device, which isn't a
// good thing if our WMI module isn't properly initialized
//
#ifdef WPP_TRACING
#ifdef W2K
W2KInitializeWPPTracing(pFunctionalDeviceObject,&GlobalRegistryPath);
#endif // W2K
#endif // WPP_TRACING
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("UsbFx2LkAddDevice: Exits\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// PnpRequestComplete
//
// We are called at this entry point when an Irp forwarded to the driver
// below us completes.
//
//
// INPUTS:
//
// DeviceObject - Address of our DEVICE_OBJECT.
//
// Irp - Address of the completing Irp
//
// Context - Address of Event to set
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_MORE_PROCESSING_REQUIRED
//
// IRQL:
//
// This routine is called at IRQL <= DISPATCH_LEVEL.
//
// CONTEXT:
//
// This routine is called in an arbitrary context
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
#ifndef IoForwardIrpSynchronously
NTSTATUS PnpRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
PKEVENT pEvent = (PKEVENT) Context;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("PnpRequestComplete: Enter.\n"));
KeSetEvent(pEvent, 0, FALSE);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("PnpRequestComplete: Exit\n"));
//
// Take the IRP back so that we can continue using it during
// the IRP_MN_START_DEVICE dispatch routine.
// NB: we will have to call IoCompleteRequest
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
#endif //IoForwardIrpSynchronously
///////////////////////////////////////////////////////////////////////////////
//
// OsrForwardIrpSynchronous
//
// We call this entry point when we want to forward an Irp to a
// device and we want to wait for the request to complete. In
// other words, we want SYNCHRONOUS behavior.
//
//
// INPUTS:
//
// TargetDevice - Address of target device
//
// Irp - Address of the Irp to deliver
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_UNSUCESSFUL if Irp could not be forwarded, otherwise
// returns the status returned by the driver that the Irp was
// forwarded to.
//
// IRQL:
//
// This routine is called at IRQL == PASSIVE_LEVEL.
//
// CONTEXT:
//
// This routine is called in an arbitrary context
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS OsrForwardIrpSynchronous(PUSBFX2LK_EXT DevExt,PIRP Irp)
{
NTSTATUS status;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("OsrForwardIrpSynchronous: Enter.\n"));
#ifdef IoForwardIrpSynchronously
if(IoForwardIrpSynchronously(DevExt->DeviceToSendIrpsTo,Irp)) {
status = Irp->IoStatus.Status;
} else {
status = STATUS_UNSUCCESSFUL;
}
#else //IoForwardIrpSynchronously
KEVENT eventWaitLowerDrivers;
KeInitializeEvent(&eventWaitLowerDrivers, NotificationEvent, FALSE);
//
// The BUS DRIVER handles this IRP before we do
//
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// Call OsrPnpComplete() when this IRP is done...
//
IoSetCompletionRoutine(Irp,
PnpRequestComplete,
&eventWaitLowerDrivers,
TRUE,
TRUE,
TRUE);
//
// Send the IRP to the bus driver. Let's see what HE
// thinks.
//
status = IoCallDriver(DevExt->DeviceToSendIrpsTo, Irp);
if (status == STATUS_PENDING) {
OsrWaitForSingleObject(&eventWaitLowerDrivers);
status = Irp->IoStatus.Status;
}
#endif //IoForwardIrpSynchronously
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("OsrForwardIrpSynchronous: Exit.\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// UsbFx2LkPnp
//
// This routine is called by the IO Manager to process a IRP_MJ_PNP
// Irp.
//
//
// INPUTS:
//
// DeviceObject - One of our Device Objects.
// Irp - The Irp to process.
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// None
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// This routine is called either in an arbitrary thread context
// or in the context of the System thread, depending on the minor
// function code. You can find out which by consulting the DDK
// documentation for the particular minor function code.
//
// NOTES:
//
// There are several difficulties implementing Plug and Play.
// Perhaps the greatest difficulty is deciding precisely how you
// want your device to work, given the various requests the driver
// can receive and the states the device can be in. In our driver,
// we've decided to implement the following policies:
//
// 1) When a removal of the device is requested, we will reject
// any new IRPs we receive (completing them with an error
// status in the dispatch routine). We will wait until all IRPs
// that are already present on the device's queue are complete
// and then allow the remove.
//
// 2) When a stop of the device is requested, we'll queue any new
// Irps then wait until any IRPs that are presently ACTIVE on the
// device complete, and then allow the stop.
//
// 3) When a SUPRISE removal of the device is indicated, we
// process any close, clean-up, power and PnP requests
// but fail all others. This applies to in process, current
// queued and future irps
//
// Of course, the second complexity in implementing plug and play
// is getting the logic in your driver correct, so that it works
// as you intend. According to our experience, this is easier said
// than done. We've changed the code in this function now, oh,
// about ten million times.
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS UsbFx2LkPnp(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)DeviceObject->DeviceExtension;
POWER_STATE powerState;
BOOLEAN enableInterface = FALSE;
//
// We're guaranteed to be called here at IRQL PASSIVE_LEVEL
//
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Increment the count of Outstanding IOs
//
OsrIncrementOutstandingIoCount(devExt,__FILE__,__LINE__);
if (ioStack->MinorFunction <= IRP_MN_SURPRISE_REMOVAL) {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("OsrPnp: Entered at PnP State %s with Minor Function %s\n",
OsrPrintState(devExt),
OsrMinorFunctionToString(ioStack->MajorFunction,
ioStack->MinorFunction)));
} else {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("OsrPnp: Entered at PnP State %s with unusual Minor Function 0x%x\n",
OsrPrintState(devExt),
ioStack->MinorFunction));
}
//
// Let's see what we have...
//
switch (devExt->DevicePnPState + ioStack->MinorFunction) {
//
// STATE: STOPPED or NEVER_STARTED
// IRP_MN: _START_DEVICE
//
// We're here if we've received an AddDevice() call, but we
// have not yet been told it's OK to talk to our device by
// the PnP Manager.
//
// We're also here if we've been stopped for a resource
// rebalance
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -