File Operations inside the MessageNotifyCallback

I use the Filter Manager MessageNotifyCallback to communicate between user-mode and my filter.

On certain messages I want to call FltCreateFile(), FltReadFile() and FltWriteFile().

FltCreateFile takes an optional filter instance. However FltReadFile and FltWriteFile required the filter instance.

My question is how do I find the instance? Lets say my filter is not attached to some volumes, does that mean I can’t call FltWriteFile on that volume (since instance is a required arg for FltWriteFile)? If this is by design, what is the suggested approach (use FltCreateFile and ZwWriteFile instead …)?

Thank you!!

Hi!

FltCreateFile takes an optional filter instance. However FltReadFile and
FltWriteFile required the filter instance.

My question is how do I find the instance? Lets say my filter is not
attached to some volumes, does that mean I can’t call FltWriteFile on that
volume (since instance is a required arg for FltWriteFile)? If this is by
design, what is the suggested approach (use FltCreateFile and ZwWriteFile
instead …)?

If you are not attached to the volumes, you can simply use ZwCreateFile/
FltCreateFile and ZwWriteFile. Using FltCreateFile in this case will not
give you any advantage because the call will go to top of the stack (since
you are not specifying an instance). However, since you are NOT in the stack
so you should not worry about the call being sent to top of the stack. :slight_smile:

Regards,
Ayush Gupta
http://www.linkedin.com/in/guptaayush

Thanks Ayush,

If I use ZwCreateFile and ZwWriteFile and there is an instance on that volume, then I will see the Create and Write request in my callbacks.

FLTFL_CALLBACK_DATA_FS_FILTER_OPERATION will not be set in this case.

Do you know how can I filter them out in my callbacks?

If I use ZwCreateFile and ZwWriteFile and there is an instance on that
volume, then I will see the Create and Write request in my callbacks.

FLTFL_CALLBACK_DATA_FS_FILTER_OPERATION will not be set in this case.

Do you know how can I filter them out in my callbacks?

[Ayush Gupta] If you have an instance on that volume then simply use
FltCreateFile with the instance parameter. :slight_smile:
I did not get your question on FLTFL_CALLBACK_DATA_FS_FILTER_OPERATION.

Regards,
Ayush Gupta
http://www.linkedin.com/in/guptaayush

>>On certain messages I want to call FltCreateFile(), FltReadFile() and FltWriteFile(). FltCreateFile takes an optional filter instance. However FltReadFile and FltWriteFile required the filter instance.

Read http://www.osronline.com/showThread.cfm?link=154376 for something similar, and this is what Alex Carp state:

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.

>If I use ZwCreateFile and ZwWriteFile and there is an instance on that volume, then I will see the Create and Write request in my callbacks.

from WDK ,

MessageNotifyCallback
Pointer to a caller-supplied callback routine. The Filter Manager calls this routine, at IRQL = PASSIVE_LEVEL, whenever a user-mode application calls FilterSendMessage to send a message to the minifilter driver through the client port.

So this callback will not at all get called by FltMgr if you call zwwrite or zwcreate etc.

It can only happen if your driver is on stack and your driver architecture is forcing this.

Thanks
Aditya

Thanks all!

Aditya, I don’t understand how did you come up with this conclusion:

MessageNotifyCallback
Pointer to a caller-supplied callback routine. The Filter Manager calls this
routine, at IRQL = PASSIVE_LEVEL, whenever a user-mode application calls
FilterSendMessage to send a message to the minifilter driver through the client
port.

So this callback will not at all get called by FltMgr if you call zwwrite or
zwcreate etc. "

Why the Pre/PostCreate and Pre/PostWrite callback won’t get called if you use ZwCreateFile or ZwWriteFile? (or are you saying something else here)

I will double check again but I am 99.9% sure the requests from ZwCreate/Write pass through my filter instance callbacks (if it happens to be attached to that volume).

What I want is to: 1. do file IO in the MessageNotifyCallback 2. filter out this IO from my callbacks

>>Why the Pre/PostCreate and Pre/PostWrite callback won’t get called if you use ZwCreateFile or ZwWriteFile? (or are you saying something else here)

Indeed I was saying something else, :slight_smile:
I meant that your messagenotify callback will not get called, if you call zwcreatefile and zwwritefile. obviously if you are on stack, your pre_irp handler will get the call.

