Clarification on WdfIoQueueFindRequest

I’ve got a manual queue in my driver that only receives device io requests, all with the same ioctl code. Each one has an “id” that is supplied in the input buffer. These are completed at a later time.

When the event occurs later, I know the id of the requests to complete. However, I’m not sure of the best way to do this.

The paper “I/O Flow and Dispatching in WDF Drivers” says: “[WdfIoQueueFindRequest] takes a reference on the request and returns a handle to the request but does not remove the request from the queue. The driver can inspect the request to determine whether it is the one that the driver was seeking.” This implies that the returned request object handle can be used, but the MSDN docs state that it can only be passed to WdfIoQueueFindRequest, WdfIoQueueRetrieveFoundRequest, or WdfObjectDereference.

Following the MSDN docs strictly forces me to empty this entire queue every time any of these requests are going to complete. I’ll have to retrieve each one, inspect its input buffer, and put it back if it doesn’t match.

So, I was wondering if anyone knows if it’s ok to access the request’s memory buffers or context without retrieving it. (I’m not sure if accessing context space counts as “using” the request object). The parameters structure does contain a pointer to the buffer, but is this off-limits?

Thanks,
-Steve

As long as you have a valid reference, the object context can be used.
I would suggest that you store the id stored in the input buffer in the
request context and then use the cached value in the context w/out
touching the buffers (which you cannot do until you successfully call
WdfIoQueueRetrieveFoundRequest)

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Sunday, June 03, 2007 1:05 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Clarification on WdfIoQueueFindRequest

I’ve got a manual queue in my driver that only receives device io
requests, all with the same ioctl code. Each one has an “id” that is
supplied in the input buffer. These are completed at a later time.

When the event occurs later, I know the id of the requests to complete.
However, I’m not sure of the best way to do this.

The paper “I/O Flow and Dispatching in WDF Drivers” says:
“[WdfIoQueueFindRequest] takes a reference on the request and returns a
handle to the request but does not remove the request from the queue.
The driver can inspect the request to determine whether it is the one
that the driver was seeking.” This implies that the returned request
object handle can be used, but the MSDN docs state that it can only be
passed to WdfIoQueueFindRequest, WdfIoQueueRetrieveFoundRequest, or
WdfObjectDereference.

Following the MSDN docs strictly forces me to empty this entire queue
every time any of these requests are going to complete. I’ll have to
retrieve each one, inspect its input buffer, and put it back if it
doesn’t match.

So, I was wondering if anyone knows if it’s ok to access the request’s
memory buffers or context without retrieving it. (I’m not sure if
accessing context space counts as “using” the request object). The
parameters structure does contain a pointer to the buffer, but is this
off-limits?

Thanks,
-Steve


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

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

xxxxx@hotmail.com wrote:

I’ve got a manual queue in my driver that only receives device io requests, all with the same ioctl code. Each one has an “id” that is supplied in the input buffer. These are completed at a later time.

When the event occurs later, I know the id of the requests to complete. However, I’m not sure of the best way to do this.

The paper “I/O Flow and Dispatching in WDF Drivers” says: “[WdfIoQueueFindRequest] takes a reference on the request and returns a handle to the request but does not remove the request from the queue. The driver can inspect the request to determine whether it is the one that the driver was seeking.” This implies that the returned request object handle can be used, but the MSDN docs state that it can only be passed to WdfIoQueueFindRequest, WdfIoQueueRetrieveFoundRequest, or WdfObjectDereference.

Following the MSDN docs strictly forces me to empty this entire queue every time any of these requests are going to complete. I’ll have to retrieve each one, inspect its input buffer, and put it back if it doesn’t match.

The documentation for WdfIoQueueFindRequest is not entirely consistent.
“Parameters” is documented as an OUT parameter that receives the
parameters from the found IRP, but the description implies that the
routine will search for an IRP that “matches” the Parameters. If it is
actually an IN OUT parameter, then you could shove the “code” into one
of the Arg fields before queueing the IRP, and then search for that.

However, if it really only looks for a match on FileObject, then that
won’t work. You could keep your own linked list (using the LIST_ENTRY
macros) mapping ID to WDFREQUEST; as long as you added an
EvtRequestCancel handler to the request, you could clean up your list of
a request did get canceled.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Took me a while (habitual blind spots you tend to develop reading these over time), but I found the doc error you described.

The Parameters parameter is output only, they are not used to locate the request. I’ll file a documentation bug for that (if Richard hasn’t beaten me to it :)- thanks.

On your other problem- you might be able to keep a collection matching IDs to WDFREQUESTS about- for instance in the queue object’s context. Keeping that updated as requests get canceled would mean adding something to the “EvtIoCanceledOnQueue” callback. Sounds like the completion end isn’t hard to figure out. At the moment, I don’t see any bad effects from doing that (sorry I’m not so definite- advice is interactive, and finding optimal solutions tends to be a batch process for me).

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, June 04, 2007 10:52 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Clarification on WdfIoQueueFindRequest

xxxxx@hotmail.com wrote:

I’ve got a manual queue in my driver that only receives device io requests, all with the same ioctl code. Each one has an “id” that is supplied in the input buffer. These are completed at a later time.

When the event occurs later, I know the id of the requests to complete. However, I’m not sure of the best way to do this.

The paper “I/O Flow and Dispatching in WDF Drivers” says: “[WdfIoQueueFindRequest] takes a reference on the request and returns a handle to the request but does not remove the request from the queue. The driver can inspect the request to determine whether it is the one that the driver was seeking.” This implies that the returned request object handle can be used, but the MSDN docs state that it can only be passed to WdfIoQueueFindRequest, WdfIoQueueRetrieveFoundRequest, or WdfObjectDereference.

Following the MSDN docs strictly forces me to empty this entire queue every time any of these requests are going to complete. I’ll have to retrieve each one, inspect its input buffer, and put it back if it doesn’t match.

The documentation for WdfIoQueueFindRequest is not entirely consistent.
“Parameters” is documented as an OUT parameter that receives the
parameters from the found IRP, but the description implies that the
routine will search for an IRP that “matches” the Parameters. If it is
actually an IN OUT parameter, then you could shove the “code” into one
of the Arg fields before queueing the IRP, and then search for that.

However, if it really only looks for a match on FileObject, then that
won’t work. You could keep your own linked list (using the LIST_ENTRY
macros) mapping ID to WDFREQUEST; as long as you added an
EvtRequestCancel handler to the request, you could clean up your list of
a request did get canceled.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


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

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

>>At the moment, I don’t see any bad effects from doing that<<

Bad choice of words- I’m sure this is OK as a way to do it. I just dislike solutions with double-entry bookkeeping- they’re a bit fragile and harder to maintain. If there’s a more direct way, it sure isn’t obvious enough for me to see it…

(Proving my original point about being something of a half-baked dunderhead when it comes to KMDF advice…)

IIRC, WDFCOLLECTIONS do have some PASSIVE_LEVEL IRQL restrictions that might make them unsuitable. If you can’t use them, you could still get some of the object management benefits by using WDFMEMORY or perhaps even raw WDFOBJECT contexts and squirreling the WDFHANDLE away in the object context along with the LIST_ENTRY so you can delete them when you’re done

>>IIRC, WDFCOLLECTIONS do have some PASSIVE_LEVEL IRQL restrictions that might make them unsuitable. <<

Sorry- I didn’t remember correctly- I once had a WDFCOLLECTION of WDFSTRINGs in my IoTarget test drivers (device interfaces I could pick at random when stress testing) and THOSE had the IRQL restrictions I was so dimly remembering.

Maybe I’ll start my day over again, and never try to do two things at once :).