STATUS_PENDING down Create path

This post contains two questions, but first, here is the background info.
While developing a file system filter, I decided to run some interop tests
with major third party vendors. I installed one third party
application/filter and began to receive numerous stop code 0x44’s (all of
which have been down the create path). I had not received this error
while testing against similar third party filters, so I began
disassembling their dispatch and completion routines for the create path.
From this, I have been able to determine that their completion routine is
very simple, but appears to have a mistake in it. I’ve converted the
assembly into C to make it easier to follow:

NTSTATUS
IoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// My filter, which is layered below theirs, will return
// STATUS_PENDING down create dispatch, so this if block
// will execute.
//
if(Irp->PendingReturned)
{
// This is what leads to my first question. Is it
// “wrong” to mark the irp pending and yet still
// return STATUS_MORE_PROCESSING_REQUIRED? This OSR
// article appears to imply it might:
// http://www.osronline.com/article.cfm?id=21
//
IoMarkIrpPending(Irp);
}

// Context is an event used to resynch completion
// back to dispatch
//
KeSetEvent(Context);

return STATUS_MORE_PROCESSING_REQUIRED
}

Once the completion routine was executed, I had a break point set in the
dispatch routine at the point where execution would continue when the
event that was passed in as Context was set. Of course, it is common to
resynch completion back to dispatch in this manner, but at the end, their
dispatch returns STATUS_PENDING. It would seem that at this point, the
filter would want to return the status contained in the irp (which was
STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
Is this a valid thing to do (my opinion is that it doesn’t look right)?

With this information in mind, would it be reasonable to conclude that
this is the actual bug (in their filter) which is causing my stop code
0x44’s?

Thank you,
M.G.

The code in question looks good.

Jamey Kirby, Windows DDK MVP
StorageCraft Inc.
xxxxx@storagecraft.com
http://www.storagecraft.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of M.G.
Sent: Monday, August 18, 2003 11:08 AM
To: File Systems Developers
Subject: [ntfsd] STATUS_PENDING down Create path

This post contains two questions, but first, here is the background info.
While developing a file system filter, I decided to run some interop tests
with major third party vendors. I installed one third party
application/filter and began to receive numerous stop code 0x44’s (all of
which have been down the create path). I had not received this error
while testing against similar third party filters, so I began
disassembling their dispatch and completion routines for the create path.
From this, I have been able to determine that their completion routine is
very simple, but appears to have a mistake in it. I’ve converted the
assembly into C to make it easier to follow:

NTSTATUS
IoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// My filter, which is layered below theirs, will return
// STATUS_PENDING down create dispatch, so this if block
// will execute.
//
if(Irp->PendingReturned)
{
// This is what leads to my first question. Is it
// “wrong” to mark the irp pending and yet still
// return STATUS_MORE_PROCESSING_REQUIRED? This OSR
// article appears to imply it might:
// http://www.osronline.com/article.cfm?id=21
//
IoMarkIrpPending(Irp);
}

// Context is an event used to resynch completion
// back to dispatch
//
KeSetEvent(Context);

return STATUS_MORE_PROCESSING_REQUIRED
}

Once the completion routine was executed, I had a break point set in the
dispatch routine at the point where execution would continue when the
event that was passed in as Context was set. Of course, it is common to
resynch completion back to dispatch in this manner, but at the end, their
dispatch returns STATUS_PENDING. It would seem that at this point, the
filter would want to return the status contained in the irp (which was
STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
Is this a valid thing to do (my opinion is that it doesn’t look right)?

With this information in mind, would it be reasonable to conclude that
this is the actual bug (in their filter) which is causing my stop code
0x44’s?

Thank you,
M.G.


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

If this isn’t an FAQ, it should be (which means it is on my “to do” list!)

STATUS_PENDING is a valid and legitimate return for ANY operation. Any
driver that sends IRPs to other drivers MUST be able to handle
STATUS_PENDING as a return.

The bug isn’t in THIS driver, but in the driver above, which must be
returning something OTHER THAN STATUS_PENDING but marking the IRP as
pending. This will cause the I/O completion to occur in the wrong order
(two distinct steps here) and lead to the bug check in question.

Interestingly enough, I had to answer a question from one of OUR clients
about this very issue. A driver that has this problem (not handling
STATUS_PENDING properly) will not pass driver verifier with full I/O
verification enabled.

So, my question back is: “does your driver run successfully with full driver
verifier running? (usually we turn on everything EXCEPT low resource
simulation)”

Regards,

Tony

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

-----Original Message-----
From: M.G. [mailto:xxxxx@hotmail.com]
Sent: Monday, August 18, 2003 2:08 PM
To: File Systems Developers
Subject: [ntfsd] STATUS_PENDING down Create path

This post contains two questions, but first, here is the background info.
While developing a file system filter, I decided to run some interop tests
with major third party vendors. I installed one third party
application/filter and began to receive numerous stop code 0x44’s (all of
which have been down the create path). I had not received this error
while testing against similar third party filters, so I began
disassembling their dispatch and completion routines for the create path.
From this, I have been able to determine that their completion routine is
very simple, but appears to have a mistake in it. I’ve converted the
assembly into C to make it easier to follow:

NTSTATUS
IoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// My filter, which is layered below theirs, will return
// STATUS_PENDING down create dispatch, so this if block
// will execute.
//
if(Irp->PendingReturned)
{
// This is what leads to my first question. Is it
// “wrong” to mark the irp pending and yet still
// return STATUS_MORE_PROCESSING_REQUIRED? This OSR
// article appears to imply it might:
// http://www.osronline.com/article.cfm?id=21
//
IoMarkIrpPending(Irp);
}

// Context is an event used to resynch completion
// back to dispatch
//
KeSetEvent(Context);

return STATUS_MORE_PROCESSING_REQUIRED
}

Once the completion routine was executed, I had a break point set in the
dispatch routine at the point where execution would continue when the
event that was passed in as Context was set. Of course, it is common to
resynch completion back to dispatch in this manner, but at the end, their
dispatch returns STATUS_PENDING. It would seem that at this point, the
filter would want to return the status contained in the irp (which was
STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
Is this a valid thing to do (my opinion is that it doesn’t look right)?

With this information in mind, would it be reasonable to conclude that
this is the actual bug (in their filter) which is causing my stop code
0x44’s?

Thank you,
M.G.


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

Thank you for your quick response Jamey.

If I may, I would like to ask for some clarification on a few points that
are troubling me. The OSR article I mentioned in my original post has a
few rules that seem to indicate the code might be wrong. For instance
(from the article):

“Rule 1: If you complete the IRP passed to your Dispatch Routine in your
Dispatch Routine, you must (a) Fill the IRP’s completion status and
information into the IRP’s I/O status block, (b) Call IoCompleteRequest(),
and (c) return the status you used to complete the IRP (the status value
you filled into the .Status member of the I/O status block in the IRP) as
the return value from your Dispatch Routine.”

I see in my original post I did not emphasize the fact that the filter
layered above us was actually completing the IRP from their dispatch
routine. Please forgive this oversight. In the filter layered above us,
after their completion routine resynchs back to the dispatch routine, the
IRP is being completed with STATUS_SUCCESS inside of Irp->IoStatus.Status,
but the dispatch routine is returning STATUS_PENDING. That seems to be a
clear violation of the rule. Continuing from the article:

“Rule 2: If you return from your Dispatch Routine without completing the
IRP passed to you, you must (a) Mark the IRP pending, before the IRP is
completed to your caller, by calling IoMarkIrpPending(), and (b) return
STATUS_PENDING from your Dispatch Routine.”

The rule seems to indicate that if you don’t complete the IRP, you should
mark it pending. In the completion routine, the IRP is marked pending.
However, when the completion routine resynchs back to dispatch, the IRP is
completed. If I read the rule correctly, since the IRP was completed in
dispatch, there was no need to mark it pending. Which leads me to wonder
if this causes any timing issues or confusion in the IoManager.

In fairness, I believe I should include this third rule from the article.
I believe this may have been the original intention of the filter layered
above us:

“Rule 3: If you return the status from the driver below yours as the
status from your dispatch routine, the IRP’s pending status, as indicated
by Irp->PendingReturned, must be propagated with a completion routine.”

However, since they are resynching back to dispatch and completing the
IRP, this rule does not seem to apply (by way of Rule 1… or perhaps I’m
wrong about that).

If you can help clear up these details for me, I would appreciate it. If,
however, this indicates an error in the filter, I would ask if such errors
could potentially lead to a stop code 0x44.

Thank you,
M.G.

-----Original Message-----
From: Jamey Kirby [mailto:xxxxx@storagecraft.com]
Sent: Monday, August 18, 2003 1:47 PM
To: File Systems Developers
Subject: [ntfsd] RE: STATUS_PENDING down Create path

The code in question looks good.

Jamey Kirby, Windows DDK MVP
StorageCraft Inc.
xxxxx@storagecraft.com
http://www.storagecraft.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of M.G.
Sent: Monday, August 18, 2003 11:08 AM
To: File Systems Developers
Subject: [ntfsd] STATUS_PENDING down Create path

This post contains two questions, but first, here is the background info.
While developing a file system filter, I decided to run some interop tests
with major third party vendors. I installed one third party
application/filter and began to receive numerous stop code 0x44’s (all of
which have been down the create path). I had not received this error
while testing against similar third party filters, so I began
disassembling their dispatch and completion routines for the create path.
From this, I have been able to determine that their completion routine is
very simple, but appears to have a mistake in it. I’ve converted the
assembly into C to make it easier to follow:

NTSTATUS
IoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// My filter, which is layered below theirs, will return
// STATUS_PENDING down create dispatch, so this if block
// will execute.
//
if(Irp->PendingReturned)
{
// This is what leads to my first question. Is it
// “wrong” to mark the irp pending and yet still
// return STATUS_MORE_PROCESSING_REQUIRED? This OSR
// article appears to imply it might:
// http://www.osronline.com/article.cfm?id=21
//
IoMarkIrpPending(Irp);
}

// Context is an event used to resynch completion
// back to dispatch
//
KeSetEvent(Context);

return STATUS_MORE_PROCESSING_REQUIRED
}

