KMDF, where does handle specific data go?

I want to make sure that I understand this, so if anyone can point me to a sample that shows this simply I would really appreciate it. The device
context contains information for each device, correct? But where is information for specific handles stored? For example, let’s say I had a device
driver that had a stream of data, and two processes opened the device. If process A read 10 bytes at a time and process B read 20, where does the
driver store pointers for where each process is reading? Does this question make sense at all? When is OSR coming to SoCal with the WDF class?
Thanks,
Michael

the context data in the WDFDEVICE is global for all consumers of the device (ie all apps who have an open handle to it). if you want per handle context data (like an index into a ring buffer stored on the WDFDEVICE context), store that data in the WDFFILEOBJECT associated with that consumer.

d

Thanks very much d!

I did a grep on the Windows DDK samples and only see a reference to WDFFILEOBJECT in toaster and general/ioctl. Any idea why so few? Is this a
strange thing to do? (Which makes me wonder if I am doing something wrong).

Thanks,
Michael

On Mon, 20 Dec 2010 16:09:19 -0500 (EST), xxxxx@Microsoft.com wrote:

the context data in the WDFDEVICE is global for all consumers of the device (ie all apps who have an open handle to it). if you want per handle context data (like an index into a ring buffer stored on the WDFDEVICE context), store that data in the WDFFILEOBJECT associated with that consumer.

d

Even before KMDF most drivers had little need for a per handle context
data. The WDFFILEOBJECT does do the job, I used it in a major project
last year. Be aware if you are developing a filter driver and need to
send “new requests” down the stack for a given WDFFILEOHJECT, there is
no way to do it, this missing piece of functionality bit me in the ass
pretty good.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Michael Wade” wrote in message
news:xxxxx@ntdev:

> Thanks very much d!
>
> I did a grep on the Windows DDK samples and only see a reference to WDFFILEOBJECT in toaster and general/ioctl. Any idea why so few? Is this a
> strange thing to do? (Which makes me wonder if I am doing something wrong).
>
> Thanks,
> Michael
>
>
> On Mon, 20 Dec 2010 16:09:19 -0500 (EST), xxxxx@Microsoft.com wrote:
>
> >the context data in the WDFDEVICE is global for all consumers of the device (ie all apps who have an open handle to it). if you want per handle context data (like an index into a ring buffer stored on the WDFDEVICE context), store that data in the WDFFILEOBJECT associated with that consumer.
> >
> >d

Don (& Doron),

Out of curiosity, is WdfRequestWdmFormatUsingStackLocation() not able to ‘set’ the PFILE_OBJECT in the IO_STACK_LOCATION and thus take a request allocated for the default I/O target and ‘add in’ the FileObject value to use going down stack?

I have not tried it but the comment below made me wonder why it may or may not be possible.

Cheers,
Dave Cattley

From: xxxxx@acm.org
Subject: Re:[ntdev] KMDF, where does handle specific data go?
Date: Mon, 20 Dec 2010 21:48:41 +0000
To: xxxxx@lists.osr.com

Even before KMDF most drivers had little need for a per handle context
data. The WDFFILEOBJECT does do the job, I used it in a major project
last year. Be aware if you are developing a filter driver and need to
send “new requests” down the stack for a given WDFFILEOHJECT, there is
no way to do it, this missing piece of functionality bit me in the ass
pretty good.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Michael Wade” wrote in message
> news:xxxxx@ntdev:
>
> > Thanks very much d!
> >
> > I did a grep on the Windows DDK samples and only see a reference to WDFFILEOBJECT in toaster and general/ioctl. Any idea why so few? Is this a
> > strange thing to do? (Which makes me wonder if I am doing something wrong).
> >
> > Thanks,
> > Michael
> >
> >
> > On Mon, 20 Dec 2010 16:09:19 -0500 (EST), xxxxx@Microsoft.com wrote:
> >
> > >the context data in the WDFDEVICE is global for all consumers of the device (ie all apps who have an open handle to it). if you want per handle context data (like an index into a ring buffer stored on the WDFDEVICE context), store that data in the WDFFILEOBJECT associated with that consumer.
> > >
> > >d
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

WdfRequestWdmFormatUsingStackLocation is basically a wrapper around IoCopyCurrentStackLocationToNext which does copy the PFILE_OBJECT.

