usb filter driver issue..

I have developed a usb lower filter driver…under usbstor.sys
Now, I want to create a new IRP and pass it to the lower driver and then complete the original Irp.
The following is my source code… May you please help to point out the error… Thanks…

My program logic is as follows,

When the upper functional driver send the IRP_MJ_INTERNAL_CONTROL irp to my filter driver…
That is in “DispatchInternalDeviceControl” routine, I would like to build a new Irp by “IoBuildDeviceIoControlRequest”
and send it down to the lower driver, since the IRQL is in Dispatch Level now, I can not wait for an event for my new Irp for finishing my work.
Instead, I set up an completion routine for my own new irp, I try to complete the original irp in that completion routine, then I will find a new Irp sent from upper driver immediately before my completion routine return a status… then loop for a while, it will hang up the system…

I also try to init a workitem in my completion routine and expect to complete the original Irp in the workqueue, but callling IoQueueWorkItem would cause page fault in my completion routine…

Do anyone have any idea about how to process the original Irp ??
Thanks for your help…

Best Regards!!

-Steel Chueh

NTSTATUS DispatchInternalDeviceControl(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{
PURB urb;
NTSTATUS status;
PIO_STACK_LOCATION stack;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
PDEVICE_EXTENSION pdx1;

KdPrintf((DRIVERNAME “-InternalDeviceControl\n”));

status=STATUS_SUCCESS;

//BreakPoint();

status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);

stack=IoGetCurrentIrpStackLocation(Irp);

switch(stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_USB_SUBMIT_URB:

case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:

KdPrint((“Write Data\n”));
BreakPoint();
PIRP irp1;
PURB urb1;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION currStack;
PIO_STACK_LOCATION nextStack;
urb1 = (PURB)ExAllocatePool(NonPagedPool,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));

PUCHAR inbuf,outbuf;
PUCHAR buffer2;
buffer2 = (PUCHAR)ExAllocatePool(NonPagedPool,length);
RtlCopyMemory(buffer2,buffer1,length);

UsbBuildInterruptOrBulkTransferRequest(
urb1,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
urb->UrbBulkOrInterruptTransfer.PipeHandle,
buffer2,
NULL,
length,
USBD_TRANSFER_DIRECTION_OUT,
NULL
);

irp1 = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->LowerDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
//&event,
NULL,
&ioStatus);

if ( irp1 == NULL )
{
BreakPoint();
return STATUS_INSUFFICIENT_RESOURCES;
}

IoSetNextIrpStackLocation(irp1);
currStack = IoGetCurrentIrpStackLocation(irp1);
nextStack = IoGetNextIrpStackLocation(irp1);

nextStack->MajorFunction=IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode=IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->Parameters.Others.Argument1 = urb1;

pdx->buffer=buffer2;
pdx->urb=urb1;
pdx->irp=Irp;

irp1->Tail.Overlay.Thread=Irp->Tail.Overlay.Thread;

IoSetCompletionRoutine(irp1,
URB_Write_Complete,
pdx,
TRUE,
TRUE,
TRUE);

status=IoCallDriver(pdx->LowerDeviceObject,irp1);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
}
}

NTSTATUS URB_Write_Complete(IN PDEVICE_OBJECT fido,IN PIRP Irp,IN PVOID context)
{
PDEVICE_EXTENSION pdx;
PURB urb;

// UNREFERENCED_PARAMETER(fido);

KdPrinta((“WriteNo Complete\n”));
BreakPoint();

pdx=(PDEVICE_EXTENSION)context;
//urb = (PURB) context;

ExFreePool(pdx->urb);
ExFreePool(pdx->buffer);

pdx->irp->IoStatus.Status = STATUS_SUCCESS;
pdx->irp->IoStatus.Information = 0;
IoCompleteRequest(pdx->irp, IO_NO_INCREMENT);
KdPrinta((“WriteNo 2 Complete\n”));
BreakPoint();

//pdx->workitem=IoAllocateWorkItem(fido);
//if (pdx->workitem == NULL )
//{
// BreakPoint();
// return STATUS_INSUFFICIENT_RESOURCES;
//}

//IoQueueWorkItem(
// pdx->workitem,
// URB_WriteIrp_Complete,
// DelayedWorkQueue,
// pdx);

return STATUS_MORE_PROCESSING_REQUIRED;
return STATUS_SUCCESS;
}

// Work Item routine
VOID URB_WriteIrp_Complete(IN PDEVICE_OBJECT fido,IN PVOID context)
{
PDEVICE_EXTENSION pdx;
PURB urb;

//UNREFERENCED_PARAMETER(fido);

KdPrinta((“Work Item\n”));
BreakPoint();

pdx = (PDEVICE_EXTENSION) context;

IoFreeWorkItem(pdx->workitem);

pdx->irp->IoStatus.Status = STATUS_SUCCESS;
pdx->irp->IoStatus.Information = 0;
IoCompleteRequest(pdx->irp, IO_NO_INCREMENT);

//return STATUS_SUCCESS;
}


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

I have developed a usb lower filter driver.
Now, I want to create a new IRP and pass it to the lower driver and then
complete the original Irp.

My program logic is as follows,

