Question about completion routine and IoMarkIrpPending

I had a problem with an I/O completion routine a few days ago and for
debugging purposes inserted the completion routine from a Microsoft example
(KB326315). I found my code then failed under DriverVerifer with a pool
corruption error.

The article KB326315 claims to be the correct way to handle things, yet when
I look at everything I believe Scenario 7 and 8 in the document are wrong.

Both these pieces of code create an IRP and call IoCallDriver() on the IRP.
Their completion routines both include:

if (Irp->PendingReturned) {

IoMarkIrpPending( Irp );
}

If you look at IoMarkIrpPending, it’s a macro:

#define IoMarkIrpPending( Irp ) ( IoGetCurrentIrpStackLocation(
(Irp) )->Control |= SL_PENDING_RETURNED )

So here’s where the problem occurs, if you created the IRP and sent it,
isn’t IoGetCurrentIrpStackLocation going to be pointing at the stack
location PAST the end of the IRP, as there is no IRP stack frame for the
caller? As a result, the above code corrupts memory by setting a bit in
memory a little above your IRP. It seems like this is what I saw happen, as
DriverVerifier allocated my IRP with tail corruption checking.

Is my understanding of where the current IRP stack frame is on a completion
routine wrong? Or does this actually corrupt memory? I found a number of
previous NTDEV comments that say IoMarkIrpPending should not be called for
top level IRP’s, and that was my belief until KB326315 made me question it.

I didn’t offhand see any comments about NOT calling IoMarkIrpPending if your
the original IRP caller in the NT Insider article
http://www.osronline.com/article.cfm?id=21

It seems like CUV perhaps detects this issue, although putting an ASSERT in
the IoMarkIrpPending macro would be pretty easy.

  • Jan

Hi Jan,

If you allocate the IRP in your driver, you do not have a stack location
and you cannot set the IRP as pending.

It sounds like the discussions you read were not considering the case
when your driver is the one creating the IRP in question. I’ll track
down the guilty party at OSR and have them soundly flogged (and if it is
me, I’ll have to find someone else to beat me…)

Regards,

Tony

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Jan Bottorff
Sent: Thursday, January 20, 2005 9:29 PM
To: ntdev redirect
Subject: [ntdev] Question about completion routine and IoMarkIrpPending

I had a problem with an I/O completion routine a few days ago and for
debugging purposes inserted the completion routine from a Microsoft
example
(KB326315). I found my code then failed under DriverVerifer with a pool
corruption error.

The article KB326315 claims to be the correct way to handle things, yet
when
I look at everything I believe Scenario 7 and 8 in the document are
wrong.

Both these pieces of code create an IRP and call IoCallDriver() on the
IRP.
Their completion routines both include:

if (Irp->PendingReturned) {

IoMarkIrpPending( Irp );
}

If you look at IoMarkIrpPending, it’s a macro:

#define IoMarkIrpPending( Irp ) ( IoGetCurrentIrpStackLocation(
(Irp) )->Control |= SL_PENDING_RETURNED )

So here’s where the problem occurs, if you created the IRP and sent it,
isn’t IoGetCurrentIrpStackLocation going to be pointing at the stack
location PAST the end of the IRP, as there is no IRP stack frame for the

caller? As a result, the above code corrupts memory by setting a bit in
memory a little above your IRP. It seems like this is what I saw happen,
as
DriverVerifier allocated my IRP with tail corruption checking.

Is my understanding of where the current IRP stack frame is on a
completion
routine wrong? Or does this actually corrupt memory? I found a number of

previous NTDEV comments that say IoMarkIrpPending should not be called
for
top level IRP’s, and that was my belief until KB326315 made me question
it.

I didn’t offhand see any comments about NOT calling IoMarkIrpPending if
your
the original IRP caller in the NT Insider article
http://www.osronline.com/article.cfm?id=21

It seems like CUV perhaps detects this issue, although putting an ASSERT
in
the IoMarkIrpPending macro would be pretty easy.

  • Jan

Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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

I will fwd this to the owner of that KB article.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Jan Bottorff
Sent: Thursday, January 20, 2005 6:29 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Question about completion routine and IoMarkIrpPending

I had a problem with an I/O completion routine a few days ago and for
debugging purposes inserted the completion routine from a Microsoft
example
(KB326315). I found my code then failed under DriverVerifer with a pool
corruption error.

The article KB326315 claims to be the correct way to handle things, yet
when
I look at everything I believe Scenario 7 and 8 in the document are
wrong.

Both these pieces of code create an IRP and call IoCallDriver() on the
IRP.
Their completion routines both include:

if (Irp->PendingReturned) {

IoMarkIrpPending( Irp );
}

If you look at IoMarkIrpPending, it’s a macro:

#define IoMarkIrpPending( Irp ) ( IoGetCurrentIrpStackLocation(
(Irp) )->Control |= SL_PENDING_RETURNED )

So here’s where the problem occurs, if you created the IRP and sent it,
isn’t IoGetCurrentIrpStackLocation going to be pointing at the stack
location PAST the end of the IRP, as there is no IRP stack frame for the

caller? As a result, the above code corrupts memory by setting a bit in
memory a little above your IRP. It seems like this is what I saw happen,
as
DriverVerifier allocated my IRP with tail corruption checking.

Is my understanding of where the current IRP stack frame is on a
completion
routine wrong? Or does this actually corrupt memory? I found a number of

previous NTDEV comments that say IoMarkIrpPending should not be called
for
top level IRP’s, and that was my belief until KB326315 made me question
it.

I didn’t offhand see any comments about NOT calling IoMarkIrpPending if
your
the original IRP caller in the NT Insider article
http://www.osronline.com/article.cfm?id=21

It seems like CUV perhaps detects this issue, although putting an ASSERT
in
the IoMarkIrpPending macro would be pretty easy.

  • Jan

Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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