Don, if you create a WDFIOTARGET in the EvtDeviceFileCreate callback and after calling WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE, set Params.TargetFileObject, the WDFIOTARGET will set the file object on newly created requests that you format and send through the io target

d

and Michael, IMHO, it is a common thing to do to keep track of per client in the file object. i don’t think the wdk sample content is a broad enough sampling set to show this type of pattern to make the conclusion that it is not common.

d

Dave,

In previous versions of KMDF the WdfRequestSend would wipe out the
file object. You can use Doron’s approach but if this is a simple
filter it means you have to have an IO target for anything you see which
is overhead. The particular case I remember is I received in the filter
an IOCTL X and wanted to satisfy it with two IOCTL’s to a lower driver
of Y and Z. It was a lot more work than I ever did for WDM, which is
exactly what KMDF was not supposed to be.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Dave Cattley” wrote in message news:xxxxx@ntdev:

> Don (& Doron),
>
> Out of curiosity, is WdfRequestWdmFormatUsingStackLocation() not able to ‘set’ the PFILE_OBJECT in the IO_STACK_LOCATION and thus take a request allocated for the default I/O target and ‘add in’ the FileObject value to use going down stack?
>
> I have not tried it but the comment below made me wonder why it may or may not be possible.
>
> Cheers,
> Dave Cattley
>
>
> > From: xxxxx@acm.org
> > Subject: Re:[ntdev] KMDF, where does handle specific data go?
> > Date: Mon, 20 Dec 2010 21:48:41 +0000
> > To: xxxxx@lists.osr.com
> >
> > Even before KMDF most drivers had little need for a per handle context
> > data. The WDFFILEOBJECT does do the job, I used it in a major project
> > last year. Be aware if you are developing a filter driver and need to
> > send “new requests” down the stack for a given WDFFILEOHJECT, there is
> > no way to do it, this missing piece of functionality bit me in the ass
> > pretty good.
> >
> >
> > Don Burn (MVP, Windows DKD)
> > Windows Filesystem and Driver Consulting
> > Website: http://www.windrvr.com
> > Blog: http://msmvps.com/blogs/WinDrvr
> >
> >
> >
> >
> > “Michael Wade” wrote in message
> > news:xxxxx@ntdev:
> >
> > > Thanks very much d!
> > >
> > > I did a grep on the Windows DDK samples and only see a reference to WDFFILEOBJECT in toaster and general/ioctl. Any idea why so few? Is this a
> > > strange thing to do? (Which makes me wonder if I am doing something wrong).
> > >
> > > Thanks,
> > > Michael
> > >
> > >
> > > On Mon, 20 Dec 2010 16:09:19 -0500 (EST), xxxxx@Microsoft.com wrote:
> > >
> > > >the context data in the WDFDEVICE is global for all consumers of the device (ie all apps who have an open handle to it). if you want per handle context data (like an index into a ring buffer stored on the WDFDEVICE context), store that data in the WDFFILEOBJECT associated with that consumer.
> > > >
> > > >d
> >
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > For our schedule of WDF, WDM, debugging and other seminars visit:
> > http://www.osr.com/seminars
> >
> > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

Again, thanks.

On Mon, 20 Dec 2010 18:38:06 -0500 (EST), xxxxx@Microsoft.com wrote:

and Michael, IMHO, it is a common thing to do to keep track of per client in the file object. i don’t think the wdk sample content is a broad enough sampling set to show this type of pattern to make the conclusion that it is not common.

d

I just want to make sure that I am using the right tools for the job here. Is there a better way to handle this kind of situation? I guess why I’m
asking is that I would think that it would be more prevalent. Like reading from files, etc. Is there a better way to handle things like that?

Thanks,
Michael

On Mon, 20 Dec 2010 21:48:41 +0000, “Don Burn” wrote:

>Even before KMDF most drivers had little need for a per handle context
>data. The WDFFILEOBJECT does do the job, I used it in a major project
>last year. Be aware if you are developing a filter driver and need to
>send “new requests” down the stack for a given WDFFILEOHJECT, there is
>no way to do it, this missing piece of functionality bit me in the ass
>pretty good.
>
>
>Don Burn (MVP, Windows DKD)
>Windows Filesystem and Driver Consulting
>Website: http://www.windrvr.com
>Blog: http://msmvps.com/blogs/WinDrvr
>
>
>
>
>“Michael Wade” wrote in message
>news:xxxxx@ntdev:
>
>> Thanks very much d!
>>
>> I did a grep on the Windows DDK samples and only see a reference to WDFFILEOBJECT in toaster and general/ioctl. Any idea why so few? Is this a
>> strange thing to do? (Which makes me wonder if I am doing something wrong).
>>
>> Thanks,
>> Michael
>>
>>
>> On Mon, 20 Dec 2010 16:09:19 -0500 (EST), xxxxx@Microsoft.com wrote:
>>
>> >the context data in the WDFDEVICE is global for all consumers of the device (ie all apps who have an open handle to it). if you want per handle context data (like an index into a ring buffer stored on the WDFDEVICE context), store that data in the WDFFILEOBJECT associated with that consumer.
>> >
>> >d
>

The Read and Write IRPs carry a deviceoffset field (which you can get using WdfRequestGetParameters), which is maintained by I/O manager, IIRC- particularly in the case of regular file IO. I’ve used them for this sort of thing, but not recently, so I’m unsure if there are any weird pitfalls to doing this I should be warning about. It is (again, IIRC) basically the “file pointer” concept used in the file API.

For your specific case, I believe that’s also a potentially workable approach. As for why that isn’t illustrated in samples, well my observation is that people writing drivers tend to a do a lot of IOCTLs and not a whole lot of flat-out read and write.

For per-handle WDF I/O you can use the WDFILEOBJECT context to hold
per-handle information. Define a structure loosely like this:

typedef struct _FILE_OBJECT_CONTEXT
{
WDFFILEOBJECT FileObject; // FileObject that owns this context

WDFQUEUE PendingReadQueue;

// Other Stuff…

}
FILE_OBJECT_CONTEXT, *PFILE_OBJECT_CONTEXT;

In your DeviceAdd:


// Specify the size of file object context
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
FILE_OBJECT_CONTEXT);

WdfDeviceInitSetFileObjectConfig(
DeviceInit,
&fileConfig,
&attributes
);

The parent is the Device Object.

Now whenever you are given a WDFFILEOBJECT you can fetch the
FILE_OBJECT_CONTEXT like this:


PFILE_OBJECT_CONTEXT fileContext;


fileContext = GetFileObjectContext(FileObject);

Of course GetFileObjectContext has to have been declared like this:

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FILE_OBJECT_CONTEXT,
GetFileObjectContext)

In your WDF FileCreate callback you must fetch PFILE_OBJECT_CONTEXT and
initialize it. One thing that I do is to stash the WFDFILEOBJECT in the
FILE_OBJECT_CONTEXT. This helps in some cases.

In my EXAMPLE structure the PendingReadQueue field is an WDFQUEUE created by
calling WdfIoQueueCreate when initializing PFILE_OBJECT_CONTEXT in
FileCreate. Parent is the FileObject. This is the queue that I use for
pending read requests. When read requests are passed to the driver’s default
queue forward them to this per-handle queue. Then dequeue when you need the
requests.

The PendingReadQueue can be for requests passed to FileRead if desired. In
my IRPs forwarded to PendingReadQueue are actually IoDeviceControl requests.
Works for pending any requests. You can also have multiple queues if needed.

In FileCleanup the pending reads can be purged by calling
WdfIoQueuePurgeSynchronously.

There are other features that I haven’t mentioned in detail. For example, I
create a WDFCOLLECTION that holds FileObjects because I may need to examine
all of the per-handle data at some points. Of course various locks are
needed according to your requirements.

This isn’t a complete “cookbook”, but for sure you can use WDF very
effectively to implement per-handle data.

And “The Devil is in the details!”.

(Of course your third or fourth WDF driver will be a lot “cleaner” and
simpler than your first…).

I hope I haven’t confused you or given irrelevant information. I have just
gone through this exercise (per-handle WDF driver…) and was pleased with
the results.

Good luck and Merry Christmas!

Thomas F. Divine
http://www.pcausa.com


From: “Bob Kjelgaard”
Sent: Monday, December 20, 2010 9:27 PM
To: “Windows System Software Devs Interest List”
Subject: RE: Re:[ntdev] KMDF, where does handle specific data go?