When the upper functional driver send the IRP_MJ_INTERNAL_CONTROL irp to my
filter driver…
That is in “DispatchInternalDeviceControl” routine, I would like to build
a new Irp by “IoBuildDeviceIoControlRequest”
and send it down to the lower driver, since the IRQL is in Dispatch Level
now, I can not wait for an event for my new Irp for finishing my work.
Instead, I set up an completion routine for my own new irp, I try to
complete the original irp in that completion routine, then I will find a
new Irp sent from upper driver immediately before my completion routine
return a status… then loop for a while, it will hang up the system…

I also try to init a workitem in my completion routine and expect to
complete the original Irp in the workqueue, but callling IoQueueWorkItem
would cause page fault in my completion routine…

Do anyone have any idea about how to process the original Irp ??
Thanks for your help…

Best Regards!!

-Steel Chueh

NTSTATUS DispatchInternalDeviceControl(IN PDEVICE_OBJECT fido, IN PIRP
Irp)
{
PURB urb;
NTSTATUS status;
PIO_STACK_LOCATION stack;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
PDEVICE_EXTENSION pdx1;

KdPrintf((DRIVERNAME “-InternalDeviceControl\n”));

status=STATUS_SUCCESS;

//BreakPoint();

status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);

stack=IoGetCurrentIrpStackLocation(Irp);

switch(stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_USB_SUBMIT_URB:

case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:

KdPrint((“Write Data\n”));
BreakPoint();
PIRP irp1;
PURB urb1;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION currStack;
PIO_STACK_LOCATION nextStack;
urb1 = (PURB)ExAllocatePool(NonPagedPool,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));

PUCHAR inbuf,outbuf;
PUCHAR buffer2;
buffer2 = (PUCHAR)ExAllocatePool(NonPagedPool,length);
RtlCopyMemory(buffer2,buffer1,length);

UsbBuildInterruptOrBulkTransferRequest(
urb1,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
urb->UrbBulkOrInterruptTransfer.PipeHandle,
buffer2,
NULL,
length,
USBD_TRANSFER_DIRECTION_OUT,
NULL
);

irp1 = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->LowerDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
//&event,
NULL,
&ioStatus);

if ( irp1 == NULL )
{
BreakPoint();
return STATUS_INSUFFICIENT_RESOURCES;
}

IoSetNextIrpStackLocation(irp1);
currStack = IoGetCurrentIrpStackLocation(irp1);
nextStack = IoGetNextIrpStackLocation(irp1);

nextStack->MajorFunction=IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode=IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->Parameters.Others.Argument1 = urb1;

pdx->buffer=buffer2;
pdx->urb=urb1;
pdx->irp=Irp;

irp1->Tail.Overlay.Thread=Irp->Tail.Overlay.Thread;

IoSetCompletionRoutine(irp1,
URB_Write_Complete,
pdx,
TRUE,
TRUE,
TRUE);

status=IoCallDriver(pdx->LowerDeviceObject,irp1);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
}
}

NTSTATUS URB_Write_Complete(IN PDEVICE_OBJECT fido,IN PIRP Irp,IN PVOID
context)
{
PDEVICE_EXTENSION pdx;
PURB urb;

// UNREFERENCED_PARAMETER(fido);

KdPrinta((“WriteNo Complete\n”));
BreakPoint();

pdx=(PDEVICE_EXTENSION)context;
//urb = (PURB) context;

ExFreePool(pdx->urb);
ExFreePool(pdx->buffer);

pdx->irp->IoStatus.Status = STATUS_SUCCESS;
pdx->irp->IoStatus.Information = 0;
IoCompleteRequest(pdx->irp, IO_NO_INCREMENT);
KdPrinta((“WriteNo 2 Complete\n”));
BreakPoint();

//pdx->workitem=IoAllocateWorkItem(fido);
//if (pdx->workitem == NULL )
//{
// BreakPoint();
// return STATUS_INSUFFICIENT_RESOURCES;
//}

//IoQueueWorkItem(
// pdx->workitem,
// URB_WriteIrp_Complete,
// DelayedWorkQueue,
// pdx);

return STATUS_MORE_PROCESSING_REQUIRED;
return STATUS_SUCCESS;
}

// Work Item routine
VOID URB_WriteIrp_Complete(IN PDEVICE_OBJECT fido,IN PVOID context)
{
PDEVICE_EXTENSION pdx;
PURB urb;

//UNREFERENCED_PARAMETER(fido);

KdPrinta((“Work Item\n”));
BreakPoint();

pdx = (PDEVICE_EXTENSION) context;

IoFreeWorkItem(pdx->workitem);

pdx->irp->IoStatus.Status = STATUS_SUCCESS;
pdx->irp->IoStatus.Information = 0;
IoCompleteRequest(pdx->irp, IO_NO_INCREMENT);

//return STATUS_SUCCESS;
}


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

>“IoBuildDeviceIoControlRequest”

and send it down to the lower driver, since the IRQL is in Dispatch Level now, I can not wait
for an event for my new Irp for finishing my work.
Instead, I set up an completion routine for my own new irp, I try to complete the original irp in

Then do not use IoBuildDeviceIoControlRequest and use IoAllocateIrp instead.

Max


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com