FltReadFile

The file object now contains a “hidden field” known as the file object
extension. When you use IoCreateFileSpecifyDeviceObjectHint, the “hint”
device is stored in the file object extension (it is not the ONLY thing
in the FOE, it is just ONE thing in the FOE. The
IO_IGNORE_SHARE_ACCESS_CHECK behavior is also stored there, for
example.)

There are a number of scenarios in which this becomes an issue:

(1) Someone does a direct IRP call (build and IRP_MJ_READ and send it
with your file object.) It goes where it is sent, regardless of what
the FOE says

(2) A filter or FSD somewhere in the stack uses one of the stream
file object operations (IoCreateStreamFileObject, etc.) Such file
objects are not currently created with a file object extension (of
course, this behavior is subject to change.) Any I/O against those file
objects will go to the top of the stack (because they don’t have the
file object extension.)

(3) Someone below you maps/opens the file again to perform some other
operation. This can (and does) cause potential re-entrancy. While the
“hint” model, and the filter manager’s attempt to eliminate re-entrant
behavior helps, it’s surprisingly easy for someone to introduce
re-entrancy into the system.

We’ve seen some amazing examples of unexpected re-entrancy. It happens
on a regular basis. It isn’t necessarily deliberate and eliminating it
will provide one with considerable job security for the forseeable
future.

Tony

OSR

Well,

There is documentation on this. You can find it here: http://download.microsoft.com/download/f/0/5/f05a42ce-575b-4c60-82d6-208d3754b2d6/IoGeneration.ppt
There are a couple more documents that I very strongly urge people that are developing minifilters to read (or re-read), on this page:
http://www.microsoft.com/whdc/driver/filterdrv/default.mspx (this link should not change, but if it does, search for “File System Filter Drivers”). This also points to the document above.

Now, assuming you read those, the following should make sense (and of course, there are exceptions to every rule, governed by other rules and their exceptions and so on). Also, I hope the formatting will work:

  1. AVOID sending IO to the top of the stack at all costs. This can lead to black holes appear, tears in the fabric of the universe, global warming, deadlocks and so on… (see this for a reference http://www.amazon.com/Scary-Book-Horrible-Things-Kids/dp/159258148X; though it’s not complete, it doesn’t mention deadlocks)

  2. If you are in the IO path (i.e. a minifilter callback) you should use Flt… functions.

  3. If you are NOT in the IO path (i.e. in a different callback ?) you should use Zw… functions.

  4. If you want to call a Flt… function that requires an instance and you just don’t have one, then you are probably not supposed to call that function. Look for either an Flt… function that doesn’t require and instance or use a Zw function, just don’t try to ‘forge’ an instance.

  5. You can mix’n’match Flt… and Zw… functions. It matters more where you are in the system (i.e. callback on the IO path vs. other system callbacks) than calling Flt… functions only on handles from with FltCreate and Zw… functions on other functions.

  6. If you open a handle with FltCreateFile and then use it with Zw… functions, those IOs will be targeted properly (i.e. at the right instance in filter manager). But please, use Zw… functions only when appropriate (see the points above).

  7. If you have a FILE_OBJECT (from a file opened by someone else, even the user) and call Flt… functions on it, the IOs will also be targeted properly.

  8. If you are in the IO stack (minifilter callback) and call a Zw… function (you would ONLY do that if there is no Flt… function, right?) on a FILE_OBJECT you didn’t open, that IO WILL be seen by people above your instance, with all the bad things that can follow from that (see point 0). So if you’ve read the book above and you don’t want to send IO to the top of the stack then it’s time to roll your own CALLBACK_DATA (IRPs are soooo last season). This is pretty simple:

  9. Call FltAllocateCallbackData()

  10. Populate it like you would an IRP (Data->Iopb->MajorFunction = … , Data->Iopb->MinorFunction = …, Data->Iopb->Parameters… = … , Data->Iopb->OperationFlags = SL_… and so on

  11. Call FltPerformSynchronousIo (or FltPerformAsynchronousIo, you know the rules)

  12. Call FltFreeCallbackData. (if you used FltPerformAsynchronousIo, ideally you should wait for the IO to complete before that :)).

I hope this makes sense.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.

> But mini filter do not create a device object, so if there is a mini filter below my driver how

IoCreateFileSpecifyDeviceObjectHint can be used to pass a request to the driver. Or is it like fltmgr
initialized fileobject DO field to fltmgr DO, and than taking decision based on what I mentioned.

I think something like this. FltMgr surely creates a device object for each “altitude group” of minifilters which have no legacy filters in between them.


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

>>While the “hint” model, and the filter manager’s attempt to eliminate re-entrant behavior helps, it’s surprisingly easy for someone to introduce re-entrancy into the system.

This is what exactly I was thinking but was not able to reach the conclusion point.

>FltMgr surely creates a device object for each “altitude group” of minifilters which have no legacy filters in between them

Alright, now i understand what all those unnamed fltmgr’s device objects are for.

>This can lead to black holes appear, tears in the fabric of the universe, global warming, deadlocks and so on…

Amazed! I never thought like this, i mean i thought for re-rentertency but never relate that with global warming.

Thanks,
Aditya