Problem about Directory Change Notification

Hi All,

I have a FS filter driver which compresses files. So from explorer you can right click on a file and say compresses (explorer have our shell extension loaded and used to display the menu).

Compression process has following steps?
? Open the file to be compressed (Let?s call it as original file).
? Create a temporary file that will contain the compressed data.
? Read the original file, compress the data and write to temporary file.
? Delete the original file.
? Copy the temporary file to original file with .cmp extension (So if original file is a.txt, new file will be a.txt.cmp). And then delete temporary file.
? Now though actual file is a.txt.cmp it is exposed as a.txt to application layer.
? This is purposefully done so in absence of our software, user can see .cmp extension and come to know that this is compressed file.

Now the problem here is that, when I delete original file it gets disappeared from explorer and never reappear until explorer is explicitly refreshed with F5.

I am not sure handling IRP_MN_NOTIFY_CHANGE_DIRECTORY will help, or I need to call FsRtlNotifyFullChangeDirectory or FsRtlNotifyFilterReportChange.

So please guide me how to tackle this problem.

Thanks & regards,
Amit.

When you remove the file, the File system is going to send the FILE_ACTION_REMOVED notification.

So try FILE_ACTION_ADDED with FsRtlNotifyFullReportChange, (or you can try the other two you mentioned) after deleting the file.

On 02/27/2013 02:19 AM, xxxxx@yahoo.com wrote:

> ? Copy the temporary file to original file with .cmp extension (So if original file is a.txt, new file will be a.txt.cmp). And then delete temporary file.
> ? Now though actual file is a.txt.cmp it is exposed as a.txt to application layer.
> ? This is purposefully done so in absence of our software, user can see .cmp extension and come to know that this is compressed file.
>
> Now the problem here is that, when I delete original file it gets disappeared from explorer and never reappear until explorer is explicitly refreshed with F5.
>
> I am not sure handling IRP_MN_NOTIFY_CHANGE_DIRECTORY will help…

In Vista+ explorer requires relatively accurate change notification
reporting. Here the filesystem will report events on foo.txt.cmp, but
when explorer tries to access that file it will fail. I think what you
need to do is manipulate the existing change notifications to ensure
these report foo.txt.

You might want to check my theory with procmon - see if explorer is
opening foo.txt.cmp and that it’s failing.

- M

Hi Adnan & Malcolm Smith,

Thanks for your prompt reply.

>In Vista+ explorer requires relatively accurate change notification
>reporting. Here the filesystem will report events on foo.txt.cmp, but
>when explorer tries to access that file it will fail. I think what you
>need to do is manipulate the existing change notifications to ensure
>these report foo.txt.

Yes, your theory is correct.
So according to you I need to handle IRP_MN_NOTIFY_CHANGE_DIRECTORY and in it’s completion I require to manipulate the result.

But I just want to avoid the manipulation. I just want to trigger the notification explicitly so that explorer will add it in the list. I am not sure that will be a good way or not, so guide me on that.

>So try FILE_ACTION_ADDED with FsRtlNotifyFullReportChange, (or you can try the
>other two you mentioned) after deleting the file.

So is there any article or sample code that demos how to do it? Actually the parameters to FsRtlNotifyFullReportChange such as Notifylist are unknown to me and MSDN document is bit confusing to me.

How can I get Notifylist?

Thanks & Regards,
Amit.

Please refer to WDK sample src/filesys/fastfat. Search NotifySync, and you can find how it is initialized and used.

Hi Adnan,

just gone through that code. So here is my understanding…

Notifylist and NotifySync are maintained by per volume by File System Driver and they are kept in private datastructure by that driver. So as mine is a filter driver I don’t have access to them.

So if I want to call FsRtlNotifyFullReportChange I need to mintain my own Notifylist and NotifySync. If I am wrong can you tell me how to get access to Notifylist and NotifySync maintained by file system?

Thnaks & Regards,
Amit.

No, you can’t access the File System Notifylist and NotifySync.

Obviously, you have to notify the upper layer, regarding the change you have done.

