I have a file system filter driver that is used to restrict access to files. The driver works for the most part. However, in testing, I have come across an issue that I have yet been able to solve.
The problem occurs when an IRP_MJ_DIRECTORY_CONTROL request results in ALL files within that request being restricted. In other words, no data is returned.
As long as at least one file is not restricted in the request, moving in the new buffer and completing the IRP results in displaying only the non-restricted files as expected. If all files are restricted however and an empty buffer is returned when completing the request, then a invalid listing is displayed (a NULL character) is Windows Explorer or the Command Prompt.
The IoStatus.Status field is set to STATUS_SUCCESS, the IoStatus.Information field is set to 0 and the user buffer is cleared when all files have been restricted.
Is there something else that I need to set or clear? Or, am I supposed to do something other than completing the IRP?
Mike
Your return doesn’t make sense to the caller - they probably aren’t handling that case, since if you don’t return an entry you should either return STATUS_NO_MORE_FILES or STATUS_NO_SUCH_FILE (depending upon whether or not you’ve returned entries already.) Of course, you could ALSO ask for more from the underlying FSD before failing the call (otherwise, how do you handle the case where it is the first N entries you suppress, but there are more.)
Getting this right in my experience takes a bit of work. I’d suggest writing your own test program would be generally useful - so you can control what goes into the directory and the size of the buffers you are pulling back.
Tony
OSR
I have tried returning each of those values. They result in the directory listing terminating even though there are more files to display.
I have read about asking “for more from the underlying FSD”, but I am not sure how that is done and I have not found any examples. Do I simply do an IoCallDriver with the current IRP and return STATUS_PENDING? Or ???
Mike
You can get the answer for yourself with a simple experiment. Grab the
latest copy of FileSpy (http://www.zezula.net/en/fstools/filespy.html) and
watch what happens when you do a dir of an empty directory on a volume. Then
do the same thing with your filter installed and you removing all entries
from the directory and compare the results.
Probably faster than waiting for a response and a good technique to learn
anyway.
-scott
–
Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com
wrote in message news:xxxxx@ntfsd…
> I have a file system filter driver that is used to restrict access to
> files. The driver works for the most part. However, in testing, I have
> come across an issue that I have yet been able to solve.
>
> The problem occurs when an IRP_MJ_DIRECTORY_CONTROL request results in ALL
> files within that request being restricted. In other words, no data is
> returned.
>
> As long as at least one file is not restricted in the request, moving in
> the new buffer and completing the IRP results in displaying only the
> non-restricted files as expected. If all files are restricted however and
> an empty buffer is returned when completing the request, then a invalid
> listing is displayed (a NULL character) is Windows Explorer or the Command
> Prompt.
>
> The IoStatus.Status field is set to STATUS_SUCCESS, the
> IoStatus.Information field is set to 0 and the user buffer is cleared when
> all files have been restricted.
>
> Is there something else that I need to set or clear? Or, am I supposed to
> do something other than completing the IRP?
>
> Mike
>
> The problem occurs when an IRP_MJ_DIRECTORY_CONTROL request results in ALL files within
that request being restricted. In other words, no data is returned.
If there is no data to return, IRP_MJ_DIRECTORY_CONTROL must fail with STATUS_NO_SUCH_FILE if this is the first call for this file object (FindFirstFile), or with STATUS_NO_MORE_FILES if this is the next call for this file object (FindNextFile).
See FASTFAT source.
To track what call is first and what is not, the CCB structure is used, which is the per-file-object context.
You must reproduce the same logic.
What is also important with this path:
a) wildcard support (SMB server can use it), FsRtlIsNameInExpression should be used for filtering
b) correct value of IoStatus.Information if partial entry is returned (forgot the details, see the FASTFAT source).
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
> I have read about asking “for more from the underlying FSD”
Note: you’re filtering this path.
So, you do something like this:
- submit the IRP down to FSD
- if FSD returned error, or nothing due to buffer space too small (all valid cases) - then just complete the request
- if FSD returned some entries, then you must filter them according to your logic
- and, if all of them were filtered away, you must resubmit the IRP to the FSD again for the next portion. Actually, you can do this always even if the entries were returned, just update the buffer space for FSD’s use to not overwrite the previous entries.
- you must complete the IRP only if a) FSD returned error, including the “no more” cases b) buffer space is out. In all other cases, you should resubmit.
Your bug is probably like this: you get the entries from the FSD, you filter all of them away and complete the IRP with zero data to callers. The callers are not expecting to see this, and thus FindFirst/NextFile fails miserably.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
> Your bug is probably like this: you get the entries from the FSD, you filter
all of them away and complete the IRP with zero data to callers. The
callers are not expecting to see this, and thus FindFirst/NextFile fails miserably.
You are exactly right, Maxim.
I am adding functionality to re-issue the IRP.
Mike
Re-issuing the IRP corrected the problem. Thank you Tony and Maxim.
Some knowledge to share … you can re-use the mapped buffer pointer created the first time you forward the IRP, no need to allocate an MDL and lock the pages a second time. (Yes, I did that the first time which resulted in “issues”. What was I thinking? lol)