IoCallDriver on Win2k

I wrote a USB smart card driver for WinXP and my understanding is that it
should work on Win2k. It does–if, the BIG IF–my USB smart card reader is
connected to the system via a USB hub. If I connect my reader directly to
the root hub, the driver fails in one of the calls to the lower bus driver
(usbd.sys) during driver init time when I call IoCallDriver. The error code
from the call to IoCallDriver is 0xc000000d (STATUS_INVALID_PARAMETER). Now
this call is the second call I made to the reader–the first call, which
uses the same code, sends a command via the output pipe and SUCEEDS. This
second call is supposed to get the response from the smart card reader via
the input pipe.
Here’s code segment for making the call (this is based on Walter Oney’s
sample code):

NTSTATUS SendAwaitUrb(PDEVICE_OBJECT fdo, PURB urb)
{ // SendAwaitUrb
PAGED_CODE();
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);

IO_STATUS_BLOCK iostatus;
PIRP Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->LowerDeviceObject, NULL, 0,
NULL, 0, TRUE, &event, &iostatus);

if (!Irp) {
KdPrint((DRIVERNAME " - Unable to allocate IRP for sending URB\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}

// Set up our completion routine
IoSetCompletionRoutine(Irp, SendUrbComplete, (PVOID)&event, TRUE, TRUE,
TRUE);

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
stack->Parameters.Others.Argument1 = (PVOID) urb;

// We will wait for 1 min before the reader returns
LARGE_INTEGER timeOut;
// 1 min = 60 sec, in units of 100 nano sec
timeOut.QuadPart = -60 * 1000 * 1000 * 10;

// Send URB to USBD
NTSTATUS status = IoCallDriver(pdx->LowerDeviceObject, Irp);

if (status == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event, Executive, KernelMode, FALSE, &timeOut);
if (status == STATUS_TIMEOUT) {
SmartcardDebug(DEBUG_INFO,
(“%s!SendAwaitUrb: cmd time out, cancelling IRP\n”, DRIVERNAME));
// We timed out, need to cancel the IRP
IoCancelIrp(Irp);
// Now wait for our completion routine to signal us
KeWaitForSingleObject(
&event, Executive, KernelMode, FALSE, NULL);
}
else {
// Since our completion routine returned STATUS_MORE_PROCESSING_NEEDED
that
// prevents USBD to finish the IRP, we need to do it here
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}

}

if (status != STATUS_SUCCESS)
SmartcardDebug(DEBUG_INFO,
(“%s!SendAwaitUrb: err 0x%x\n”, DRIVERNAME, status));

return status;
} // SendAwaitUrb