Tail.Overlay.OriginalFileObject

In my driver I attempt to use the libusb-win32 driver. I have the problem that my IRPs are passed down to another driver depending on the type of usb device while those of an user mode test application won’t, see a) and b) which are IRPtracker logs of my driver calls and identical API calls. I suspect that this happens because of following check in the USB driver (IRPs are passed down if it evaluates to false).

bool_t accept_irp(libusb_device_t *dev, IRP *irp)
{
/* check if the IRP is sent to libusb’s device object or to */
/* the lower one. This check is neccassary since the device object */
/* might be a filter */
if(irp->Tail.Overlay.OriginalFileObject)
{
return irp->Tail.Overlay.OriginalFileObject->DeviceObject
== dev->self ? TRUE : FALSE;
}

return FALSE;
}

My logs show that the OriginalFileObject is NULL in any IRP originating in my driver.
My driver does have a PFILE object that it got from IoGetDeviceObjectPointer().
I tried setting newIrp->Tail.Overlay.OriginalFileObject to this PFILE between IoBuildDeviceIoControlRequest() and IoCallDriver(), but that will BSOD.
See c) for my code.

Do I need to use any ddk function calls to do that, or what am I doing wrong? Maybe it works and BSOD comes from an unrelated problem? For some reason there is no dump created so i cannot tell.

Another Question: There is newIrp->IoStatus and the IoStatus that gets passed to IoBuildDeviceIoControlRequest(). Which of these will carry the number of bytes transferred once the IRP is completed? Or will both?

Thank you for reading this and any help will be greatly appreciated.

Best regards,
Fabian Cordes

a) driver call

NTAPI NtCreateFile dspys-test.exe \Device\DspSys0 CREATE
Call 0x819428B0-1724 (UNKNOWN) \Device\DspSys0 CREATE
Call 0x81DC8B48-1725 (UNKNOWN) \Device\libusb00001 DEVICE_CONTROL
Call 0x81DC8B48-1725 \Device\libusb00001 \Device_HID00000000 DEVICE_CONTROL
Comp 0x81DC8B48-1725 \Device_HID00000000 DEVICE_CONTROL INVALID_PARAMETER_1, Info = 0x0
Call 0x81DC8B48-1726 (UNKNOWN) \Device\libusb00001 DEVICE_CONTROL
Call 0x81DC8B48-1726 \Device\libusb00001 \Device_HID00000000 DEVICE_CONTROL
Comp 0x81DC8B48-1726 \Device_HID00000000 DEVICE_CONTROL INVALID_PARAMETER_1, Info = 0x0
Comp 0x819428B0-1724 \Device\DspSys0 CREATE SUCCESS, Info = 0x0
NTAPIRet NtCreateFile dspys-test.exe \Device\DspSys0 CREATE SUCCESS
NTAPI NtDeviceIoControlFile dspys-test.exe \Device\DspSys0 DEVICE_CONTROL
Call 0x819428B0-1727 (UNKNOWN) \Device\DspSys0 DEVICE_CONTROL
Comp 0x819428B0-1727 \Device\DspSys0 DEVICE_CONTROL SUCCESS, Info = 0x1
NTAPIRet NtDeviceIoControlFile dspys-test.exe \Device\DspSys0 DEVICE_CONTROL SUCCESS
NTAPI NtClose dspys-test.exe \Device\DspSys0 CLEANUP
Call 0x819428B0-1728 (UNKNOWN) \Device\DspSys0 CLEANUP
Comp 0x819428B0-1728 \Device\DspSys0 CLEANUP INVALID_DEVICE_REQUEST, Info = 0x0
Call 0x819428B0-1729 (UNKNOWN) \Device\DspSys0 CLOSE
Comp 0x819428B0-1729 \Device\DspSys0 CLOSE SUCCESS, Info = 0x0
NTAPIRet NtClose dspys-test.exe \Device\DspSys0 CLEANUP SUCCESS

b) API call

NTAPI NtCreateFile usb_cli.exe \Device\libusb00001 CREATE
Call 0x81E43008-1719 (UNKNOWN) \Device\libusb00001 CREATE
Comp 0x81E43008-1719 \Device\libusb00001 CREATE SUCCESS, Info = 0x0
NTAPIRet NtCreateFile usb_cli.exe \Device\libusb00001 CREATE SUCCESS
NTAPI NtDeviceIoControlFile usb_cli.exe \Device\libusb00001 DEVICE_CONTROL
Call 0x81E43008-1720 (UNKNOWN) \Device\libusb00001 DEVICE_CONTROL
Comp 0x81E43008-1720 \Device\libusb00001 DEVICE_CONTROL SUCCESS, Info = 0x18
NTAPIRet NtDeviceIoControlFile usb_cli.exe \Device\libusb00001 DEVICE_CONTROL SUCCESS
NTAPI NtDeviceIoControlFile usb_cli.exe \Device\libusb00001 DEVICE_CONTROL
Call 0x81E43008-1721 (UNKNOWN) \Device\libusb00001 DEVICE_CONTROL
Comp 0x81E43008-1721 \Device\libusb00001 DEVICE_CONTROL SUCCESS, Info = 0x0
NTAPIRet NtDeviceIoControlFile usb_cli.exe \Device\libusb00001 DEVICE_CONTROL SUCCESS
NTAPI NtClose usb_cli.exe \Device\libusb00001 CLEANUP
Call 0x81E43008-1722 (UNKNOWN) \Device\libusb00001 CLEANUP
Comp 0x81E43008-1722 \Device\libusb00001 CLEANUP SUCCESS, Info = 0x0
Call 0x81E43008-1723 (UNKNOWN) \Device\libusb00001 CLOSE
Comp 0x81E43008-1723 \Device\libusb00001 CLOSE SUCCESS, Info = 0x0
NTAPIRet NtClose usb_cli.exe \Device\libusb00001 CLEANUP SUCCESS