> The Read and Write IRPs carry a deviceoffset field (which you can get
> using WdfRequestGetParameters), which is maintained by I/O manager, IIRC-
> particularly in the case of regular file IO. I’ve used them for this sort
> of thing, but not recently, so I’m unsure if there are any weird pitfalls
> to doing this I should be warning about. It is (again, IIRC) basically
> the “file pointer” concept used in the file API.
>
> For your specific case, I believe that’s also a potentially workable
> approach. As for why that isn’t illustrated in samples, well my
> observation is that people writing drivers tend to a do a lot of IOCTLs
> and not a whole lot of flat-out read and write.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

> driver that had a stream of data, and two processes opened the device. If process A read 10 bytes

Usually, such streams just plain cannot be opened twice.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

I agree with (some of what) Don said: It’s not unheard of for drivers to track certain things on a per-open instance basis, but it’s relatively rare.

To be specific and clear, I’m going to rephrase that to “If some thread reads 10 bytes of data using handle A, and some other thread reads 20 bytes of data using handle B, where does the driver store the pointers for the current location for each handle?”

If that’s not what you intended in your question, please correct me.

And the answer is… the driver DOESN’T store the byte offset. The I/O Manager does it for you.

If the user opens the device for synchronous I/O and does ReadFile for 20 bytes, without specifically specifying an offset from which to start readin, the I/O Manager keeps the pointer and puts it into the byteOffset field of the read request.

Likewise for Write.

Sorry… the closest we usually get is Silicon Valley and we were there in the past few months, IIRC; SOMEbody (Dan) should really think about us returning to LA or San Diego or … gosh … someplace nice an warm like Phoenix. Why do we never teach in Phoenix?? You should write to Dan at OSR dot com to advocate for a seminar near you :slight_smile:

Peter
OSR

I think I see, but just to make sure, if we make the example two handles opened to read a file, say, then the driver does not need to keep track of
where each handle’s file position is, that is taken care of by the I/O manager? So the driver just gets a read request with a byte count and byte
offset, then, right? These are located in the IRP as Parameters.Read.Length and Parameters.Read.ByteOffset, I think.

I’m sending an email right now for a San Diego WDF class. C’mon, it’s nice, warm, got fun things to do for families during the day…

Thanks,
Michael

On Tue, 21 Dec 2010 11:59:29 -0500 (EST), xxxxx@osr.com wrote:

I agree with (some of what) Don said: It’s not unheard of for drivers to track certain things on a per-open instance basis, but it’s relatively rare.

To be specific and clear, I’m going to rephrase that to “If some thread reads 10 bytes of data using handle A, and some other thread reads 20 bytes of data using handle B, where does the driver store the pointers for the current location for each handle?”

If that’s not what you intended in your question, please correct me.

And the answer is… the driver DOESN’T store the byte offset. The I/O Manager does it for you.

If the user opens the device for synchronous I/O and does ReadFile for 20 bytes, without specifically specifying an offset from which to start readin, the I/O Manager keeps the pointer and puts it into the byteOffset field of the read request.

Likewise for Write.

Sorry… the closest we usually get is Silicon Valley and we were there in the past few months, IIRC; SOMEbody (Dan) should really think about us returning to LA or San Diego or … gosh … someplace nice an warm like Phoenix. Why do we never teach in Phoenix?? You should write to Dan at OSR dot com to advocate for a seminar near you :slight_smile:

Peter
OSR

Length: Correct. Actually, the byte offset is maintained by the I/O Manager in the FILE_OBJECT.

For byte offset, see http://msdn.microsoft.com/en-us/library/ff549327(v=vs.85).aspx, where it says:


IrpSp->Parameters.Read.ByteOffset

Pointer to a LARGE_INTEGER variable that specifies the starting byte offset within the file of the data to be read.

Under certain circumstances, this parameter might validly contain a NULL or negative value. For example, if the file object was opened for synchronous I/O, and one of the following conditions is true, this indicates that the current file position should be used instead of an explicit file offset value:

IrpSp->Parameters.Read.ByteOffset.QuadPart == 0

IrpSp->Parameters.Read.ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION and IrpSp->Parameters.Read.ByteOffset.HighPart == -1.

The idea is to provide a way where you can differentiate between the USER supplying the byte offset and the SYSTEM supplying you the current offset for synchronous reads.

In the case of the latter, you get the byte offset that’s automagically maintained for you from fileObject->CurrentByteOffset

Hope that helps,

Peter
OSR