Search code examples
windowsdriverminifilterjunction

In a minifilter, how do I get the path the file was opened with?


My minifilter driver uses the post-create callback to communicate the path of the file being opened to a user-mode process. The minifilter uses a reparse point to identify which files need to be processed.

PFLT_FILE_NAME_INFORMATION pFNI = NULL;

DWORD FNIFlags = FLT_FILE_NAME_OPENED | 
                 FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP |
                 FLT_FILE_NAME_ALLOW_QUERY_ON_REPARSE;

NTSTATUS Status = FltGetFileNameInformation(Data, FNIFlags, &pFNI);
if (!NT_SUCCESS(Status))
{
    DBG_PRINT_ERROR("FltGetFileNameInformation failed: %#x", Status);
    __leave;
}

DBG_PRINT_INFO("Realize '%wZ'", pFNI->Name);

This works fine, except when the file is opened through a NTFS junction like so:

mkdir c:\a
mkdir c:\b
echo "hello world" >c:\b\b.txt
# ...set reparse point metadata on b.txt
mklink /j c:\a\b c:\b
type c:\a\b\b.txt

When type openes the file, my driver prints this output:

Realize '\Device\HarddiskVolume2\b\b.txt'

So, it's seeing the file's true path, after the junction is evaluated, not the path that the file was opened from.

The problem is, my program depends on finding a configuration file in one of the parent directories of the file being opened, and this problem with junctions makes my program miss the configuration file.

MSDN says that FLT_FILE_NAME_OPENED returns "The name that was used when the handle was opened to this file". I believe that it should therefore give me \Device\HarddiskVolume2\a\b\b.txt instead of \Device\HarddiskVolume2\b\b.txt. What am I missing?


Solution

  • Unless the file is cached in which case you will get the "resolved".
    I would suggest to use only the FLT_FILE_NAME_OPENED getting rid of the other two flags.

    Check out this article by Alex Carp regarding these flags.

    Cheers,
    Gabriel