>What I want is to: 1. do file IO in the MessageNotifyCallback 2. filter out this IO from my callbacks?

In the link I posted, I suggested a way to achieve this but Alex told me that this is not good.

Aditya

The OP doesn’t make it clear whether they want to ignore the IO from their callbacks but still send the IO to the top of the stack or or only show the IO below their level. This is a very important decision that can impact the security of the system so give it some thought.

Please note that I’m only talking about the specific case of issuing IO (the Create and all other IO) from the MessageNotifyCallback routine. If you issue IO to a volume stack where you don’t have an instance you must send it to the top of the stack anyway (but this should not be a problem at all there is no instance of yours to see it).

First case: you want everybody on the stack to see the IO but you want your minifilter to KNOW it is your IO and that it should just let it through…

  1. use FltCreateFileEx with an EA (or FltCreateFileEx2 with an ECP if you only care about Vista+) and DO NOT pass in an instance (ZwCreateFile + ObReferenceObjectByHandle will work as well but I would use FltCreateFileEx just because I get the FILE_OBJECT back). This will send the create to the top of the stack. When the create gets to your instance, your minifilter will see the EA and know it can ignore the create. Then in the post-create callback you should set a StreamHandle context on the FILE_OBJECT.
  2. Use the handle you get from the create with Zw… functions. This will send all IO to the top of the stack so everyone can see it and when you get it in your minifilter you can check for the StreamHandle context and figure out this is one of your files and that you should just ignore it.

Second case: you want only the minifilters below your instance to see the IO. Your instance will not see the Create or any IO on it.

  1. you MUST use FltCreateFile with your instance. If you don’t have an instance, pass in NULL. This tells filter manager to only show the CREATE to minifilters below that instance.
  2. Use the handle you get from the create with Zw… functions. IO manager in conjunction with filter manager will make sure that IO is only shown to the minifilters below that instance.

Does this make sense ?

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

> 1. you MUST use FltCreateFile with your instance. If you

don’t have an instance, pass in NULL. This tells filter
manager to only show the CREATE to minifilters below that instance.

I thought giving FltCreateFile a NULL instance would send it to the top
of the stack:

“This parameter is optional and can be NULL. If this parameter is NULL,
the request is sent to the device object at the top of the file system
driver stack for the volume.”

Am I confused or is there some additional trickery you mentioned that I
missed?

~Eric

Exactly, it would send it to the top. However, not having an instance means the minifilter is not attached to that volume and I already specifically called out the fact that everything should be sent to the top of the stack in that case.

I should have probably qualified everything a little better. Please read that statement like this:

  1. you MUST use FltCreateFile with your instance. If you don’t have an instance for the volume you want to issue the IO to, pass in NULL, which will send it to the top of the stack. This tells filter manager to only show the CREATE to minifilters below that instance (in the case where the instance was specified) and to all filters in the case where the instance was NULL.

Based on the (rather incomplete) description of the problem in the OP and subsequent posts I assumed there were at least 2 volumes on the system (let’s call them Volume1 and Volume2), and the minifilter was attached to only one of them (Volume1). So in that case the routine for MessageNotifyCallback would do this:

  1. Get the volume on which the file to open resides.
  2. Get the instance for that volume (it would get an instance for Volume1 and NULL for Volume2)
  3. Call FltCreateFile(…, instance, …)

So… no trickery, just trying to cover all the cases.

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

ok very good! This is exactly what I was looking for:

Second case: you want only the minifilters below your instance to see the IO.
Your instance will not see the Create or any IO on it.

  1. you MUST use FltCreateFile with your instance. If you don’t have an instance,
    pass in NULL. This tells filter manager to only show the CREATE to minifilters
    below that instance.
  2. Use the handle you get from the create with Zw… functions. IO manager in
    conjunction with filter manager will make sure that IO is only shown to the
    minifilters below that instance.

Especially that using the handle from FltCreateFile with ZwRead/ZwWrite will ensure the instance used with FltCreateFile will not see the ZwRead/ZwWrite IO on that handle.

As a workaround I changed my filter to ignore all IO from my control process but now I will revert that and go with this instead.

Thanks for the help!