Hello. I will describe my plight in some detail. I have been assigned to
debug a problem in another project in which I have not worked.
Unfortunately, this is a streaming class driver (stream.sys is the port
driver) over the USB bus (1.1), and I have experience in neither. Also, the
project uses DriverWorks, and I am not familiar with this tool. But
anyways, here goes.
The problem is as follows; on Win2k SP3, when performing MIDI capture on a
bulk in endpoint, and I unplug the device, the system crashes with such
severity that WinDBG does not seem to trap the exception, and the system
reboots. SoftICE sometimes does trap the fault, and it seemed that the
crash occurred in one of the pool functions (ExAllocatePoolWithTag,
ExFreePool). I could never get a memory dump or stack trace with either
debugger. Of course, I had previously configured the system to yield a
kernel mode dump, and to not automatically reboot.
Unfortunately, with stream class port driver, I don’t have control over the
PnP dispatch routine. Nevertheless I overrode the routine with my own, and
called stream class’ routine. I merely put this in place to see what PnP
manager was sending the port driver. When MIDI capture was not on, I
clearly saw a call of IoInvalidateDeviceRelations call by the USB bus
driver, followed by two IRP_MN_QUERY_DEVICE_RELATIONS, and then a
IRP_MN_SURPRISE_REMOVAL. This last IRP triggers a surprise removal SRB to
be sent to my miniport, and I have of course have control the function which
responds to this SRB.
Unfortunately, when MIDI capture is in progress, and I unplug, I don’t even
see the USB bus driver calling IoInvalidateDeviceRelations, let alone
IRP_MN_SURPRISE_REMOVAL; the system merely reboots. Rarely, WinDBG pops up,
with a failure message: “unable to get context” (or something like that).
Using driver verifier did not help me, except to find some other minor bugs.
I therefore did a small experiment. I broke into my driver, set a global
variable which made my driver no longer touch the hardware, and unplugged
the device while the system was still frozen. This time the I saw the call
to IoInvalidateDeviceRelations, IRP_MN_QUERY_DEVICE_RELATIONS, and
IRP_MN_SURPRISE_REMOVAL. The driver unloaded fine.
Looking into the capture architecture of the driver, I saw that in the
completion routine for the IOCTL_INTERNAL_USB_SUBMIT_URB call to the USB bus
driver (which is at DISPATCH), that the data received from the bus driver
was copied up to stream class, and that a new URB was sent down, all at
DISPATCH. I thought that perhaps it would be more prudent to send down the
next URB at PASSIVE, even though the service
UsbBuildInterruptOrBulkTransferRequest can be called at DISPATCH. I also
used IoAllocateIrp, which is fine to call at DISPATCH. Of course no waiting
is done at DISPATCH in the driver.
So as a test I used a system thread to send the next URB down at PASSIVE.
This seemed to solve the problem! What I don’t understand is why the
previous architecture failed. I did not find any stricture stating that
IOCTL_INTERNAL_USB_SUBMIT_URB must be sent at PASSIVE. Surely in the
original architecture, the USB bus driver would pend my IRP, and the system
would drop down to PASSIVE, giving enough time to low IRQL for the USB bus
driver to note that the device is not present any more on the USB bus (and
send the required PnP IRPs at PASSIVE).
Any ideas on why this change worked? I’m really not comfortable not knowing
why this helped. For all I know this is masking the real issue. Thanks
in advance.
Philip Lukidis