Once the completion routine was executed, I had a break point set in the
dispatch routine at the point where execution would continue when the
event that was passed in as Context was set. Of course, it is common to
resynch completion back to dispatch in this manner, but at the end, their
dispatch returns STATUS_PENDING. It would seem that at this point, the
filter would want to return the status contained in the irp (which was
STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
Is this a valid thing to do (my opinion is that it doesn’t look right)?

With this information in mind, would it be reasonable to conclude that
this is the actual bug (in their filter) which is causing my stop code
0x44’s?

Thank you,
M.G.


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


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

Thank you for your reply as well Tony,

Absolutely. Verifier is turned on through IoStress with the preferred
settings for stress and runs by itself or with other third party venders.
The original post came about when we started seeing 0x44’s during stress
with a particular vendor’s product and then began receiving 0x44’s from
the field from customers also running a particular vendor’s product.

Thank you,
M.G.

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Tuesday, August 19, 2003 9:10 AM
To: File Systems Developers
Subject: [ntfsd] RE: STATUS_PENDING down Create path

If this isn’t an FAQ, it should be (which means it is on my “to do” list!)

STATUS_PENDING is a valid and legitimate return for ANY operation. Any
driver that sends IRPs to other drivers MUST be able to handle
STATUS_PENDING as a return.

The bug isn’t in THIS driver, but in the driver above, which must be
returning something OTHER THAN STATUS_PENDING but marking the IRP as
pending. This will cause the I/O completion to occur in the wrong order
(two distinct steps here) and lead to the bug check in question.

Interestingly enough, I had to answer a question from one of OUR clients
about this very issue. A driver that has this problem (not handling
STATUS_PENDING properly) will not pass driver verifier with full I/O
verification enabled.

So, my question back is: “does your driver run successfully with full
driver
verifier running? (usually we turn on everything EXCEPT low resource
simulation)”

Regards,

Tony

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

-----Original Message-----
From: M.G. [mailto:xxxxx@hotmail.com]
Sent: Monday, August 18, 2003 2:08 PM
To: File Systems Developers
Subject: [ntfsd] STATUS_PENDING down Create path

This post contains two questions, but first, here is the background info.
While developing a file system filter, I decided to run some interop tests
with major third party vendors. I installed one third party
application/filter and began to receive numerous stop code 0x44’s (all of
which have been down the create path). I had not received this error
while testing against similar third party filters, so I began
disassembling their dispatch and completion routines for the create path.
From this, I have been able to determine that their completion routine is
very simple, but appears to have a mistake in it. I’ve converted the
assembly into C to make it easier to follow:

NTSTATUS
IoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// My filter, which is layered below theirs, will return
// STATUS_PENDING down create dispatch, so this if block
// will execute.
//
if(Irp->PendingReturned)
{
// This is what leads to my first question. Is it
// “wrong” to mark the irp pending and yet still
// return STATUS_MORE_PROCESSING_REQUIRED? This OSR
// article appears to imply it might:
// http://www.osronline.com/article.cfm?id=21
//
IoMarkIrpPending(Irp);
}

// Context is an event used to resynch completion
// back to dispatch
//
KeSetEvent(Context);

return STATUS_MORE_PROCESSING_REQUIRED
}