If you can see what your filter driver is doing, you can clearly figure out what you have to do.
For each action on a File System, the file system will report/notify it to upper layer.

Now your filter create a file, and delete a file. Filter is notified, and it goes to the upper layer (explorer.exe).

(I don’t know if there is a way to catch that notification and discard it)
But the easy solution is to, send a notification to upper layer, that the file xyz.txt is created again. Hence you have to maintain your own data structure for that, and once you delete the file, the file system will send notification, you create a file, file system will send notification, just at that time, notify the upper layer that you created the same file again (or find a way to discard the delete notification)

On 02/27/2013 08:15 PM, xxxxx@yahoo.com wrote:

Yes, your theory is correct.
So according to you I need to handle IRP_MN_NOTIFY_CHANGE_DIRECTORY and in it’s completion I require to manipulate the result.

But I just want to avoid the manipulation…
I don’t understand. It sounds like you’re trying to avoid doing
something simple because you’d rather do something hard.

Change notifications work by having explorer send an irp to the file
system. The file system retains that irp, returns STATUS_PENDING, and
completes it with information when a change occurs. A filter can’t just
notify explorer - it needs to take that irp that it no longer owns, put
something in it, and complete it.

So the filter could take over all directory change notifications to the
volume, then all of explorer’s irps will be owned by the filter, then it
can issue a change notification for any purpose at any time.
Unfortunately it would also need to be monitoring the underlying file
system for changes in order to know what’s changing. That seems like a
lot of work to me.

You could avoid the manipulation by creating foo.txt on the underlying
volume, but it seems like you’re trying to avoid that which is why
foo.txt.cmp exists to begin with.

After all the work you’d need to have done to make a working compression
filter, this seems like the smallest and simplest piece, it just needs
to be written.

Newer WDKs should have an Nc sample which shows this process in a
minifilter. Your situation is in a lot of ways much simpler since
you’re only concerned with files and not directories (don’t need to
merge two data sources), and whenever substitutions are needed the
result is smaller than the original data (since the extension is being
removed) so there’s no need to buffer changes. Nor is there anything to
suppress completely, so there’s no need to reissue requests. So a huge
amount of code could be removed from that sample - all the hard parts.
Google/Bing ncdirnotify.c.

Hi Malcolm Smith,

That?s a good example. So I decided now to handle IRP_MN_NOTIFY_CHANGE_DIRECTORY and in it?s completion routine I will modify the foo.txt.xml to foo.txt in the out buffer.

Doing it in minifilter is always easy than doing same in legacy and mine is a legacy driver. So my next question is?

What method is used for IRP_MN_NOTIFY_CHANGE_DIRECTORY for accessing the user buffer, I mean BUFFERED, DIRECT or NEITHER. And what precautions I should take to access that buffer in completion routine?

Thanks & Regards,
Amit.

On 03/05/2013 05:44 AM, xxxxx@yahoo.com wrote:

What method is used for IRP_MN_NOTIFY_CHANGE_DIRECTORY for accessing the user buffer, I mean BUFFERED, DIRECT or NEITHER. And what precautions I should take to access that buffer in completion routine?

I don’t mean to sound dismissive, but I’d refer you back to the sample.

Handling this is somewhat tricky, because the answer is “all of them.”
It might refer to a non-NULL UserBuffer that represents a user address;
if a MDL is present that might represent the user address; and even more
strangely, the file system can convert one of these requests into a
buffered request, adding a SystemBuffer and populating that, leaving
iomgr to copy back into the user buffer on completion. The sample does
deal with this, and although it is a mini, it still provides an outline
for what’s happening.

Pay particular attention to FltGetNewSystemBufferAddress, which is new
in Win7. The sample can use this when available to send user buffers to
the file system and then manipulate the system buffered result, and when
the API is not available it can fall back to locking the buffer and
providing a MDL. As a legacy filter, you have the advantage of being
able to perform the correct handling of buffered requests manually on
all platforms (back to Win2k.)

The logic in the sample is in NcGetDestinationNotifyBuffer. Although as
a legacy the data structures are different, the logic is the same.

  • M