From: Sushma on
Hi All,

When i intercept the MJ_INTERNAL_DEVICE_CONTROL IRP for my usb mass
storage device in usbstor lower filter I get a BSOD when completing
the original request.

Basically when I get the request I encrypt the data buffer in filter
before sending it to device. I create a new request and a URB for the
request. But when I try complete the original request in completion
routine I get BSOD (DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)). Here is the
stack trace and source code. Can some one provide a hint where I'm
going wrong.

Regards,
Sushma

STACK_TEXT:
f895c7ac 804f8df9 00000003 f895cb08 00000000 nt!
RtlpBreakWithStatusInstruction
f895c7f8 804f99e4 00000003 00000018 f83391cc nt!KiBugCheckDebugBreak
+0x19
f895cbd8 805446e0 0000000a 00000018 00000002 nt!KeBugCheck2+0x574
f895cbd8 f83391cc 0000000a 00000018 00000002 nt!KiTrap0E+0x238
f895cc98 f8339325 82dd93d0 82af7390 f836ba8c wdf01000!
FxRequestBase::CompleteSubmittedNoContext+0x18
f895ccb4 f831dc36 82b9d6fb 82af7390 00000000 wdf01000!
FxRequestBase::CompleteSubmitted+0x104
f895ccd0 f831dcde 01dd93d0 82b916c8 f895ccfc wdf01000!
FxIoTarget::RequestCompletionRoutine+0x12d
f895cce0 804f080d 82adb2a0 82b9d640 82dd93d0 wdf01000!
FxIoTarget::_RequestCompletionRoutine+0x35
f895ccfc 804f16b0 82adb2a0 82b9d640 82b916c8 nt!IopUnloadSafeCompletion
+0x1d
f895cd2c f8336d6b 82dd93d0 aa2102a0 00000000 nt!IopfCompleteRequest
+0xa2
f895cd54 f8329757 00000000 00000000 00000000 wdf01000!
FxRequest::CompleteInternal+0x379
f895cd70 aa20faea 00000000 82dd93d0 00000000 wdf01000!
imp_WdfRequestComplete+0x108
WARNING: Stack unwind information not available. Following frames may
be wrong.
f895cd84 aa2102ea 7d226c28 00000000 825a71d8 lfilter+0xaea
f895cd98 f8339217 7d2467b0 7d508c68 f895cdbc lfilter+0x12ea
f895cde4 f8339325 82db9848 82af7390 f836ba8c wdf01000!
FxRequestBase::CompleteSubmittedNoContext+0x63
f895ce00 f831dc36 82f71af7 82af7390 00000000 wdf01000!
FxRequestBase::CompleteSubmitted+0x104
f895ce1c f831dcde 01db9848 828ae378 f895ce48 wdf01000!
FxIoTarget::RequestCompletionRoutine+0x12d
f895ce2c 804f080d 00000000 82f71a60 82db9848 wdf01000!
FxIoTarget::_RequestCompletionRoutine+0x35
f895ce48 804f16b0 00000000 82f71a60 828ae378 nt!IopUnloadSafeCompletion
+0x1d
f895ce78 f7fb70d5 82f71a60 82617498 82e0e028 nt!IopfCompleteRequest
+0xa2
f895cee0 f7fb7d47 82dbef00 00000000 82e0e7d8 USBPORT!
USBPORT_CompleteTransfer+0x373
f895cf10 f7fb8944 026e6f44 82e0e0e0 82e0e0e0 USBPORT!
USBPORT_DoneTransfer+0x137
f895cf48 f7fba13a 82e0e028 80546abc 82e0e230 USBPORT!
USBPORT_FlushDoneTransferList+0x16c
f895cf74 f7fc824b 82e0e028 80546abc 82e0e028 USBPORT!USBPORT_DpcWorker
+0x224
f895cfb0 f7fc83c2 82e0e028 00000001 806e6427 USBPORT!
USBPORT_IsrDpcWorker+0x38f
f895cfcc 80545e6f 82e0e64c 6b755044 00000000 USBPORT!USBPORT_IsrDpc
+0x166
f895cff4 805459db f85e433c 00000000 00000000 nt!KiRetireDpcList+0x61
f895cff8 f85e433c 00000000 00000000 00000000 nt!KiDispatchInterrupt
+0x2b
805459db 00000000 00000009 0081850f bb830000 0xf85e433c


