Hello folks,
I’m developing a minifilter driver that provides write protection on a chosen directory by redirecting all ops from source dir to another dir that’s on a different volume.
In order to get better picture, let’s assume c:\tmp1 is the directory I want to protect from any sort of modifications and T:\tmp1 is the place where all operations are re-directed.
I achieve this by returning STATUS_REPARSE from Pre-create callback if the file in question has c:\tmp1\ as prefix and if it meets certain criterias.
Note that, in Pre-create I do not differentiate between file and dir and a request is reparsed if it meets above mentioned conditions.
In addition to this, I also handle IRP_MJ_QUERY_DIRECTORY to merge the results from both the locations to provide the virtualization.
(I handle other IRPs as well but those are irrelevant for this discussion).
This sort of a design has surfaced a problem when a file is opened with FILE_OPEN_BY_FILE_ID set.
Here are the steps in detail:
c:\tmp1 contains a singel file t1.txt whereas t:\tmp1 is an empty directory.
- hDir = CreateFileW("C:\tmp1", GENERIC_READ | GENERIC_WRITE,……); → Here app receives handle to t:\tmp1 in reality because of the re-direction from minifilter.
- FileId = NtQueryDirectoryFile(hDir, FileBothIdInformation…); → IRP_MJ_QUERY_DIRECTORY is triggered and returns info about C:\tmp1\t1.txt since there is none in t:\tmp1.
- NtCreateFile(FILE_OPEN_BY_FILE_ID) → This call fails with STATUS_INVALID_PARAMETER.
(Do not worry about the parameters much - the function calls work fine when my minifilter is not loaded).
What’s happening is because of the redirection in step 1, user app receives handle to directory from T:\ (which shall have different volume id that C:) but the FileID that was returned really belongs to C:\tmp1\t1.txt. And because File IDs are volume dependent, I think NtCreateFile catches this and doesn’t even send IRP_MJ_CREATE for the corresponding NtCreateFile call with file id set.
So this basically makes me wonder should I even be re-directing IRP_MJ_CREATE on directories?
If the approach followed makes sense to you, can you provide some insights as to how I can get around this?
Thanks