Re: PendingReturned and a subsidiary IRP
- From: soviet_bloke@xxxxxxxxxxx
- Date: 22 Nov 2006 01:23:23 -0800
Again I receive an arrogant, foolish, surface-level answer that
results from too much repetition of high-level conclusions and not
enough understanding of the underlying rules that create those
conclusions.
Again, agressive reaction, instead of willingness to learn and analyze
things.....
In fact, instead of posting questions, you should try to write your own
code, so that you will see how it all works. Once you believe that your
code should work, you can try actually running it, so that you will see
the "result"....
You just cannot learn how to write drivers simply by reading MSDN,
books or by asking questions - you need some practical exercise.
Practically all logic in your post (as well as in most posts that you
make) is faulty, and this directly results from your lack of practical
hands-on experience. Believe me or not, but after you start practical
experimentation, quite a few things from DDK documentation will start
making a perfect sense to you, although right now they don't ....
Look below:
The documentation also states that "If a driver
sets an IoCompletion routine for an IRP and then passes the IRP down
to a lower driver, the IoCompletion routine should check the
IRP->PendingReturned flag. If the flag is set, the IoCompletion
routine must call IoMarkIrpPending with the IRP." This implies that
IoMarkIrpPending would not have been called in the dispatch routine
(as the statement you quoted unfortunately says in unclear terms),
since there's no need for a single driver to call IoMarkIrpPending
twice for the same IRP.
Don't you understand that the above statement does not come to a
*SLIGHTEST* contradiction with the quotation that I have provided????
Look at the quotation - "Unless an IRP's dispatch routine completes the
IRP (by calling IoCompleteRequest) or passes the IRP on to lower
drivers, it must call IoMarkIrpPending with the IRP". It is
understandable that, once Dispatch() routine passes IRP to the
lower-level driver in the case that you have described, it does not
call IoMarkIrpPending(). What may be possibly unclear here????
Here is one more excerpt:
If IoCallDriver for the subsidiary IRP returns STATUS_PENDING (and as
I said I then return that from my dispatch routine as well), the I/O
manager will not attempt to complete the IRP as soon as the dispatch
routine returns control. It can't. It doesn't have the
success/failure status for the IRP yet. It has to hold off until the
IRP is completed,
You should clearly realize that IoCallDriver(), IoMarkIrpPending() and
IoCompleteRequest() are IO Manager's routines, so that IO Manager
expects to be involved with IRP that it passed to your driver well
before Dispatch() routine returns control. If it sees that your
Dispatch() routine did not do anything about the given IRP, it has no
option other than completing it - otherwise, it may have no chance to
be completed (you want to do it upon subsidiary IRP's completion, but
the IO Manager does not know it, does it????). Therefore, by calling
IoMarkIrpPending() you simply inform IO Manager about your intention
to complete IRP at some later stage - returning STATUS_PENDING is not
enough
IoMarkIrpPending is not what controls whether the I/O manager will
attempt to complete the IRP as soon as the dispatch routine returns.
STATUS_PENDING is what does this. STATUS_PENDING informs the I/O
manager the IRP won't be completed for a while and possibly not in the
original thread context. IoMarkIrpPending informs IoCompleteRequest
to do the special handling required to complete an IRP that's been
left in this state.
Hopefully, by now you already understand that the whole above paragraph
is full of nonsense.....
Anton Bassov
[begin quote]
Unless an IRP's dispatch routine completes the IRP (by calling
IoCompleteRequest) or passes the IRP on to lower drivers, it must call
IoMarkIrpPending with the IRP. Otherwise, the I/O manager attempts to
complete the IRP as soon as the dispatch routine returns control.
[end quote]
BubbaGump wrote:
On 20 Nov 2006 16:45:55 -0800, soviet_bloke@xxxxxxxxxxx wrote:
The original IRP only needs to be marked pending if it will be
completed in a different thread context from its dispatch routine,
which will only happen if the completion routine of the subsidiary IRP
can run after the dispatch routine returns, which will only happen if
IoCallDriver for the subsidiary IRP returns STATUS_PENDING.
The answer, again, can be easily found on MSDN.... This is what
IoMarkIrpPending() documentation says on the subject:
[begin quote]
Unless an IRP's dispatch routine completes the IRP (by calling
IoCompleteRequest) or passes the IRP on to lower drivers, it must call
IoMarkIrpPending with the IRP. Otherwise, the I/O manager attempts to
complete the IRP as soon as the dispatch routine returns control.
[end quote]
As you can see, if IoCallDriver for the subsidiary IRP returns
STATUS_PENDING in your situation, BSOD is guaranteed.....
Once you haven't called IoMarkIrpPending() with the original IRP from
your Dispatch() routine, IO Manager will complete the original IRP
right after your Dispatch() routine returns.
When subsidiary IRP gets completed at same later point, your
IoCompletionRoutine() will get called, and this routine accesses the
original IRP (i.e. the one that has already been completed by IO
Manager). BANG!!!!!!!!
Anton Bassov
Again I receive an arrogant, foolish, surface-level answer that
results from too much repetition of high-level conclusions and not
enough understanding of the underlying rules that create those
conclusions. This is how religions get started. Focusing on deeper
understanding is useful because it makes old conclusions easier to
remember and new conclusions easier to create.
Anyway, a single statement in the documentation cannot be used to gain
full understanding. The documentation also states that "If a driver
sets an IoCompletion routine for an IRP and then passes the IRP down
to a lower driver, the IoCompletion routine should check the
IRP->PendingReturned flag. If the flag is set, the IoCompletion
routine must call IoMarkIrpPending with the IRP." This implies that
IoMarkIrpPending would not have been called in the dispatch routine
(as the statement you quoted unfortunately says in unclear terms),
since there's no need for a single driver to call IoMarkIrpPending
twice for the same IRP.
If IoCallDriver for the subsidiary IRP returns STATUS_PENDING (and as
I said I then return that from my dispatch routine as well), the I/O
manager will not attempt to complete the IRP as soon as the dispatch
routine returns control. It can't. It doesn't have the
success/failure status for the IRP yet. It has to hold off until the
IRP is completed, and before that happens my completion routine will
be called and in turn call IoMarkIrpPending so that when the
completion process finally reaches back up to the I/O manager it will
know the IRP was not completed in the original thread context.
IoMarkIrpPending is not what controls whether the I/O manager will
attempt to complete the IRP as soon as the dispatch routine returns.
STATUS_PENDING is what does this. STATUS_PENDING informs the I/O
manager the IRP won't be completed for a while and possibly not in the
original thread context. IoMarkIrpPending informs IoCompleteRequest
to do the special handling required to complete an IRP that's been
left in this state.
When appropriate, IoMarkIrpPending can be called any time before an
IRP reaches its final stage of completion in the I/O manager. It
doesn't have to be called in a dispatch routine.
.
- References:
- Re: PendingReturned and a subsidiary IRP
- From: soviet_bloke
- Re: PendingReturned and a subsidiary IRP
- Prev by Date: Re: Don't receive IRP_MJ_CREATE on a CreateFile
- Next by Date: URL filter and URL encoding problem
- Previous by thread: Re: PendingReturned and a subsidiary IRP
- Next by thread: Re: PendingReturned and a subsidiary IRP
- Index(es):
Relevant Pages
|