VOID
FilterEvtIoInternalDeviceControl(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
{
NTSTATUS status = STATUS_SUCCESS;

WDF_REQUEST_PARAMETERS_INIT(&params);
WdfRequestGetParameters(Request, &params);
urb = (PURB) params.Parameters.Others.Arg1;
device = WdfIoQueueGetDevice(Queue);
filterExt = FilterGetData(device);

switch (IoControlCode) {
case IOCTL_INTERNAL_USB_SUBMIT_URB:
switch(urb->UrbHeader.Function)
{
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
if(CBW || CSW)
{
ret = WdfRequestSend(Request,
Target,
WDF_NO_SEND_OPTIONS);

if (ret == FALSE) {
status = WdfRequestGetStatus (Request);
WdfRequestComplete(Request, status);
}
}

if(DataBuffer)
{
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = ioTarget;

status = WdfRequestCreate(
&attributes,
ioTarget,
&filterExt->NewRequest
);

if (!NT_SUCCESS(status))
{
goto Exit;
}

WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = Request;


status = WdfMemoryCreate(
&attributes,
NonPagedPool,
POOL_TAG,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
&urbMemory,
(PVOID*) &pUrb
);

if (!NT_SUCCESS(status)) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}

filterExt->pUrb = pUrb;

filterExt->RequestToComplete = Request;


OldIrp = WdfRequestWdmGetIrp(Request);
virtualAddress = (ULONG_PTR) MmGetSystemAddressForMdlSafe(OldIrp-
>MdlAddress, NormalPagePriority);
totalLength = pUrb-
>UrbBulkOrInterruptTransfer.TransferBufferLength;

status = FilterEncrypt(Request, filterExt->NewRequest, filterExt)

if (!NT_SUCCESS(status)) {
goto Exit;
}

filterExt->newMdl = IoAllocateMdl((PVOID) virtualAddress,
totalLength,
FALSE,
FALSE,
NULL);

if (filterExt->newMdl == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}

Irp = WdfRequestWdmGetIrp(filterExt->NewRequest);
Irp->MdlAddress = filterExt->newMdl;
MmBuildMdlForNonPagedPool(filterExt->newMdl);

UsbBuildInterruptOrBulkTransferRequest(
filterExt->pUrb,
sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pUrb->UrbBulkOrInterruptTransfer.PipeHandle,
NULL,
filterExt->newMdl,
totalLength,
pUrb->UrbBulkOrInterruptTransfer.TransferFlags,
NULL
);

NextStack =
IoGetNextIrpStackLocation(WdfRequestWdmGetIrp(filterExt->NewRequest));

NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextStack->Parameters.Others.Argument1 = filterExt->pUrb;
NextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;

// Setup completion proc
WdfRequestSetCompletionRoutine(filterExt->NewRequest,
FilterBulkOnlySendDataComplete, filterExt);

if (WdfRequestSend(filterExt->NewRequest,
WdfDeviceGetIoTarget(filterExt->WdfDevice),
WDF_NO_SEND_OPTIONS) == FALSE)
{
status = WdfRequestGetStatus(filterExt->NewRequest);
}
}
default:
//do something
}
default:
// do something
}

Exit:
WdfRequestComplete(Request, CompletionParams->IoStatus.Status);
}

VOID
FilterBulkOnlySendDataComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PFILTER_EXTENSION filterExt;

filterExt = (PFILTER_EXTENSION)Context;
WdfRequestComplete(filterExt->RequestToComplete, CompletionParams-
>IoStatus.Status);

IoFreeMdl(filterExt->newMdl);
WdfObjectDelete(filterExt->NewRequest);

return;
}


From: Sushma on
I'm desperately looking out for a fix as I'm not able to proceed
further. Can some one look into code or suggest an alternate way to
achieve what I wanted to do.

Thank You.

Regards,
sushma
From: Philip Ries [MSFT] on
You might be completing an invalid request. Why don't you complete the
request that is being completed to you, that is, the Request parameter
of FilterBulkOnlySendDataComplete?

Sushma wrote:
> I'm desperately looking out for a fix as I'm not able to proceed
> further. Can some one look into code or suggest an alternate way to
> achieve what I wanted to do.
>
> Thank You.
>
> Regards,
> sushma
From: Sushma on

> You might be completing an invalid request.  Why don't you complete the
> request that is being completed to you, that is, the Request parameter
> of FilterBulkOnlySendDataComplete?
>

I do not think I can do that as the request was created in the driver.
The request parameter of FilterBulkOnlySendDataComplete is the one
created in my driver. However, I tried to complete it but there was
BSOD with same error.

One strange thing I observed is that if I do not complete any request
in my completion routine, there was no crash. When I tried move some
data to device few requests were successful but after copying some
data it just got stuck at completion routine and I get a reset port
request. This may not be correct, I just took a chance.

Is there any other way to complete the original request after the
completion routine of newly created request is invoked?

Thank You.

Regards,
Sushma


From: Sushma on
When I had used WDM way (IoCompleteRequest instead of
WdfRequestComplete) to complete the original request there was no
BSOD. I think the request got corrupted by mixing WDM and WDF.

The reason I had to use WDM was I need mdl pointer in the IRP. I had
tried using WdfRequestRetrieveInputWdmMdl, but it failed with
STATUS_INVALID_DEVICE_REQUEST.

I'm not sure for the reason for failure.

Thank You.

Regards,
Sushma