Irp Completion

Hello all !
I have a delayed IRP to be completed.
But when I complete it I get a blue screen :-((
Could you tell me why did it happen ?
and what should I do to avoid the problem ?

here is IRP description :

kd> !IRP 0xff6a0e48 struct _IRP *
Irp is active with 4 stacks 4 is current (= 0xff6a0f24)
No Mdl Thread ff624b48: Irp stack trace. Pending has been returned
Flags = 00000000
ThreadListEntry.Flink = ff6a0e58
ThreadListEntry.Blink = ff6a0e58
IoStatus.Status = 00000000
IoStatus.Information = 00000000
RequestorMode = 00000001
Cancel = 01
CancelIrql = 0
ApcEnvironment = 00
UserIosb = 00155b38
UserEvent = 00000000
Overlay.AsynchronousParameters.UserApcRoutine = 00000000
Overlay.AsynchronousParameters.UserApcContext = 00155b30
Overlay.AllocationSize = 00000000 - 00000000
CancelRoutine = 00000000
UserBuffer = 00155b38
&Tail.Overlay.DeviceQueueEntry = ff6a0e88
Tail.Overlay.Thread = ff624b48
Tail.Overlay.AuxiliaryBuffer = 00000000
Tail.Overlay.ListEntry.Flink = 00000000
Tail.Overlay.ListEntry.Blink = 00000000
Tail.Overlay.CurrentStackLocation = ff6a0f24
Tail.Overlay.OriginalFileObject = ff652d18
Tail.Apc = 00000000
Tail.CompletionKey = 00000000
cmd flg cl Device File Completion-Context
[0, 0] 0 0 00000000 00000000 00000000-00000000

Args: 00000000 00000000 00000000 00000000
[f, 0] 0 0 ffb0d100 00000000 fc3397e0-ffb000d8
\Driver\Tcpip MYDRV!TDI_ConnectComplete
Args: 00000000 00000000 00000000 00000000
[f, 0] 0 0 ffb00020 00000000 fb7f1ce4-ff74d008
\Driver\MYDRV afd!AfdRestartConnect
Args: 00000000 00000000 00000000 00000000

[e, 1] 0 1 ff8717b8 ff71ac08 00000000-00000000 pending
\Driver\AFD
Args: 00000008 00000022 00012007 00155b48

Foxgen

“xxxxx@yandex” wrote:

I have a delayed IRP to be completed.
But when I complete it I get a blue screen :-((

Tell us the bug code first. If it indicates multiple completion, than
you probably didn’t manage the pending flag exactly right. A typical
scenario would be this:

Dispatch routine:
IoMarkIrpPending()

return STATUS_PENDING

Elsewhere:

IoCompleteRequest();

The Cancel flag is also set in your IRP, which suggests that someone has
called IoCancelIrp. If you have a cancel routine in place while you’re
delaying the IRP, it may have completed the IRP already. If you’re new
at this, you may also have mishandled the race between your cancel
routine and the code that attempts to retrieve and complete the IRP. My
best advice here would be to use the “pending IOCTL” scheme outlined in
my WDM book.


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

My scheme is the following :

  1. IoSetCompletionRoutine(), IoCallDriver()
  2. In completion routine : IoMarkIrpPending(), ,
    return STATUS_MORE_PROCESSING_REQUIRED;
    3. In a worker thread I wait for a very long time (couple of days) and
    then execute IoCompleteRequest(), which crashes system.

    WO> “xxxxx@yandex” wrote:
    >> I have a delayed IRP to be completed.
    >> But when I complete it I get a blue screen :-((

    WO> Tell us the bug code first. If it indicates multiple completion, than
    WO> you probably didn’t manage the pending flag exactly right. A typical
    WO> scenario would be this:

    WO> Dispatch routine:
    WO> IoMarkIrpPending()
    WO>
    WO> return STATUS_PENDING

    WO> Elsewhere:
    WO>
    WO> IoCompleteRequest();

    WO> The Cancel flag is also set in your IRP, which suggests that someone has
    WO> called IoCancelIrp. If you have a cancel routine in place while you’re
    WO> delaying the IRP, it may have completed the IRP already. If you’re new
    WO> at this, you may also have mishandled the race between your cancel
    WO> routine and the code that attempts to retrieve and complete the IRP. My
    WO> best advice here would be to use the “pending IOCTL” scheme outlined in
    WO> my WDM book.

    WO> –
    WO> Walter Oney, Consulting and Training
    WO> Basic and Advanced Driver Programming Seminars
    WO> Now teaming with John Hyde for USB Device Engineering Seminars
    WO> Check out our schedule at http://www.oneysoft.com

    WO> —
    WO> You are currently subscribed to ntdev as: xxxxx@yandex.ru
    WO> To unsubscribe send a blank email to xxxxx@lists.osr.com

    Foxgen

What do you return in your dispatch routine? Do you do something like:

return IoCallDriver?

If so, that would lead to your problem (return STATUS_SUCCESS but mark the
IRP as pending…)

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@yandex [mailto:xxxxx@yandex.ru]
Sent: Monday, May 12, 2003 9:24 AM
To: NT Developers Interest List
Subject: [ntdev] Re: Irp Completion

My scheme is the following :

  1. IoSetCompletionRoutine(), IoCallDriver()
  2. In completion routine : IoMarkIrpPending(), ,
    return STATUS_MORE_PROCESSING_REQUIRED;
    3. In a worker thread I wait for a very long time (couple of days) and
    then execute IoCompleteRequest(), which crashes system.

    WO> “xxxxx@yandex” wrote:
    >> I have a delayed IRP to be completed.
    >> But when I complete it I get a blue screen :-((

    WO> Tell us the bug code first. If it indicates multiple completion, than
    WO> you probably didn’t manage the pending flag exactly right. A typical
    WO> scenario would be this:

    WO> Dispatch routine:
    WO> IoMarkIrpPending()
    WO>
    WO> return STATUS_PENDING

    WO> Elsewhere:
    WO>
    WO> IoCompleteRequest();

    WO> The Cancel flag is also set in your IRP, which suggests that someone has
    WO> called IoCancelIrp. If you have a cancel routine in place while you’re
    WO> delaying the IRP, it may have completed the IRP already. If you’re new
    WO> at this, you may also have mishandled the race between your cancel
    WO> routine and the code that attempts to retrieve and complete the IRP. My
    WO> best advice here would be to use the “pending IOCTL” scheme outlined in
    WO> my WDM book.

    WO> –
    WO> Walter Oney, Consulting and Training
    WO> Basic and Advanced Driver Programming Seminars
    WO> Now teaming with John Hyde for USB Device Engineering Seminars
    WO> Check out our schedule at http://www.oneysoft.com

    WO> —
    WO> You are currently subscribed to ntdev as: xxxxx@yandex.ru
    WO> To unsubscribe send a blank email to xxxxx@lists.osr.com

    Foxgen


    You are currently subscribed to ntdev as: xxxxx@osr.com
    To unsubscribe send a blank email to xxxxx@lists.osr.com

ntStatus = IoCallDriver (HookerDevExt->LowerDeviceObject, Irp);
return ntStatus;

but I guess it doesnt lead to a problem( I mark Irp pending in my
completion routine … not in dispatch routine ! )

TM> What do you return in your dispatch routine? Do you do something like:

TM> return IoCallDriver?

TM> If so, that would lead to your problem (return STATUS_SUCCESS but mark the
TM> IRP as pending…)

TM> Regards,

TM> Tony

TM> Tony Mason
TM> Consulting Partner
TM> OSR Open Systems Resources, Inc.
TM> http://www.osr.com

TM> -----Original Message-----
TM> From: xxxxx@yandex [mailto:xxxxx@yandex.ru]
TM> Sent: Monday, May 12, 2003 9:24 AM
TM> To: NT Developers Interest List
TM> Subject: [ntdev] Re: Irp Completion

TM> My scheme is the following :
TM> 1. IoSetCompletionRoutine(), IoCallDriver()
TM> 2. In completion routine : IoMarkIrpPending(), ,
TM> return STATUS_MORE_PROCESSING_REQUIRED;
TM> 3. In a worker thread I wait for a very long time (couple of days) and
TM> then execute IoCompleteRequest(), which crashes system.

WO>> “xxxxx@yandex” wrote:
>>> I have a delayed IRP to be completed.
>>> But when I complete it I get a blue screen :-((

WO>> Tell us the bug code first. If it indicates multiple completion, than
WO>> you probably didn’t manage the pending flag exactly right. A typical
WO>> scenario would be this:

WO>> Dispatch routine:
WO>> IoMarkIrpPending()
WO>>
WO>> return STATUS_PENDING

WO>> Elsewhere:
WO>>
WO>> IoCompleteRequest();

WO>> The Cancel flag is also set in your IRP, which suggests that someone has
WO>> called IoCancelIrp. If you have a cancel routine in place while you’re
WO>> delaying the IRP, it may have completed the IRP already. If you’re new
WO>> at this, you may also have mishandled the race between your cancel
WO>> routine and the code that attempts to retrieve and complete the IRP. My
WO>> best advice here would be to use the “pending IOCTL” scheme outlined in
WO>> my WDM book.

WO>> –
WO>> Walter Oney, Consulting and Training
WO>> Basic and Advanced Driver Programming Seminars
WO>> Now teaming with John Hyde for USB Device Engineering Seminars
WO>> Check out our schedule at http://www.oneysoft.com

WO>> —
WO>> You are currently subscribed to ntdev as: xxxxx@yandex.ru
WO>> To unsubscribe send a blank email to xxxxx@lists.osr.com

TM> Foxgen

TM> —
TM> You are currently subscribed to ntdev as: xxxxx@osr.com
TM> To unsubscribe send a blank email to xxxxx@lists.osr.com

TM> —
TM> You are currently subscribed to ntdev as: xxxxx@yandex.ru
TM> To unsubscribe send a blank email to xxxxx@lists.osr.com

Foxgen

“xxxxx@yandex” wrote:

ntStatus = IoCallDriver (HookerDevExt->LowerDeviceObject, Irp);
return ntStatus;

Just don’t do it this way, because it leads to the problem you’re
experiencing. Upstream code may interpret a non-pending status to mean
that the IRP was completed synchronously and to perform cleanup
processing. When IoCompleteRequest eventually sees the pending flag, it
will schedule an APC that will *also* do the cleanup processing, and
that leads to a multiple-completion bugcheck.

If you have my WDM book, you can find out way more than you probably
ever wanted to know about the pending flag on pp. 247-54.


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

Well, Windbg says bugcheck is not multiple completion …
And I tried to do the following trick : when I see CancelFlag set, I dont
complete IRP (I guess it was completed already)
But such scheme leads to incorrect system boot - system hangs
infinitely after login (I write firewall filter driver)

You suggest to install CancelRoutine … But what should I do inside
it ? I dont have and queue for my penging IRP’s, so I dont need to
dequeue anything …

here is more detailed code:
So Could you convince me of this code incorrectness ?

TDI_Connect()
{

IoCopyCurrentIrpStackLocationToNext ( Irp );

IoSetCompletionRoutine(
Irp,
TDI_ConnectComplete,
HookerDevExt,
TRUE,
TRUE,
FALSE // I dont want to be called when
// cancelled
);

ntStatus = IoCallDriver (HookerDevExt->LowerDeviceObject, Irp);

return ntStatus;
}

TDI_ConnectComplete()
{
NTSTATUS ntStatus = Irp->IoStatus.Status;

PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation ( Irp );

IoMarkIrpPending(Irp);

CompleteContext = ExAllocatePoolWithTag (NonPagedPool, sizeof (IRP_COMPLETE_CONTEXT), COMMON_TAG);
if (CompleteContext == NULL || ntStatus != STATUS_SUCCESS)
{
Irp->IoStatus.Status = ntStatus;
return ntStatus;
}

CompleteContext->Irp = Irp;
CompleteContext->IrpSp = *IrpSp;
CompleteContext->DeviceObject = HookerDevExt->HookerDevObj;

ExInitializeWorkItem(&CompleteContext->WorkQueueItem,
TDI_DelayedConnect,
CompleteContext);

ExQueueWorkItem(&CompleteContext->WorkQueueItem, DelayedWorkQueue);

return STATUS_MORE_PROCESSING_REQUIRED;
}

TDI_DelayedConnect(PIRP_COMPLETE_CONTEXT Context)
{
Irp = Context->Irp;
HookerDevExt = Context->DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation ( Irp );

ExFreePool (Context);

IoCompleteRequest(Irp, IO_NO_INCREMENT);
}

WO> “xxxxx@yandex” wrote:

> ntStatus = IoCallDriver (HookerDevExt->LowerDeviceObject, Irp);
> return ntStatus;

WO> Just don’t do it this way, because it leads to the problem you’re
WO> experiencing. Upstream code may interpret a non-pending status to mean
WO> that the IRP was completed synchronously and to perform cleanup
WO> processing. When IoCompleteRequest eventually sees the pending flag, it
WO> will schedule an APC that will *also* do the cleanup processing, and
WO> that leads to a multiple-completion bugcheck.

Foxgen

In TDI_ConnectComplete(), you must not do IoMarkIrpPending(Irp) if the
routine is going to return STATUS_MORE_PROCESSING_REQUIRED. See Walter
Oney, “Programming the Microsoft Windows Driver Model,” 2d edition, page
253.

To make the point a little more general, do

if (TRUE==pIrp->PendingReturned) IoMarkIrpPending(pIrp);

if and only if (IFF) the completion routine is going to return something
other than STATUS_MORE_PROCESSING_REQUIRED.


If replying by e-mail, please remove “nospam.” from the address.

James Antognini