Once the completion routine was executed, I had a break point set in the
dispatch routine at the point where execution would continue when the
event that was passed in as Context was set. Of course, it is common to
resynch completion back to dispatch in this manner, but at the end, their
dispatch returns STATUS_PENDING. It would seem that at this point, the
filter would want to return the status contained in the irp (which was
STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
Is this a valid thing to do (my opinion is that it doesn’t look right)?

With this information in mind, would it be reasonable to conclude that
this is the actual bug (in their filter) which is causing my stop code
0x44’s?

Thank you,
M.G.


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


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

One thing that does appear to be wrong is that the call to IoMarkIrpPending
should not be made. As documented in the IFS Kit:

Checking the PendingReturned Flag
a… Unless the completion routine signals an event, it must check the
Irp->PendingReturned flag. If this flag is set, the completion routine must
call IoMarkIrpPending to mark the IRP as pending.
b… If a completion routine signals an event, it should not call
IoMarkIrpPending.
I recall at a prior Plugfest asking about this and was told by a member of
the filter group that you definitely do not propagate the pending bit when
you synchronize back to dispatch. So, if the completion routine as shown
below is in an actual driver, it can cause some real problems.

Hope this helps.

Jerry

“M.G.” wrote in message news:xxxxx@ntfsd…
>
> This post contains two questions, but first, here is the background info.
> While developing a file system filter, I decided to run some interop tests
> with major third party vendors. I installed one third party
> application/filter and began to receive numerous stop code 0x44’s (all of
> which have been down the create path). I had not received this error
> while testing against similar third party filters, so I began
> disassembling their dispatch and completion routines for the create path.
> From this, I have been able to determine that their completion routine is
> very simple, but appears to have a mistake in it. I’ve converted the
> assembly into C to make it easier to follow:
>
> NTSTATUS
> IoCompletion(
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp,
> IN PVOID Context
> )
> {
> // My filter, which is layered below theirs, will return
> // STATUS_PENDING down create dispatch, so this if block
> // will execute.
> //
> if(Irp->PendingReturned)
> {
> // This is what leads to my first question. Is it
> // “wrong” to mark the irp pending and yet still
> // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> // article appears to imply it might:
> // http://www.osronline.com/article.cfm?id=21
> //
> IoMarkIrpPending(Irp);
> }
>
> // Context is an event used to resynch completion
> // back to dispatch
> //
> KeSetEvent(Context);
>
> return STATUS_MORE_PROCESSING_REQUIRED
> }
>
> Once the completion routine was executed, I had a break point set in the
> dispatch routine at the point where execution would continue when the
> event that was passed in as Context was set. Of course, it is common to
> resynch completion back to dispatch in this manner, but at the end, their
> dispatch returns STATUS_PENDING. It would seem that at this point, the
> filter would want to return the status contained in the irp (which was
> STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
> Is this a valid thing to do (my opinion is that it doesn’t look right)?
>
> With this information in mind, would it be reasonable to conclude that
> this is the actual bug (in their filter) which is causing my stop code
> 0x44’s?
>
> Thank you,
> M.G.
>
>

Actually, upon further thought (the wonders of getting that first cup of
coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
unconditional in this case BECAUSE they are returning STATUS_PENDING in
their completion routine. If I were coding it, I would put it
(IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
is unconditionally returning STATUS_PENDING, they have to call
IoMarkIrpPending.

This is one of the more complicated pieces to understand for filters (in
particular) with respect to the I/O Manager. Get it wrong and the system
blows up in these mysterious ways.

Regards,

Tony

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

-----Original Message-----
From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
Sent: Tuesday, August 19, 2003 10:58 AM
To: File Systems Developers
Subject: [ntfsd] Re: STATUS_PENDING down Create path

One thing that does appear to be wrong is that the call to IoMarkIrpPending
should not be made. As documented in the IFS Kit:

Checking the PendingReturned Flag
a… Unless the completion routine signals an event, it must check the
Irp->PendingReturned flag. If this flag is set, the completion routine must
call IoMarkIrpPending to mark the IRP as pending.
b… If a completion routine signals an event, it should not call
IoMarkIrpPending.
I recall at a prior Plugfest asking about this and was told by a member of
the filter group that you definitely do not propagate the pending bit when
you synchronize back to dispatch. So, if the completion routine as shown
below is in an actual driver, it can cause some real problems.

Hope this helps.

Jerry

“M.G.” wrote in message news:xxxxx@ntfsd…
>
> This post contains two questions, but first, here is the background info.
> While developing a file system filter, I decided to run some interop tests
> with major third party vendors. I installed one third party
> application/filter and began to receive numerous stop code 0x44’s (all of
> which have been down the create path). I had not received this error
> while testing against similar third party filters, so I began
> disassembling their dispatch and completion routines for the create path.
> From this, I have been able to determine that their completion routine is
> very simple, but appears to have a mistake in it. I’ve converted the
> assembly into C to make it easier to follow:
>
> NTSTATUS
> IoCompletion(
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp,
> IN PVOID Context
> )
> {
> // My filter, which is layered below theirs, will return
> // STATUS_PENDING down create dispatch, so this if block
> // will execute.
> //
> if(Irp->PendingReturned)
> {
> // This is what leads to my first question. Is it
> // “wrong” to mark the irp pending and yet still
> // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> // article appears to imply it might:
> // http://www.osronline.com/article.cfm?id=21
> //
> IoMarkIrpPending(Irp);
> }
>
> // Context is an event used to resynch completion
> // back to dispatch
> //
> KeSetEvent(Context);
>
> return STATUS_MORE_PROCESSING_REQUIRED
> }
>
> Once the completion routine was executed, I had a break point set in the
> dispatch routine at the point where execution would continue when the
> event that was passed in as Context was set. Of course, it is common to
> resynch completion back to dispatch in this manner, but at the end, their
> dispatch returns STATUS_PENDING. It would seem that at this point, the
> filter would want to return the status contained in the irp (which was
> STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
> Is this a valid thing to do (my opinion is that it doesn’t look right)?
>
> With this information in mind, would it be reasonable to conclude that
> this is the actual bug (in their filter) which is causing my stop code
> 0x44’s?
>
> Thank you,
> M.G.
>
>


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

Yes, thank you Jerry.

I would say that the most interesting point of Jerry’s post would be:

b… If a completion routine signals an event, it should not call
IoMarkIrpPending.

To me this indicates that the driver layered above should have:
A) Not have called IoMarkIrpPending
B) In the dispatch routine, he should have returned the status from the
Irp (in this case STATUS_SUCCESS) and not STATUS_PENDING.

Thank you both,
M.G.

Actually, upon further thought (the wonders of getting that first cup of
coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
unconditional in this case BECAUSE they are returning STATUS_PENDING in
their completion routine. If I were coding it, I would put it
(IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
is unconditionally returning STATUS_PENDING, they have to call
IoMarkIrpPending.

This is one of the more complicated pieces to understand for filters (in
particular) with respect to the I/O Manager. Get it wrong and the system
blows up in these mysterious ways.

Regards,

Tony

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

-----Original Message-----
From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
Sent: Tuesday, August 19, 2003 10:58 AM
To: File Systems Developers
Subject: [ntfsd] Re: STATUS_PENDING down Create path

One thing that does appear to be wrong is that the call to
IoMarkIrpPending
should not be made. As documented in the IFS Kit:

Checking the PendingReturned Flag
a… Unless the completion routine signals an event, it must check the
Irp->PendingReturned flag. If this flag is set, the completion routine
must
call IoMarkIrpPending to mark the IRP as pending.
b… If a completion routine signals an event, it should not call
IoMarkIrpPending.
I recall at a prior Plugfest asking about this and was told by a member of
the filter group that you definitely do not propagate the pending bit when
you synchronize back to dispatch. So, if the completion routine as shown
below is in an actual driver, it can cause some real problems.

Hope this helps.

Jerry

“M.G.” wrote in message news:xxxxx@ntfsd…
>
> This post contains two questions, but first, here is the background info.
> While developing a file system filter, I decided to run some interop tests
> with major third party vendors. I installed one third party
> application/filter and began to receive numerous stop code 0x44’s (all of
> which have been down the create path). I had not received this error
> while testing against similar third party filters, so I began
> disassembling their dispatch and completion routines for the create path.
> From this, I have been able to determine that their completion routine is
> very simple, but appears to have a mistake in it. I’ve converted the
> assembly into C to make it easier to follow:
>
> NTSTATUS
> IoCompletion(
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp,
> IN PVOID Context
> )
> {
> // My filter, which is layered below theirs, will return
> // STATUS_PENDING down create dispatch, so this if block
> // will execute.
> //
> if(Irp->PendingReturned)
> {
> // This is what leads to my first question. Is it
> // “wrong” to mark the irp pending and yet still
> // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> // article appears to imply it might:
> // http://www.osronline.com/article.cfm?id=21
> //
> IoMarkIrpPending(Irp);
> }
>
> // Context is an event used to resynch completion
> // back to dispatch
> //
> KeSetEvent(Context);
>
> return STATUS_MORE_PROCESSING_REQUIRED
> }
>
> Once the completion routine was executed, I had a break point set in the
> dispatch routine at the point where execution would continue when the
> event that was passed in as Context was set. Of course, it is common to
> resynch completion back to dispatch in this manner, but at the end, their
> dispatch returns STATUS_PENDING. It would seem that at this point, the
> filter would want to return the status contained in the irp (which was
> STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
> Is this a valid thing to do (my opinion is that it doesn’t look right)?
>
> With this information in mind, would it be reasonable to conclude that
> this is the actual bug (in their filter) which is causing my stop code
> 0x44’s?
>
> Thank you,
> M.G.
>
>


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


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

Thanks Tony.

M.G.,

There’s a very good sample of what should be done. Take a look at Filespy.
If you look at SpyPassThrough, it is the dispatch routine and handles the
option of synchronizing with completion. After the call to the lower driver,
it makes the standard check for STATUS_PENDING and waits if necessary. It
then gets the status from the IRP, calls IoCompleteRequest, and returns the
IRP status.

The completion routine, SpyPassThroughCompletion, makes the check for
synching back to dispatch and, if it has to synch, just sets the event and
returns STATUS_MORE_PROCESSING_REQUIRED. If it didn’t have to synch, THEN
it checks the pending bit, marks it if necessary, and returns
STATUS_SUCCESS.

Back to Tony,

Sorry if this is redundant but I was a bit confused by your usage of
STATUS_PENDING as a return value for the completion routine. Did you mean
STATUS_MORE_PROCESSING_REQUIRED?

Note that Filespy does not call IoMarkIrpPending anywhere in the dispatch
routine discussed here. So I’m curious when you would call it in the
dispatch routine.

Jerry

“Tony Mason” wrote in message news:xxxxx@ntfsd…
>
> Actually, upon further thought (the wonders of getting that first cup of
> coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
> unconditional in this case BECAUSE they are returning STATUS_PENDING in
> their completion routine. If I were coding it, I would put it
> (IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
> is unconditionally returning STATUS_PENDING, they have to call
> IoMarkIrpPending.
>
> This is one of the more complicated pieces to understand for filters (in
> particular) with respect to the I/O Manager. Get it wrong and the system
> blows up in these mysterious ways.
>
> Regards,
>
> Tony
>
> Tony Mason
> Consulting Partner
> OSR Open Systems Resources, Inc.
> http://www.osr.com
>
>
> -----Original Message-----
> From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
> Sent: Tuesday, August 19, 2003 10:58 AM
> To: File Systems Developers
> Subject: [ntfsd] Re: STATUS_PENDING down Create path
>
> One thing that does appear to be wrong is that the call to
IoMarkIrpPending
> should not be made. As documented in the IFS Kit:
>
> Checking the PendingReturned Flag
> a… Unless the completion routine signals an event, it must check the
> Irp->PendingReturned flag. If this flag is set, the completion routine
must
> call IoMarkIrpPending to mark the IRP as pending.
> b… If a completion routine signals an event, it should not call
> IoMarkIrpPending.
> I recall at a prior Plugfest asking about this and was told by a member of
> the filter group that you definitely do not propagate the pending bit when
> you synchronize back to dispatch. So, if the completion routine as shown
> below is in an actual driver, it can cause some real problems.
>
> Hope this helps.
>
> Jerry
>
>
> “M.G.” wrote in message news:xxxxx@ntfsd…
> >
> > This post contains two questions, but first, here is the background
info.
> > While developing a file system filter, I decided to run some interop
tests
> > with major third party vendors. I installed one third party
> > application/filter and began to receive numerous stop code 0x44’s (all
of
> > which have been down the create path). I had not received this error
> > while testing against similar third party filters, so I began
> > disassembling their dispatch and completion routines for the create
path.
> > From this, I have been able to determine that their completion routine
is
> > very simple, but appears to have a mistake in it. I’ve converted the
> > assembly into C to make it easier to follow:
> >
> > NTSTATUS
> > IoCompletion(
> > IN PDEVICE_OBJECT DeviceObject,
> > IN PIRP Irp,
> > IN PVOID Context
> > )
> > {
> > // My filter, which is layered below theirs, will return
> > // STATUS_PENDING down create dispatch, so this if block
> > // will execute.
> > //
> > if(Irp->PendingReturned)
> > {
> > // This is what leads to my first question. Is it
> > // “wrong” to mark the irp pending and yet still
> > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > // article appears to imply it might:
> > // http://www.osronline.com/article.cfm?id=21
> > //
> > IoMarkIrpPending(Irp);
> > }
> >
> > // Context is an event used to resynch completion
> > // back to dispatch
> > //
> > KeSetEvent(Context);
> >
> > return STATUS_MORE_PROCESSING_REQUIRED
> > }
> >
> > Once the completion routine was executed, I had a break point set in the
> > dispatch routine at the point where execution would continue when the
> > event that was passed in as Context was set. Of course, it is common to
> > resynch completion back to dispatch in this manner, but at the end,
their
> > dispatch returns STATUS_PENDING. It would seem that at this point, the
> > filter would want to return the status contained in the irp (which was
> > STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
> > Is this a valid thing to do (my opinion is that it doesn’t look right)?
> >
> > With this information in mind, would it be reasonable to conclude that
> > this is the actual bug (in their filter) which is causing my stop code
> > 0x44’s?
> >
> > Thank you,
> > M.G.
> >
> >
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@osr.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>

Sorry. STATUS_PENDING is from Dispatch. STATUS_MORE_PROCESSING is from
completion. In fact the ONLY return code that is important in completion is
STATUS_MORE_PROCESSING_REQUIRED. Any other return code will cause completion
processing to continue.

Time for more coffee…

Regards,

Tony

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

-----Original Message-----
From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
Sent: Tuesday, August 19, 2003 11:40 AM
To: File Systems Developers
Subject: [ntfsd] Re: STATUS_PENDING down Create path

Thanks Tony.

M.G.,

There’s a very good sample of what should be done. Take a look at Filespy.
If you look at SpyPassThrough, it is the dispatch routine and handles the
option of synchronizing with completion. After the call to the lower driver,
it makes the standard check for STATUS_PENDING and waits if necessary. It
then gets the status from the IRP, calls IoCompleteRequest, and returns the
IRP status.

The completion routine, SpyPassThroughCompletion, makes the check for
synching back to dispatch and, if it has to synch, just sets the event and
returns STATUS_MORE_PROCESSING_REQUIRED. If it didn’t have to synch, THEN
it checks the pending bit, marks it if necessary, and returns
STATUS_SUCCESS.

Back to Tony,

Sorry if this is redundant but I was a bit confused by your usage of
STATUS_PENDING as a return value for the completion routine. Did you mean
STATUS_MORE_PROCESSING_REQUIRED?

Note that Filespy does not call IoMarkIrpPending anywhere in the dispatch
routine discussed here. So I’m curious when you would call it in the
dispatch routine.

Jerry

“Tony Mason” wrote in message news:xxxxx@ntfsd…
>
> Actually, upon further thought (the wonders of getting that first cup of
> coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
> unconditional in this case BECAUSE they are returning STATUS_PENDING in
> their completion routine. If I were coding it, I would put it
> (IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
> is unconditionally returning STATUS_PENDING, they have to call
> IoMarkIrpPending.
>
> This is one of the more complicated pieces to understand for filters (in
> particular) with respect to the I/O Manager. Get it wrong and the system
> blows up in these mysterious ways.
>
> Regards,
>
> Tony
>
> Tony Mason
> Consulting Partner
> OSR Open Systems Resources, Inc.
> http://www.osr.com
>
>
> -----Original Message-----
> From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
> Sent: Tuesday, August 19, 2003 10:58 AM
> To: File Systems Developers
> Subject: [ntfsd] Re: STATUS_PENDING down Create path
>
> One thing that does appear to be wrong is that the call to
IoMarkIrpPending
> should not be made. As documented in the IFS Kit:
>
> Checking the PendingReturned Flag
> a… Unless the completion routine signals an event, it must check the
> Irp->PendingReturned flag. If this flag is set, the completion routine
must
> call IoMarkIrpPending to mark the IRP as pending.
> b… If a completion routine signals an event, it should not call
> IoMarkIrpPending.
> I recall at a prior Plugfest asking about this and was told by a member of
> the filter group that you definitely do not propagate the pending bit when
> you synchronize back to dispatch. So, if the completion routine as shown
> below is in an actual driver, it can cause some real problems.
>
> Hope this helps.
>
> Jerry
>
>
> “M.G.” wrote in message news:xxxxx@ntfsd…
> >
> > This post contains two questions, but first, here is the background
info.
> > While developing a file system filter, I decided to run some interop
tests
> > with major third party vendors. I installed one third party
> > application/filter and began to receive numerous stop code 0x44’s (all
of
> > which have been down the create path). I had not received this error
> > while testing against similar third party filters, so I began
> > disassembling their dispatch and completion routines for the create
path.
> > From this, I have been able to determine that their completion routine
is
> > very simple, but appears to have a mistake in it. I’ve converted the
> > assembly into C to make it easier to follow:
> >
> > NTSTATUS
> > IoCompletion(
> > IN PDEVICE_OBJECT DeviceObject,
> > IN PIRP Irp,
> > IN PVOID Context
> > )
> > {
> > // My filter, which is layered below theirs, will return
> > // STATUS_PENDING down create dispatch, so this if block
> > // will execute.
> > //
> > if(Irp->PendingReturned)
> > {
> > // This is what leads to my first question. Is it
> > // “wrong” to mark the irp pending and yet still
> > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > // article appears to imply it might:
> > // http://www.osronline.com/article.cfm?id=21
> > //
> > IoMarkIrpPending(Irp);
> > }
> >
> > // Context is an event used to resynch completion
> > // back to dispatch
> > //
> > KeSetEvent(Context);
> >
> > return STATUS_MORE_PROCESSING_REQUIRED
> > }
> >
> > Once the completion routine was executed, I had a break point set in the
> > dispatch routine at the point where execution would continue when the
> > event that was passed in as Context was set. Of course, it is common to
> > resynch completion back to dispatch in this manner, but at the end,
their
> > dispatch returns STATUS_PENDING. It would seem that at this point, the
> > filter would want to return the status contained in the irp (which was
> > STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
> > Is this a valid thing to do (my opinion is that it doesn’t look right)?
> >
> > With this information in mind, would it be reasonable to conclude that
> > this is the actual bug (in their filter) which is causing my stop code
> > 0x44’s?
> >
> > Thank you,
> > M.G.
> >
> >
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@osr.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>


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

The rule for propagating the pending bit can actually be stated quite simply:

“STATUS_PENDING may be returned IFF the Irp has been marked pending.” -
David Goebel, Balder Technology Group.

Therefore, if you are synchronizing back to dispatch, you may either:

  1. Return the result of IoCallDriver and propagate the pending bit in your
    completion routine, or
  2. Return Irp->IoStatus.Status, and do not propagate the pending bit in
    your completion routine.

Either should work correctly.

IMNSHO, much of the documentation quoted in this thread is both overly
complex, and badly worded. For example, this:

a… Unless the completion routine signals an event, it must check the
Irp->PendingReturned flag. If this flag is set, the completion routine must
call IoMarkIrpPending to mark the IRP as pending.

is imprecise. There could clearly be other reasons for signalling an event
in a completion routine besides synchronizing back to dispatch.

The OSR article mentioned in the original post says:

“So, for example, you don’t want to propagate the IRPs pending status when
you return STATUS_MORE_ PROCESSING_REQUIRED from your completion routine”

I recall similar verbiage in at least some version of the IFS kit
documentation. I consider this to be oversimplistic. There are cases
where it is perfectly correct to propagate the pending status, and return
STATUS_MORE_PROCESSING_REQUIRED, e.g. when posting your completion routine
to a worker thread to get back to PASSIVE_LEVEL.

However, the OSR article also says:

“Finally, note that it’s considered poor engineering practice to propagate
the pending status of an IRP when this isn’t necessary. Given the
confusion surrounding this topic, always calling IoMarkIrpPending() when
you find Irp->PendingReturned set to TRUE in a completion routine can lead
to misunderstanding the code that’s been implemented.”

Given the very existence of this discussion, I agree completely.

Tony says:

“Actually, upon further thought (the wonders of getting that first cup of
coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
unconditional in this case BECAUSE they are returning STATUS_PENDING in
their completion routine. If I were coding it, I would put it
(IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
is unconditionally returning STATUS_PENDING, they have to call
IoMarkIrpPending.”

which is true (after changing the word “completion” to “dispatch” in the
second sentence, because Tony really needs 2 cups of coffee). However, I
interpreted the original post to mean that the dispatch routine is
returning the result of IoCallDriver, which in this case is STATUS_PENDING,
not explicitly returning STATUS_PENDING. If my interpretaion is correct I
don’t think the code should cause problems - it will just cause the caller
to wait on an event that’s already signalled…

  • Dan.

At 09:58 AM 8/19/2003 -0500, you wrote:

One thing that does appear to be wrong is that the call to IoMarkIrpPending
should not be made. As documented in the IFS Kit:

Checking the PendingReturned Flag
a… Unless the completion routine signals an event, it must check the
Irp->PendingReturned flag. If this flag is set, the completion routine must
call IoMarkIrpPending to mark the IRP as pending.
b… If a completion routine signals an event, it should not call
IoMarkIrpPending.
I recall at a prior Plugfest asking about this and was told by a member of
the filter group that you definitely do not propagate the pending bit when
you synchronize back to dispatch. So, if the completion routine as shown
below is in an actual driver, it can cause some real problems.

Hope this helps.

Jerry

“M.G.” wrote in message news:xxxxx@ntfsd…
> >
> > This post contains two questions, but first, here is the background info.
> > While developing a file system filter, I decided to run some interop tests
> > with major third party vendors. I installed one third party
> > application/filter and began to receive numerous stop code 0x44’s (all of
> > which have been down the create path). I had not received this error
> > while testing against similar third party filters, so I began
> > disassembling their dispatch and completion routines for the create path.
> > From this, I have been able to determine that their completion routine is
> > very simple, but appears to have a mistake in it. I’ve converted the
> > assembly into C to make it easier to follow:
> >
> > NTSTATUS
> > IoCompletion(
> > IN PDEVICE_OBJECT DeviceObject,
> > IN PIRP Irp,
> > IN PVOID Context
> > )
> > {
> > // My filter, which is layered below theirs, will return
> > // STATUS_PENDING down create dispatch, so this if block
> > // will execute.
> > //
> > if(Irp->PendingReturned)
> > {
> > // This is what leads to my first question. Is it
> > // “wrong” to mark the irp pending and yet still
> > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > // article appears to imply it might:
> > // http://www.osronline.com/article.cfm?id=21
> > //
> > IoMarkIrpPending(Irp);
> > }
> >
> > // Context is an event used to resynch completion
> > // back to dispatch
> > //
> > KeSetEvent(Context);
> >
> > return STATUS_MORE_PROCESSING_REQUIRED
> > }
> >
> > Once the completion routine was executed, I had a break point set in the
> > dispatch routine at the point where execution would continue when the
> > event that was passed in as Context was set. Of course, it is common to
> > resynch completion back to dispatch in this manner, but at the end, their
> > dispatch returns STATUS_PENDING. It would seem that at this point, the
> > filter would want to return the status contained in the irp (which was
> > STATUS_SUCCESS on the create) instead of propagating the STATUS_PENDING.
> > Is this a valid thing to do (my opinion is that it doesn’t look right)?
> >
> > With this information in mind, would it be reasonable to conclude that
> > this is the actual bug (in their filter) which is causing my stop code
> > 0x44’s?
> >
> > Thank you,
> > M.G.
> >
> >
>
>
>
>—
>You are currently subscribed to ntfsd as: xxxxx@privtek.com
>To unsubscribe send a blank email to xxxxx@lists.osr.com

> Note that Filespy does not call IoMarkIrpPending anywhere in the dispatch

routine discussed here. So I’m curious when you would call it in the
dispatch routine.

If you’re going to return STATUS_PENDING from your dispatch routine, you
must call IoMarkIrpPending. If lower driver return STATUS_PENDING, you mark
IRP pending in completion routine if Irp->PendingReturned flag is set.

-htfv

----- Original Message -----
From: “Jerry Kelley”
Newsgroups: ntfsd
To: “File Systems Developers”
Sent: Tuesday, August 19, 2003 6:40 PM
Subject: [ntfsd] Re: STATUS_PENDING down Create path

> Thanks Tony.
>
> M.G.,
>
> There’s a very good sample of what should be done. Take a look at Filespy.
> If you look at SpyPassThrough, it is the dispatch routine and handles the
> option of synchronizing with completion. After the call to the lower
driver,
> it makes the standard check for STATUS_PENDING and waits if necessary. It
> then gets the status from the IRP, calls IoCompleteRequest, and returns
the
> IRP status.
>
> The completion routine, SpyPassThroughCompletion, makes the check for
> synching back to dispatch and, if it has to synch, just sets the event and
> returns STATUS_MORE_PROCESSING_REQUIRED. If it didn’t have to synch,
THEN
> it checks the pending bit, marks it if necessary, and returns
> STATUS_SUCCESS.
>
>
> Back to Tony,
>
> Sorry if this is redundant but I was a bit confused by your usage of
> STATUS_PENDING as a return value for the completion routine. Did you mean
> STATUS_MORE_PROCESSING_REQUIRED?
>
> Note that Filespy does not call IoMarkIrpPending anywhere in the dispatch
> routine discussed here. So I’m curious when you would call it in the
> dispatch routine.
>
> Jerry
>
>
> “Tony Mason” wrote in message news:xxxxx@ntfsd…
> >
> > Actually, upon further thought (the wonders of getting that first cup of
> > coffee in the morning) I agree with Jerry. The IoMarkIrpPending should
be
> > unconditional in this case BECAUSE they are returning STATUS_PENDING in
> > their completion routine. If I were coding it, I would put it
> > (IoMarkIrpPending) in the dispatch routine, but since the dispatch
routine
> > is unconditionally returning STATUS_PENDING, they have to call
> > IoMarkIrpPending.
> >
> > This is one of the more complicated pieces to understand for filters (in
> > particular) with respect to the I/O Manager. Get it wrong and the
system
> > blows up in these mysterious ways.
> >
> > Regards,
> >
> > Tony
> >
> > Tony Mason
> > Consulting Partner
> > OSR Open Systems Resources, Inc.
> > http://www.osr.com
> >
> >
> > -----Original Message-----
> > From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
> > Sent: Tuesday, August 19, 2003 10:58 AM
> > To: File Systems Developers
> > Subject: [ntfsd] Re: STATUS_PENDING down Create path
> >
> > One thing that does appear to be wrong is that the call to
> IoMarkIrpPending
> > should not be made. As documented in the IFS Kit:
> >
> > Checking the PendingReturned Flag
> > a… Unless the completion routine signals an event, it must check the
> > Irp->PendingReturned flag. If this flag is set, the completion routine
> must
> > call IoMarkIrpPending to mark the IRP as pending.
> > b… If a completion routine signals an event, it should not call
> > IoMarkIrpPending.
> > I recall at a prior Plugfest asking about this and was told by a member
of
> > the filter group that you definitely do not propagate the pending bit
when
> > you synchronize back to dispatch. So, if the completion routine as shown
> > below is in an actual driver, it can cause some real problems.
> >
> > Hope this helps.
> >
> > Jerry
> >
> >
> > “M.G.” wrote in message news:xxxxx@ntfsd…
> > >
> > > This post contains two questions, but first, here is the background
> info.
> > > While developing a file system filter, I decided to run some interop
> tests
> > > with major third party vendors. I installed one third party
> > > application/filter and began to receive numerous stop code 0x44’s (all
> of
> > > which have been down the create path). I had not received this error
> > > while testing against similar third party filters, so I began
> > > disassembling their dispatch and completion routines for the create
> path.
> > > From this, I have been able to determine that their completion routine
> is
> > > very simple, but appears to have a mistake in it. I’ve converted the
> > > assembly into C to make it easier to follow:
> > >
> > > NTSTATUS
> > > IoCompletion(
> > > IN PDEVICE_OBJECT DeviceObject,
> > > IN PIRP Irp,
> > > IN PVOID Context
> > > )
> > > {
> > > // My filter, which is layered below theirs, will return
> > > // STATUS_PENDING down create dispatch, so this if block
> > > // will execute.
> > > //
> > > if(Irp->PendingReturned)
> > > {
> > > // This is what leads to my first question. Is it
> > > // “wrong” to mark the irp pending and yet still
> > > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > > // article appears to imply it might:
> > > // http://www.osronline.com/article.cfm?id=21
> > > //
> > > IoMarkIrpPending(Irp);
> > > }
> > >
> > > // Context is an event used to resynch completion
> > > // back to dispatch
> > > //
> > > KeSetEvent(Context);
> > >
> > > return STATUS_MORE_PROCESSING_REQUIRED
> > > }
> > >
> > > Once the completion routine was executed, I had a break point set in
the
> > > dispatch routine at the point where execution would continue when the
> > > event that was passed in as Context was set. Of course, it is common
to
> > > resynch completion back to dispatch in this manner, but at the end,
> their
> > > dispatch returns STATUS_PENDING. It would seem that at this point,
the
> > > filter would want to return the status contained in the irp (which was
> > > STATUS_SUCCESS on the create) instead of propagating the
STATUS_PENDING.
> > > Is this a valid thing to do (my opinion is that it doesn’t look
right)?
> > >
> > > With this information in mind, would it be reasonable to conclude that
> > > this is the actual bug (in their filter) which is causing my stop code
> > > 0x44’s?
> > >
> > > Thank you,
> > > M.G.
> > >
> > >
> >
> >
> >
> > —
> > You are currently subscribed to ntfsd as: xxxxx@osr.com
> > To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@vba.com.by
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>

I think the confusion is related to who is deciding the status returned from
dispatch. Looking at samples and the documentation, here’s what it boils
down to:

  1. If you know you’re going to explicitly return STATUS_PENDING in dispatch,
    you call IoMarkIrpPending before you call the lower driver. Then be sure
    that the dispatch routine does return STATUS_PENDING.

  2. If you’re going to return the status from IoCallDriver, then you do not
    mark the pending bit.

  3. If you’re synchronizing with completion, the completion routine must not
    mark the pending bit. Otherwise, the completion routine has to propagate the
    pending bit if it’s set.

So you shouldn’t be setting the pending bit in the completion routine if
it’s synchronizing back to dispatch.

“Alexey Logachyov” wrote in message news:xxxxx@ntfsd…
>
> > Note that Filespy does not call IoMarkIrpPending anywhere in the
dispatch
> > routine discussed here. So I’m curious when you would call it in the
> > dispatch routine.
>
> If you’re going to return STATUS_PENDING from your dispatch routine, you
> must call IoMarkIrpPending. If lower driver return STATUS_PENDING, you
mark
> IRP pending in completion routine if Irp->PendingReturned flag is set.
>
> -htfv
>
>
>
> ----- Original Message -----
> From: “Jerry Kelley”
> Newsgroups: ntfsd
> To: “File Systems Developers”
> Sent: Tuesday, August 19, 2003 6:40 PM
> Subject: [ntfsd] Re: STATUS_PENDING down Create path
>
>
> > Thanks Tony.
> >
> > M.G.,
> >
> > There’s a very good sample of what should be done. Take a look at
Filespy.
> > If you look at SpyPassThrough, it is the dispatch routine and handles
the
> > option of synchronizing with completion. After the call to the lower
> driver,
> > it makes the standard check for STATUS_PENDING and waits if necessary.
It
> > then gets the status from the IRP, calls IoCompleteRequest, and returns
> the
> > IRP status.
> >
> > The completion routine, SpyPassThroughCompletion, makes the check for
> > synching back to dispatch and, if it has to synch, just sets the event
and
> > returns STATUS_MORE_PROCESSING_REQUIRED. If it didn’t have to synch,
> THEN
> > it checks the pending bit, marks it if necessary, and returns
> > STATUS_SUCCESS.
> >
> >
> > Back to Tony,
> >
> > Sorry if this is redundant but I was a bit confused by your usage of
> > STATUS_PENDING as a return value for the completion routine. Did you
mean
> > STATUS_MORE_PROCESSING_REQUIRED?
> >
> > Note that Filespy does not call IoMarkIrpPending anywhere in the
dispatch
> > routine discussed here. So I’m curious when you would call it in the
> > dispatch routine.
> >
> > Jerry
> >
> >
> > “Tony Mason” wrote in message news:xxxxx@ntfsd…
> > >
> > > Actually, upon further thought (the wonders of getting that first cup
of
> > > coffee in the morning) I agree with Jerry. The IoMarkIrpPending
should
> be
> > > unconditional in this case BECAUSE they are returning STATUS_PENDING
in
> > > their completion routine. If I were coding it, I would put it
> > > (IoMarkIrpPending) in the dispatch routine, but since the dispatch
> routine
> > > is unconditionally returning STATUS_PENDING, they have to call
> > > IoMarkIrpPending.
> > >
> > > This is one of the more complicated pieces to understand for filters
(in
> > > particular) with respect to the I/O Manager. Get it wrong and the
> system
> > > blows up in these mysterious ways.
> > >
> > > Regards,
> > >
> > > Tony
> > >
> > > Tony Mason
> > > Consulting Partner
> > > OSR Open Systems Resources, Inc.
> > > http://www.osr.com
> > >
> > >
> > > -----Original Message-----
> > > From: Jerry Kelley [mailto:xxxxx@nsisoftware.com]
> > > Sent: Tuesday, August 19, 2003 10:58 AM
> > > To: File Systems Developers
> > > Subject: [ntfsd] Re: STATUS_PENDING down Create path
> > >
> > > One thing that does appear to be wrong is that the call to
> > IoMarkIrpPending
> > > should not be made. As documented in the IFS Kit:
> > >
> > > Checking the PendingReturned Flag
> > > a… Unless the completion routine signals an event, it must check
the
> > > Irp->PendingReturned flag. If this flag is set, the completion routine
> > must
> > > call IoMarkIrpPending to mark the IRP as pending.
> > > b… If a completion routine signals an event, it should not call
> > > IoMarkIrpPending.
> > > I recall at a prior Plugfest asking about this and was told by a
member
> of
> > > the filter group that you definitely do not propagate the pending bit
> when
> > > you synchronize back to dispatch. So, if the completion routine as
shown
> > > below is in an actual driver, it can cause some real problems.
> > >
> > > Hope this helps.
> > >
> > > Jerry
> > >
> > >
> > > “M.G.” wrote in message news:xxxxx@ntfsd…
> > > >
> > > > This post contains two questions, but first, here is the background
> > info.
> > > > While developing a file system filter, I decided to run some interop
> > tests
> > > > with major third party vendors. I installed one third party
> > > > application/filter and began to receive numerous stop code 0x44’s
(all
> > of
> > > > which have been down the create path). I had not received this
error
> > > > while testing against similar third party filters, so I began
> > > > disassembling their dispatch and completion routines for the create
> > path.
> > > > From this, I have been able to determine that their completion
routine
> > is
> > > > very simple, but appears to have a mistake in it. I’ve converted
the
> > > > assembly into C to make it easier to follow:
> > > >
> > > > NTSTATUS
> > > > IoCompletion(
> > > > IN PDEVICE_OBJECT DeviceObject,
> > > > IN PIRP Irp,
> > > > IN PVOID Context
> > > > )
> > > > {
> > > > // My filter, which is layered below theirs, will return
> > > > // STATUS_PENDING down create dispatch, so this if block
> > > > // will execute.
> > > > //
> > > > if(Irp->PendingReturned)
> > > > {
> > > > // This is what leads to my first question. Is it
> > > > // “wrong” to mark the irp pending and yet still
> > > > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > > > // article appears to imply it might:
> > > > // http://www.osronline.com/article.cfm?id=21
> > > > //
> > > > IoMarkIrpPending(Irp);
> > > > }
> > > >
> > > > // Context is an event used to resynch completion
> > > > // back to dispatch
> > > > //
> > > > KeSetEvent(Context);
> > > >
> > > > return STATUS_MORE_PROCESSING_REQUIRED
> > > > }
> > > >
> > > > Once the completion routine was executed, I had a break point set in
> the
> > > > dispatch routine at the point where execution would continue when
the
> > > > event that was passed in as Context was set. Of course, it is
common
> to
> > > > resynch completion back to dispatch in this manner, but at the end,
> > their
> > > > dispatch returns STATUS_PENDING. It would seem that at this point,
> the
> > > > filter would want to return the status contained in the irp (which
was
> > > > STATUS_SUCCESS on the create) instead of propagating the
> STATUS_PENDING.
> > > > Is this a valid thing to do (my opinion is that it doesn’t look
> right)?
> > > >
> > > > With this information in mind, would it be reasonable to conclude
that
> > > > this is the actual bug (in their filter) which is causing my stop
code
> > > > 0x44’s?
> > > >
> > > > Thank you,
> > > > M.G.
> > > >
> > > >
> > >
> > >
> > >
> > > —
> > > You are currently subscribed to ntfsd as: xxxxx@osr.com
> > > To unsubscribe send a blank email to xxxxx@lists.osr.com
> > >
> > >
> >
> >
> >
> > —
> > You are currently subscribed to ntfsd as: xxxxx@vba.com.by
> > To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
>
>
>
>
>

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine. Given that overly simplistic perception, it is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit, and
    return SMPR.

I’ll be the first to admit that I’m wrong if this is not the correct
behavior for this case. But that’s how I’ve come to understand the Magical
Pending Bit.

And the real question is, what could happen if the pending bit is set by the
completion routine in this case?

“Dan Kyler” wrote in message news:xxxxx@ntfsd…
>
> The rule for propagating the pending bit can actually be stated quite
simply:
>
> “STATUS_PENDING may be returned IFF the Irp has been marked pending.” -
> David Goebel, Balder Technology Group.
>
> Therefore, if you are synchronizing back to dispatch, you may either:
>
> 1) Return the result of IoCallDriver and propagate the pending bit in your
> completion routine, or
> 2) Return Irp->IoStatus.Status, and do not propagate the pending bit in
> your completion routine.
>
> Either should work correctly.
>
> IMNSHO, much of the documentation quoted in this thread is both overly
> complex, and badly worded. For example, this:
>
> > a… Unless the completion routine signals an event, it must check the
> >Irp->PendingReturned flag. If this flag is set, the completion routine
must
> >call IoMarkIrpPending to mark the IRP as pending.
>
> is imprecise. There could clearly be other reasons for signalling an
event
> in a completion routine besides synchronizing back to dispatch.
>
> The OSR article mentioned in the original post says:
>
> “So, for example, you don’t want to propagate the IRPs pending status when
> you return STATUS_MORE_ PROCESSING_REQUIRED from your completion routine”
>
> I recall similar verbiage in at least some version of the IFS kit
> documentation. I consider this to be oversimplistic. There are cases
> where it is perfectly correct to propagate the pending status, and return
> STATUS_MORE_PROCESSING_REQUIRED, e.g. when posting your completion routine
> to a worker thread to get back to PASSIVE_LEVEL.
>
> However, the OSR article also says:
>
> “Finally, note that it’s considered poor engineering practice to propagate
> the pending status of an IRP when this isn’t necessary. Given the
> confusion surrounding this topic, always calling IoMarkIrpPending() when
> you find Irp->PendingReturned set to TRUE in a completion routine can lead
> to misunderstanding the code that’s been implemented.”
>
> Given the very existence of this discussion, I agree completely.
>
> Tony says:
>
> “Actually, upon further thought (the wonders of getting that first cup of
> coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
> unconditional in this case BECAUSE they are returning STATUS_PENDING in
> their completion routine. If I were coding it, I would put it
> (IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
> is unconditionally returning STATUS_PENDING, they have to call
> IoMarkIrpPending.”
>
> which is true (after changing the word “completion” to “dispatch” in the
> second sentence, because Tony really needs 2 cups of coffee). However, I
> interpreted the original post to mean that the dispatch routine is
> returning the result of IoCallDriver, which in this case is
STATUS_PENDING,
> not explicitly returning STATUS_PENDING. If my interpretaion is correct I
> don’t think the code should cause problems - it will just cause the caller
> to wait on an event that’s already signalled…
>
> - Dan.
>
> At 09:58 AM 8/19/2003 -0500, you wrote:
> >One thing that does appear to be wrong is that the call to
IoMarkIrpPending
> >should not be made. As documented in the IFS Kit:
> >
> >Checking the PendingReturned Flag
> > a… Unless the completion routine signals an event, it must check the
> >Irp->PendingReturned flag. If this flag is set, the completion routine
must
> >call IoMarkIrpPending to mark the IRP as pending.
> > b… If a completion routine signals an event, it should not call
> >IoMarkIrpPending.
> >I recall at a prior Plugfest asking about this and was told by a member
of
> >the filter group that you definitely do not propagate the pending bit
when
> >you synchronize back to dispatch. So, if the completion routine as shown
> >below is in an actual driver, it can cause some real problems.
> >
> >Hope this helps.
> >
> >Jerry
> >
> >
> >“M.G.” wrote in message news:xxxxx@ntfsd…
> > >
> > > This post contains two questions, but first, here is the background
info.
> > > While developing a file system filter, I decided to run some interop
tests
> > > with major third party vendors. I installed one third party
> > > application/filter and began to receive numerous stop code 0x44’s (all
of
> > > which have been down the create path). I had not received this error
> > > while testing against similar third party filters, so I began
> > > disassembling their dispatch and completion routines for the create
path.
> > > From this, I have been able to determine that their completion routine
is
> > > very simple, but appears to have a mistake in it. I’ve converted the
> > > assembly into C to make it easier to follow:
> > >
> > > NTSTATUS
> > > IoCompletion(
> > > IN PDEVICE_OBJECT DeviceObject,
> > > IN PIRP Irp,
> > > IN PVOID Context
> > > )
> > > {
> > > // My filter, which is layered below theirs, will return
> > > // STATUS_PENDING down create dispatch, so this if block
> > > // will execute.
> > > //
> > > if(Irp->PendingReturned)
> > > {
> > > // This is what leads to my first question. Is it
> > > // “wrong” to mark the irp pending and yet still
> > > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > > // article appears to imply it might:
> > > // http://www.osronline.com/article.cfm?id=21
> > > //
> > > IoMarkIrpPending(Irp);
> > > }
> > >
> > > // Context is an event used to resynch completion
> > > // back to dispatch
> > > //
> > > KeSetEvent(Context);
> > >
> > > return STATUS_MORE_PROCESSING_REQUIRED
> > > }
> > >
> > > Once the completion routine was executed, I had a break point set in
the
> > > dispatch routine at the point where execution would continue when the
> > > event that was passed in as Context was set. Of course, it is common
to
> > > resynch completion back to dispatch in this manner, but at the end,
their
> > > dispatch returns STATUS_PENDING. It would seem that at this point,
the
> > > filter would want to return the status contained in the irp (which was
> > > STATUS_SUCCESS on the create) instead of propagating the
STATUS_PENDING.
> > > Is this a valid thing to do (my opinion is that it doesn’t look
right)?
> > >
> > > With this information in mind, would it be reasonable to conclude that
> > > this is the actual bug (in their filter) which is causing my stop code
> > > 0x44’s?
> > >
> > > Thank you,
> > > M.G.
> > >
> > >
> >
> >
> >
> >—
> >You are currently subscribed to ntfsd as: xxxxx@privtek.com
> >To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
>

At 01:12 PM 8/19/2003 -0500, you wrote:

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine.

If that’s the case it’s definitely broken, as Tony said (and after only one
cup).

Given that overly simplistic perception, it is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit, and
    return SMPR.

Agreed.

And the real question is, what could happen if the pending bit is set by the
completion routine in this case?

I’d be more worried about what happens when the completion routine doesn’t
set the pending bit. In that case, STATUS_PENDING would be returned, and
the Irp would not be marked pending. Off the top of my head, this could
cause the caller to wait on an event that will never be signalled.

  • Dan.

At 01:12 PM 8/19/2003 -0500, you wrote:

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine. Given that overly simplistic perception, it is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit, and
    return SMPR.

I’ll be the first to admit that I’m wrong if this is not the correct
behavior for this case. But that’s how I’ve come to understand the Magical
Pending Bit.

And the real question is, what could happen if the pending bit is set by the
completion routine in this case?

“Dan Kyler” wrote in message news:xxxxx@ntfsd…
> >
> > The rule for propagating the pending bit can actually be stated quite
>simply:
> >
> > “STATUS_PENDING may be returned IFF the Irp has been marked pending.” -
> > David Goebel, Balder Technology Group.
> >
> > Therefore, if you are synchronizing back to dispatch, you may either:
> >
> > 1) Return the result of IoCallDriver and propagate the pending bit in your
> > completion routine, or
> > 2) Return Irp->IoStatus.Status, and do not propagate the pending bit in
> > your completion routine.
> >
> > Either should work correctly.
> >
> > IMNSHO, much of the documentation quoted in this thread is both overly
> > complex, and badly worded. For example, this:
> >
> > > a… Unless the completion routine signals an event, it must check the
> > >Irp->PendingReturned flag. If this flag is set, the completion routine
>must
> > >call IoMarkIrpPending to mark the IRP as pending.
> >
> > is imprecise. There could clearly be other reasons for signalling an
>event
> > in a completion routine besides synchronizing back to dispatch.
> >
> > The OSR article mentioned in the original post says:
> >
> > “So, for example, you don’t want to propagate the IRPs pending status when
> > you return STATUS_MORE_ PROCESSING_REQUIRED from your completion routine”
> >
> > I recall similar verbiage in at least some version of the IFS kit
> > documentation. I consider this to be oversimplistic. There are cases
> > where it is perfectly correct to propagate the pending status, and return
> > STATUS_MORE_PROCESSING_REQUIRED, e.g. when posting your completion routine
> > to a worker thread to get back to PASSIVE_LEVEL.
> >
> > However, the OSR article also says:
> >
> > “Finally, note that it’s considered poor engineering practice to propagate
> > the pending status of an IRP when this isn’t necessary. Given the
> > confusion surrounding this topic, always calling IoMarkIrpPending() when
> > you find Irp->PendingReturned set to TRUE in a completion routine can lead
> > to misunderstanding the code that’s been implemented.”
> >
> > Given the very existence of this discussion, I agree completely.
> >
> > Tony says:
> >
> > “Actually, upon further thought (the wonders of getting that first cup of
> > coffee in the morning) I agree with Jerry. The IoMarkIrpPending should be
> > unconditional in this case BECAUSE they are returning STATUS_PENDING in
> > their completion routine. If I were coding it, I would put it
> > (IoMarkIrpPending) in the dispatch routine, but since the dispatch routine
> > is unconditionally returning STATUS_PENDING, they have to call
> > IoMarkIrpPending.”
> >
> > which is true (after changing the word “completion” to “dispatch” in the
> > second sentence, because Tony really needs 2 cups of coffee). However, I
> > interpreted the original post to mean that the dispatch routine is
> > returning the result of IoCallDriver, which in this case is
>STATUS_PENDING,
> > not explicitly returning STATUS_PENDING. If my interpretaion is correct I
> > don’t think the code should cause problems - it will just cause the caller
> > to wait on an event that’s already signalled…
> >
> > - Dan.
> >
> > At 09:58 AM 8/19/2003 -0500, you wrote:
> > >One thing that does appear to be wrong is that the call to
>IoMarkIrpPending
> > >should not be made. As documented in the IFS Kit:
> > >
> > >Checking the PendingReturned Flag
> > > a… Unless the completion routine signals an event, it must check the
> > >Irp->PendingReturned flag. If this flag is set, the completion routine
>must
> > >call IoMarkIrpPending to mark the IRP as pending.
> > > b… If a completion routine signals an event, it should not call
> > >IoMarkIrpPending.
> > >I recall at a prior Plugfest asking about this and was told by a member
>of
> > >the filter group that you definitely do not propagate the pending bit
>when
> > >you synchronize back to dispatch. So, if the completion routine as shown
> > >below is in an actual driver, it can cause some real problems.
> > >
> > >Hope this helps.
> > >
> > >Jerry
> > >
> > >
> > >“M.G.” wrote in message news:xxxxx@ntfsd…
> > > >
> > > > This post contains two questions, but first, here is the background
>info.
> > > > While developing a file system filter, I decided to run some interop
>tests
> > > > with major third party vendors. I installed one third party
> > > > application/filter and began to receive numerous stop code 0x44’s (all
>of
> > > > which have been down the create path). I had not received this error
> > > > while testing against similar third party filters, so I began
> > > > disassembling their dispatch and completion routines for the create
>path.
> > > > From this, I have been able to determine that their completion routine
>is
> > > > very simple, but appears to have a mistake in it. I’ve converted the
> > > > assembly into C to make it easier to follow:
> > > >
> > > > NTSTATUS
> > > > IoCompletion(
> > > > IN PDEVICE_OBJECT DeviceObject,
> > > > IN PIRP Irp,
> > > > IN PVOID Context
> > > > )
> > > > {
> > > > // My filter, which is layered below theirs, will return
> > > > // STATUS_PENDING down create dispatch, so this if block
> > > > // will execute.
> > > > //
> > > > if(Irp->PendingReturned)
> > > > {
> > > > // This is what leads to my first question. Is it
> > > > // “wrong” to mark the irp pending and yet still
> > > > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > > > // article appears to imply it might:
> > > > // http://www.osronline.com/article.cfm?id=21
> > > > //
> > > > IoMarkIrpPending(Irp);
> > > > }
> > > >
> > > > // Context is an event used to resynch completion
> > > > // back to dispatch
> > > > //
> > > > KeSetEvent(Context);
> > > >
> > > > return STATUS_MORE_PROCESSING_REQUIRED
> > > > }
> > > >
> > > > Once the completion routine was executed, I had a break point set in
>the
> > > > dispatch routine at the point where execution would continue when the
> > > > event that was passed in as Context was set. Of course, it is common
>to
> > > > resynch completion back to dispatch in this manner, but at the end,
>their
> > > > dispatch returns STATUS_PENDING. It would seem that at this point,
>the
> > > > filter would want to return the status contained in the irp (which was
> > > > STATUS_SUCCESS on the create) instead of propagating the
>STATUS_PENDING.
> > > > Is this a valid thing to do (my opinion is that it doesn’t look
>right)?
> > > >
> > > > With this information in mind, would it be reasonable to conclude that
> > > > this is the actual bug (in their filter) which is causing my stop code
> > > > 0x44’s?
> > > >
> > > > Thank you,
> > > > M.G.
> > > >
> > > >
> > >
> > >
> > >
> > >—
> > >You are currently subscribed to ntfsd as: xxxxx@privtek.com
> > >To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
> >
> >
>
>
>
>—
>You are currently subscribed to ntfsd as: xxxxx@privtek.com
>To unsubscribe send a blank email to xxxxx@lists.osr.com

Dan is right on the money here. There are four possible scenarios:

(1) Mark the IRP pending (SL_PENDING_RETURNED bit set in the stack location)

  • return STATUS_PENDING
    (2) Mark the IRP pending, return anything EXCEPT STATUS_PENDING
    (3) Don’t mark the IRP pending, return STATUS_PENDING
    (4) Don’t mark the IRP pending, return anything EXCEPT STATUS_PENDING

(1) and (4) work fine. (2) cause MULTIPLE_IRP_COMPLETION bugchecks
(although depending upon implementation not guaranteed 100% of the time).
(3) causes the I/O to “hang” (because the APC never runs)

Regards,

Tony

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

-----Original Message-----
From: Dan Kyler [mailto:xxxxx@privtek.com]
Sent: Tuesday, August 19, 2003 2:38 PM
To: File Systems Developers
Subject: [ntfsd] Re: STATUS_PENDING down Create path

At 01:12 PM 8/19/2003 -0500, you wrote:

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine.

If that’s the case it’s definitely broken, as Tony said (and after only one
cup).

Given that overly simplistic perception, it is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit,
    and
    return SMPR.

Agreed.

And the real question is, what could happen if the pending bit is set by
the
completion routine in this case?

I’d be more worried about what happens when the completion routine doesn’t
set the pending bit. In that case, STATUS_PENDING would be returned, and
the Irp would not be marked pending. Off the top of my head, this could
cause the caller to wait on an event that will never be signalled.

  • Dan.

At 01:12 PM 8/19/2003 -0500, you wrote:

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine. Given that overly simplistic perception, it is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit,
    and
    return SMPR.

I’ll be the first to admit that I’m wrong if this is not the correct
behavior for this case. But that’s how I’ve come to understand the Magical
Pending Bit.

And the real question is, what could happen if the pending bit is set by
the
completion routine in this case?

“Dan Kyler” wrote in message news:xxxxx@ntfsd…
> >
> > The rule for propagating the pending bit can actually be stated quite
>simply:
> >
> > “STATUS_PENDING may be returned IFF the Irp has been marked pending.” -
> > David Goebel, Balder Technology Group.
> >
> > Therefore, if you are synchronizing back to dispatch, you may either:
> >
> > 1) Return the result of IoCallDriver and propagate the pending bit in
your
> > completion routine, or
> > 2) Return Irp->IoStatus.Status, and do not propagate the pending bit in
> > your completion routine.
> >
> > Either should work correctly.
> >
> > IMNSHO, much of the documentation quoted in this thread is both overly
> > complex, and badly worded. For example, this:
> >
> > > a… Unless the completion routine signals an event, it must check
the
> > >Irp->PendingReturned flag. If this flag is set, the completion routine
>must
> > >call IoMarkIrpPending to mark the IRP as pending.
> >
> > is imprecise. There could clearly be other reasons for signalling an
>event
> > in a completion routine besides synchronizing back to dispatch.
> >
> > The OSR article mentioned in the original post says:
> >
> > “So, for example, you don’t want to propagate the IRPs pending status
when
> > you return STATUS_MORE_ PROCESSING_REQUIRED from your completion
routine”
> >
> > I recall similar verbiage in at least some version of the IFS kit
> > documentation. I consider this to be oversimplistic. There are cases
> > where it is perfectly correct to propagate the pending status, and
return
> > STATUS_MORE_PROCESSING_REQUIRED, e.g. when posting your completion
routine
> > to a worker thread to get back to PASSIVE_LEVEL.
> >
> > However, the OSR article also says:
> >
> > “Finally, note that it’s considered poor engineering practice to
propagate
> > the pending status of an IRP when this isn’t necessary. Given the
> > confusion surrounding this topic, always calling IoMarkIrpPending() when
> > you find Irp->PendingReturned set to TRUE in a completion routine can
lead
> > to misunderstanding the code that’s been implemented.”
> >
> > Given the very existence of this discussion, I agree completely.
> >
> > Tony says:
> >
> > “Actually, upon further thought (the wonders of getting that first cup
of
> > coffee in the morning) I agree with Jerry. The IoMarkIrpPending should
be
> > unconditional in this case BECAUSE they are returning STATUS_PENDING in
> > their completion routine. If I were coding it, I would put it
> > (IoMarkIrpPending) in the dispatch routine, but since the dispatch
routine
> > is unconditionally returning STATUS_PENDING, they have to call
> > IoMarkIrpPending.”
> >
> > which is true (after changing the word “completion” to “dispatch” in the
> > second sentence, because Tony really needs 2 cups of coffee). However,
I
> > interpreted the original post to mean that the dispatch routine is
> > returning the result of IoCallDriver, which in this case is
>STATUS_PENDING,
> > not explicitly returning STATUS_PENDING. If my interpretaion is correct
I
> > don’t think the code should cause problems - it will just cause the
caller
> > to wait on an event that’s already signalled…
> >
> > - Dan.
> >
> > At 09:58 AM 8/19/2003 -0500, you wrote:
> > >One thing that does appear to be wrong is that the call to
>IoMarkIrpPending
> > >should not be made. As documented in the IFS Kit:
> > >
> > >Checking the PendingReturned Flag
> > > a… Unless the completion routine signals an event, it must check
the
> > >Irp->PendingReturned flag. If this flag is set, the completion routine
>must
> > >call IoMarkIrpPending to mark the IRP as pending.
> > > b… If a completion routine signals an event, it should not call
> > >IoMarkIrpPending.
> > >I recall at a prior Plugfest asking about this and was told by a member
>of
> > >the filter group that you definitely do not propagate the pending bit
>when
> > >you synchronize back to dispatch. So, if the completion routine as
shown
> > >below is in an actual driver, it can cause some real problems.
> > >
> > >Hope this helps.
> > >
> > >Jerry
> > >
> > >
> > >“M.G.” wrote in message news:xxxxx@ntfsd…
> > > >
> > > > This post contains two questions, but first, here is the background
>info.
> > > > While developing a file system filter, I decided to run some interop
>tests
> > > > with major third party vendors. I installed one third party
> > > > application/filter and began to receive numerous stop code 0x44’s
(all
>of
> > > > which have been down the create path). I had not received this
error
> > > > while testing against similar third party filters, so I began
> > > > disassembling their dispatch and completion routines for the create
>path.
> > > > From this, I have been able to determine that their completion
routine
>is
> > > > very simple, but appears to have a mistake in it. I’ve converted
the
> > > > assembly into C to make it easier to follow:
> > > >
> > > > NTSTATUS
> > > > IoCompletion(
> > > > IN PDEVICE_OBJECT DeviceObject,
> > > > IN PIRP Irp,
> > > > IN PVOID Context
> > > > )
> > > > {
> > > > // My filter, which is layered below theirs, will return
> > > > // STATUS_PENDING down create dispatch, so this if block
> > > > // will execute.
> > > > //
> > > > if(Irp->PendingReturned)
> > > > {
> > > > // This is what leads to my first question. Is it
> > > > // “wrong” to mark the irp pending and yet still
> > > > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > > > // article appears to imply it might:
> > > > // http://www.osronline.com/article.cfm?id=21
> > > > //
> > > > IoMarkIrpPending(Irp);
> > > > }
> > > >
> > > > // Context is an event used to resynch completion
> > > > // back to dispatch
> > > > //
> > > > KeSetEvent(Context);
> > > >
> > > > return STATUS_MORE_PROCESSING_REQUIRED
> > > > }
> > > >
> > > > Once the completion routine was executed, I had a break point set in
>the
> > > > dispatch routine at the point where execution would continue when
the
> > > > event that was passed in as Context was set. Of course, it is
common
>to
> > > > resynch completion back to dispatch in this manner, but at the end,
>their
> > > > dispatch returns STATUS_PENDING. It would seem that at this point,
>the
> > > > filter would want to return the status contained in the irp (which
was
> > > > STATUS_SUCCESS on the create) instead of propagating the
>STATUS_PENDING.
> > > > Is this a valid thing to do (my opinion is that it doesn’t look
>right)?
> > > >
> > > > With this information in mind, would it be reasonable to conclude
that
> > > > this is the actual bug (in their filter) which is causing my stop
code
> > > > 0x44’s?
> > > >
> > > > Thank you,
> > > > M.G.
> > > >
> > > >
> > >
> > >
> > >
> > >—
> > >You are currently subscribed to ntfsd as: xxxxx@privtek.com
> > >To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
> >
> >
>
>
>
>—
>You are currently subscribed to ntfsd as: xxxxx@privtek.com
>To unsubscribe send a blank email to xxxxx@lists.osr.com


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

UPDATE:
I thought I would send a quick update for all those who gave input on this
issue. We loaded both drivers onto a W2K3 machine and ran IrpTracker
(this is an excellent tool… too bad it’s not available for NT4/NT5).
With this tool, we were able to see that the status of the IRP was
STATUS_ACCESS_DENIED. With that, we knew that either the file system was
returning the status, or the other driver was changing the status. After
we eliminated the first possibility, we began searching the other driver’s
assembly for instructions that would change the status. From there we
soon discovered that the other driver was not only changing the status of
the IRP, but then also returning STATUS_ACCESS_DENIED on the IRP which was
marked status pending (by their completion routine). Looking at the handy
list below, we see that this creates the 2nd condition (which leads to
stop 0x44 - MULTIPLE_IRP_COMPLETION bugchecks).

Thank you all for your help,
M.G.

Dan is right on the money here. There are four possible scenarios:

(1) Mark the IRP pending (SL_PENDING_RETURNED bit set in the stack
location)

  • return STATUS_PENDING
    (2) Mark the IRP pending, return anything EXCEPT STATUS_PENDING
    (3) Don’t mark the IRP pending, return STATUS_PENDING
    (4) Don’t mark the IRP pending, return anything EXCEPT STATUS_PENDING

(1) and (4) work fine. (2) cause MULTIPLE_IRP_COMPLETION bugchecks
(although depending upon implementation not guaranteed 100% of the time).
(3) causes the I/O to “hang” (because the APC never runs)

Regards,

Tony

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

-----Original Message-----
From: Dan Kyler [mailto:xxxxx@privtek.com]
Sent: Tuesday, August 19, 2003 2:38 PM
To: File Systems Developers
Subject: [ntfsd] Re: STATUS_PENDING down Create path

At 01:12 PM 8/19/2003 -0500, you wrote:

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine.

If that’s the case it’s definitely broken, as Tony said (and after only
one
cup).

Given that overly simplistic perception, it is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit,
    and
    return SMPR.

Agreed.

And the real question is, what could happen if the pending bit is set by
the
completion routine in this case?

I’d be more worried about what happens when the completion routine doesn’t
set the pending bit. In that case, STATUS_PENDING would be returned, and
the Irp would not be marked pending. Off the top of my head, this could
cause the caller to wait on an event that will never be signalled.

  • Dan.

At 01:12 PM 8/19/2003 -0500, you wrote:

I believe what M.G. is describing is a dispatch routine that explicitly
returns STATUS_PENDING and a completion routine that’s only purpose is to
signal the dispatch routine. Given that overly simplistic perception, it
is
my understanding that:

  1. In dispatch, the pending bit should be marked before IoCallDriver.
  2. In completion, just set the event, do not check the pending bit,
    and
    return SMPR.

I’ll be the first to admit that I’m wrong if this is not the correct
behavior for this case. But that’s how I’ve come to understand the
Magical
Pending Bit.

And the real question is, what could happen if the pending bit is set by
the
completion routine in this case?

“Dan Kyler” wrote in message news:xxxxx@ntfsd…
> >
> > The rule for propagating the pending bit can actually be stated quite
>simply:
> >
> > “STATUS_PENDING may be returned IFF the Irp has been marked pending.” -
> > David Goebel, Balder Technology Group.
> >
> > Therefore, if you are synchronizing back to dispatch, you may either:
> >
> > 1) Return the result of IoCallDriver and propagate the pending bit in
your
> > completion routine, or
> > 2) Return Irp->IoStatus.Status, and do not propagate the pending bit in
> > your completion routine.
> >
> > Either should work correctly.
> >
> > IMNSHO, much of the documentation quoted in this thread is both overly
> > complex, and badly worded. For example, this:
> >
> > > a… Unless the completion routine signals an event, it must check
the
> > >Irp->PendingReturned flag. If this flag is set, the completion routine
>must
> > >call IoMarkIrpPending to mark the IRP as pending.
> >
> > is imprecise. There could clearly be other reasons for signalling an
>event
> > in a completion routine besides synchronizing back to dispatch.
> >
> > The OSR article mentioned in the original post says:
> >
> > “So, for example, you don’t want to propagate the IRPs pending status
when
> > you return STATUS_MORE_ PROCESSING_REQUIRED from your completion
routine”
> >
> > I recall similar verbiage in at least some version of the IFS kit
> > documentation. I consider this to be oversimplistic. There are cases
> > where it is perfectly correct to propagate the pending status, and
return
> > STATUS_MORE_PROCESSING_REQUIRED, e.g. when posting your completion
routine
> > to a worker thread to get back to PASSIVE_LEVEL.
> >
> > However, the OSR article also says:
> >
> > “Finally, note that it’s considered poor engineering practice to
propagate
> > the pending status of an IRP when this isn’t necessary. Given the
> > confusion surrounding this topic, always calling IoMarkIrpPending() when
> > you find Irp->PendingReturned set to TRUE in a completion routine can
lead
> > to misunderstanding the code that’s been implemented.”
> >
> > Given the very existence of this discussion, I agree completely.
> >
> > Tony says:
> >
> > “Actually, upon further thought (the wonders of getting that first cup
of
> > coffee in the morning) I agree with Jerry. The IoMarkIrpPending should
be
> > unconditional in this case BECAUSE they are returning STATUS_PENDING in
> > their completion routine. If I were coding it, I would put it
> > (IoMarkIrpPending) in the dispatch routine, but since the dispatch
routine
> > is unconditionally returning STATUS_PENDING, they have to call
> > IoMarkIrpPending.”
> >
> > which is true (after changing the word “completion” to “dispatch” in the
> > second sentence, because Tony really needs 2 cups of coffee). However,
I
> > interpreted the original post to mean that the dispatch routine is
> > returning the result of IoCallDriver, which in this case is
>STATUS_PENDING,
> > not explicitly returning STATUS_PENDING. If my interpretaion is correct
I
> > don’t think the code should cause problems - it will just cause the
caller
> > to wait on an event that’s already signalled…
> >
> > - Dan.
> >
> > At 09:58 AM 8/19/2003 -0500, you wrote:
> > >One thing that does appear to be wrong is that the call to
>IoMarkIrpPending
> > >should not be made. As documented in the IFS Kit:
> > >
> > >Checking the PendingReturned Flag
> > > a… Unless the completion routine signals an event, it must check
the
> > >Irp->PendingReturned flag. If this flag is set, the completion routine
>must
> > >call IoMarkIrpPending to mark the IRP as pending.
> > > b… If a completion routine signals an event, it should not call
> > >IoMarkIrpPending.
> > >I recall at a prior Plugfest asking about this and was told by a member
>of
> > >the filter group that you definitely do not propagate the pending bit
>when
> > >you synchronize back to dispatch. So, if the completion routine as
shown
> > >below is in an actual driver, it can cause some real problems.
> > >
> > >Hope this helps.
> > >
> > >Jerry
> > >
> > >
> > >“M.G.” wrote in message news:xxxxx@ntfsd…
> > > >
> > > > This post contains two questions, but first, here is the background
>info.
> > > > While developing a file system filter, I decided to run some interop
>tests
> > > > with major third party vendors. I installed one third party
> > > > application/filter and began to receive numerous stop code 0x44’s
(all
>of
> > > > which have been down the create path). I had not received this
error
> > > > while testing against similar third party filters, so I began
> > > > disassembling their dispatch and completion routines for the create
>path.
> > > > From this, I have been able to determine that their completion
routine
>is
> > > > very simple, but appears to have a mistake in it. I’ve converted
the
> > > > assembly into C to make it easier to follow:
> > > >
> > > > NTSTATUS
> > > > IoCompletion(
> > > > IN PDEVICE_OBJECT DeviceObject,
> > > > IN PIRP Irp,
> > > > IN PVOID Context
> > > > )
> > > > {
> > > > // My filter, which is layered below theirs, will return
> > > > // STATUS_PENDING down create dispatch, so this if block
> > > > // will execute.
> > > > //
> > > > if(Irp->PendingReturned)
> > > > {
> > > > // This is what leads to my first question. Is it
> > > > // “wrong” to mark the irp pending and yet still
> > > > // return STATUS_MORE_PROCESSING_REQUIRED? This OSR
> > > > // article appears to imply it might:
> > > > // http://www.osronline.com/article.cfm?id=21
> > > > //
> > > > IoMarkIrpPending(Irp);
> > > > }
> > > >
> > > > // Context is an event used to resynch completion
> > > > // back to dispatch
> > > > //
> > > > KeSetEvent(Context);
> > > >
> > > > return STATUS_MORE_PROCESSING_REQUIRED
> > > > }
> > > >
> > > > Once the completion routine was executed, I had a break point set in
>the
> > > > dispatch routine at the point where execution would continue when
the
> > > > event that was passed in as Context was set. Of course, it is
common
>to
> > > > resynch completion back to dispatch in this manner, but at the end,
>their
> > > > dispatch returns STATUS_PENDING. It would seem that at this point,
>the
> > > > filter would want to return the status contained in the irp (which
was
> > > > STATUS_SUCCESS on the create) instead of propagating the
>STATUS_PENDING.
> > > > Is this a valid thing to do (my opinion is that it doesn’t look
>right)?
> > > >
> > > > With this information in mind, would it be reasonable to conclude
that
> > > > this is the actual bug (in their filter) which is causing my stop
code
> > > > 0x44’s?
> > > >
> > > > Thank you,
> > > > M.G.
> > > >
> > > >
> > >
> > >
> > >
> > >—
> > >You are currently subscribed to ntfsd as: xxxxx@privtek.com
> > >To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
> >
> >
>
>
>
>—
>You are currently subscribed to ntfsd as: xxxxx@privtek.com
>To unsubscribe send a blank email to xxxxx@lists.osr.com


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


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