Ok, I feel like I’m asking someone to do my job for me, but I’m out of
ideas and I’m looking for some suggestions for how to proceed.
PROBLEM: I have a 3rd-party unmodifiable user-mode application that monitors
a remote directory on the network for changes using the .NET
FileSystemWatcher object, which is just a wrapper for the
ReadDirectoryChangesW Win32 API. The problem is that when the remote
computer reboots, the FileSystemWatcher loses its “hooks” into the remote
drive and ceases to throw events when files change. The only way to restore
these hooks is to restart the user-mode app. I am trying to come up with a
way (via kernel drivers or otherwise) to repair the hooks or prevent them
from breaking so that the user-mode app continues to detect directory
changes after the remote computer finishes rebooting.
ATTEMPTED SOLUTION: For the past month I’ve been implemented the following
solution… I created a kernel-mode minifilter driver that intercepts
NotifyDirectory IRPs in its PreOp callback and stores them in its own
cancel-safe “completion” queue. It then clones each IRP and sends the clone
down the filter chain. If the clone comes back successful (meaning a file
changed), it copies the result back to the original IRP and completes it. If
the clone comes back failed (meaning that the directory being monitored
disappeared), it places the clone into a 2nd “retry” queue and kicks off a
5-second timer that sends a new clone down the filter chain. This process is
repeated until the clone completes successfully and causes the original IRP
to be sent back up the filter chain. The whole idea here is to prevent the
original IRP from completing with a ‘failed’ status, which causes the
FileSystemWatcher to break its hooks into the directory being monitored.
PROBLEM WITH ATTEMPTED SOLUTION: What I didn’t realize until I had this
minifilter complete is that the filter manager keeps a reference count on
the number of IRPs referencing a given file system object. So, as long as I
am hanging onto the original IRP in my cancel-safe queue, the reference
count on the directory being monitored never decrements to zero and the
filesystem essentially goes into la-la land. Even if I had some way to
artificially force the reference count to zero (a horrible idea, I know),
the IRP I was holding onto would essentially be useless because when the
directory reappeared it would almost certainly be assigned a different
pointer.
ANOTHER IDEA #1: My next idea is to use the EldoS callback file system to
somehow abstract the network drive away from the user-mode app. The EldoS
guys think this is possible.
ANOTHER IDEA #2: Write a network mini-redirector that suppresses the
disconnect message, so the user-mode app will think the network drive is
always there. The problem with this approach (aside from very long
development time) is that it will almost certainly have unintended
consequences on other user-mode apps and the filesystem in general. Plus,
the network redirector architecture seems hugely complicated and somewhat
poorly documented.
ANOTHER IDEA #3: Write a FileSystemWatcher2 class that has the ability to
auto-repair directory-monitoring hooks (see
http://www.codeguru.com/csharp/.net/net_general/eventsanddelegates/article.php/c9113/).
Then, uncompile the original user-mode app using Reflector and modify it to
call my FileSystemWatcher2. Aside from probably being impossible, this idea
probably also violates copyright law and has virus-like qualities.
I’m running out of ideas … does anybody have any other suggestions for
allowing a user-mode app to keep its directory-monitoring hooks into a
network directory after the remote machine reboots (aside from modifying the
user-mode app)?