c) used code

NTSTATUS DspSys_DispatchCreate(IN PDEVICE_OBJECT devObj,IN PIRP Irp)
{
NTSTATUS result;
UNICODE_STRING targetObjectNameUcString;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK IoStatus;
UCHAR bResult;
ULONG ret;
libusb_request req;

KEVENT Event;
PIRP newIrp = NULL;
PDEVICE_EXTENSION deviceExtension;
PFILE_OBJECT libusbFileObject;
PDEVICE_OBJECT libusbDeviceObject;

struct usb_device_descriptor usbDevDesc;

DbgPrint((“DspSys: DispatchCreate: Entered\n”));
// Assume successful operation and change it if something happens later
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;

deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
libusbFileObject = deviceExtension->libusbFileObject;
libusbDeviceObject = deviceExtension->NextDeviceObject;

DbgPrint(“DspSys: KeInitializeEvent()\n”);
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);

// Send a request for driver version
RtlZeroMemory(&req, sizeof(libusb_request));
DbgPrint(“DspSys: IoBuildDeviceIoControlRequest()\n”);
newIrp = IoBuildDeviceIoControlRequest(
LIBUSB_IOCTL_GET_VERSION,
libusbDeviceObject,
&req,
sizeof (libusb_request),
&req,
sizeof (libusb_request),
FALSE,
&Event,
&IoStatus);

if (newIrp == NULL)
{
// Unable to interface to LibUSB, so fail creation
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint(" failed\n");
return;

} else
{
DbgPrint(“successful\n”);

}

newIrp->Tail.Overlay.OriginalFileObject = libusbFileObject;
DbgPrint(“DspSys: IoStatus=%X, Irp->IoStatus=%X\n”, IoStatus.Status, newIrp->IoStatus.Status);

DbgPrint(“DspSys: IoCallDriver()\n”);
DbgPrint(“DspSys: libusbDeviceObject=%X, newIrp=%X\n”, libusbDeviceObject, newIrp);
result = IoCallDriver( libusbDeviceObject,
newIrp);

if (result == STATUS_PENDING)
{
DbgPrint(“DspSys: KeWaitForSingleObject()\n”);
KeWaitForSingleObject(&Event, UserRequest, KernelMode, TRUE, NULL);
result = newIrp->IoStatus.Status;
}

if(NT_SUCCESS(result))
{
DbgPrint(“DspSys: IRP completed\n”);
} else
{
DbgPrint(“DspSys: IRP failed, result=%X\n”, newIrp->IoStatus.Status);
}
DbgPrint(“DspSys: IRP IoStatus: %X\n”, newIrp->IoStatus.Status);
DbgPrint(“DspSys: Read %u bytes\n”, newIrp->IoStatus.Information);
DbgPrint(“DspSys: local IoStatus: %X\n”, newIrp->IoStatus.Status);
DbgPrint(“DspSys: Read %u bytes\n”, IoStatus.Information);
DbgPrint(“DspSys: Should be %u\n”, sizeof(libusb_request));
DbgPrint(“DspSys: %u for device object\n”, sizeof(struct usb_device));
DbgPrint(“DspSys: LibUSB reported Version %u.%u.%u.%u\n”,req.version.major,
req.version.micro,
req.version.minor,
req.version.nano);

DbgPrint(“libusgSetDebugLevel()\n”);
libusbSetDebug(&req);

IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint(“DspSys: DispatchCreate: Exiting\n”);
return STATUS_SUCCESS;
}

> /* check if the IRP is sent to libusb’s device object or to */

/* the lower one. This check is neccassary since the device object */
/* might be a filter */

Bug in libusb, it should not do such distinction this way.

if(irp->Tail.Overlay.OriginalFileObject)

Bug in libusb: touching the undocumented and unsupported IRP field.

Probably you should avoid this buggy code and use the well-supported WinUSB instead.

Another Question: There is newIrp->IoStatus and the IoStatus that gets passed to
IoBuildDeviceIoControlRequest(). Which of these will carry the number of bytes transferred once the
IRP is completed? Or will both?

I would never ever create threaded IRPs in my driver. Just plain so - I think they are intended for syscall implementations only, not for driver-to-driver communication. So, I suggest to never use IoBuildDeviceIoControlRequest. Use IoAllocateIrp and fill the rest of the fields yourself - not this complex.

For the yet-uncompleted IRP (at the moment of IoCompleteRequest), Irp->IoStatus.Information must be filled to number of bytes to be transferred.

What about the IoStatus argument to IoBuildDeviceIoControlRequest - I don’t know (just due to my dislike to threaded IRPs).


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com