Is there a flat enumeration mechanism available to mini-filters to
efficiently locate all reparse points (similar to
FindFirstVolumeMountPoint)? Something that queries $Extend$Reparse
rather than the hierarchical zwQueryDirectoryFile() for
FileReparsePointInformation. Wading through all reparse points is ok.
Queries matching a particular reparse tag would be ideal.
There is no api written to do this but you can write your own code to read the reparse index . See http://www.osronline.com/showThread.cfm?link=105613 for some more details.
Thanks for link. It appears that [Zw/Nt]QueryDirectoryFile() is it. I
was hoping to avoid having to descend into every directory on the
volume.
There is no api written to do this but you can write your own code to
read > the reparse index . See
http://www.osronline.com/showThread.cfm?link=105613 for some more
details.
You do not have to descend into every directory if you read the reparse index (open Extend$Reparse:$R:$INDEX_ALLOCATION and use ZwQueryDirectoryFile on that handle to get reparse info). It gives you the FileReference (file id) and tag value of all the reparse points on the volume (see ntifs.h for FILE_REPARSE_POINT_INFORMATION). From that you can identify which reparse points you are interested in (by the tag) and open the file or directory by file ID. It is possible to get the path from the handle that you opened by ID doing a by query for FileNameInformation although this does not work 100% of the time (depends on what rights the user has).
>You do not have to descend into every directory if you read the reparse
index (open Extend$Reparse:$R:$INDEX_ALLOCATION and use [Hornay,
Rich] >ZwQueryDirectoryFile on that handle to get reparse info).
Why didn’t I think of that? That’s the magic I was looking for. I will
give that a try.
Thanks for your help.
Rick,
I just want to check the behavior I am seeing. I wrote a user mode app
to list the reparse points. I am calling NtQueryDirectoryFile. It
appears to return STATUS_SUCCESS for some random number of iterations on
the last entry before returning STATUS_NO_MORE_FILES. This is on Srv03
SP1.
Is that what you see? Do you stop when you get an entry with the same
file reference as the last iteration?
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com
Sent: Monday, April 30, 2007 4:51 PM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Enumerating Reparse Points on a volume
You do not have to descend into every directory if you read the reparse
index (open Extend$Reparse:$R:$INDEX_ALLOCATION and use
ZwQueryDirectoryFile on that handle to get reparse info). It gives you
the FileReference (file id) and tag value of all the reparse points on
the volume (see ntifs.h for FILE_REPARSE_POINT_INFORMATION). From that
you can identify which reparse points you are interested in (by the tag)
and open the file or directory by file ID. It is possible to get the
path from the handle that you opened by ID doing a by query for
FileNameInformation although this does not work 100% of the time
(depends on what rights the user has).
I make the first call to NtQueryDirectoryFile with a buffer size that will hold 1000 entries (sizeof(FILE_REPARSE_POINT_INFORMATION) * 1000), the ReturnSingleEntry parameter (third from the last) set to FALSE and RestartScan (the last parameter) set to TRUE. If I get 1000 reparse points I make a subsequent call with RestartScan set to FALSE. I continue making calls with RestartScan set to FALSE until I get less than 1000 entries returned or I get an error from NtQueryDirectoryFile. A success status means that some number of entries have been returned (The Information field of the IO_STATUS_BLOCK will have the actual size of the data returned) . I have not seen it return STATUS_NO_MORE_FILES.
The reason I have not seen it return STATUS_NO_MORE_FILES is most likely because I have not run it on a volume with a exact multiple of 1000 reparse points. Since I quit if I get less than 1000 I would not see the error unless the last successful call I made returned the last 1000 entries. In that case I would make one more call and get this status.
How do you know how many records were placed into your buffer?
According to the docs for ZwQuerydriectoryFile() the bytes returned
should be in the Information member of the IO_STATUS_BLOCK.
My user mode test is calling NtQueryDirectoryFile. According to the
tests that I have run, it does not populate the Information member. I
memset the buffer before the call and then stop on the first tag that is
zero. If I continue to call NtQueryDirectoryFile, it will succeed some
random number of times, though it does not populate the buffer, until
finally I get STATUS_NO_MORE_FILES in the Status member of the
IO_STATUS_BLOCK.
I need to test it on the other platforms, but it appears to be
predictable.
Thanks for your help Rick. I believe this will work for my needs. It
is much less expensive than a hierarchical traversal. It would be nice
if MS would put in a documented api similar to that for MountPoints.
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com
Sent: Thursday, May 03, 2007 11:14 AM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Enumerating Reparse Points on a volume
The reason I have not seen it return STATUS_NO_MORE_FILES is most likely
because I have not run it on a volume with a exact multiple of 1000
reparse points. Since I quit if I get less than 1000 I would not see
the error unless the last successful call I made returned the last 1000
entries. In that case I would make one more call and get this status.
Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17
You are currently subscribed to ntfsd as: xxxxx@doubletake.com
To unsubscribe send a blank email to xxxxx@lists.osr.com
I am seeing the Information member of the IO_STATUS_BLOCK getting set. I calculate the number of entries by dividing the returned size by sizeof(FILE_REPARSE_POINT_INFORMATION). Are you allocating the space for the IO_STATUS_BLOCK and passing the address of it? When you say it succeeds a random number of times does that mean that on the same volume it succeeds a different number of times each time you run the test? I am looking at the status returned by NtQueryXXX (not the value in the IO_STATUS_BLOCK). The only thing I can think of is you may be allocating a pointer to the IO_STATUS_BLOCK and passing it in uninitialized rather than allocating the space and passing the address of it. This could cause the odd behavior you are seeing.
>>Are you allocating the space for the IO_STATUS_BLOCK and passing the
>address of it?
It is on the stack and the address is being passed. I see the
STATUS_NO_MORE_FILES in the Status member of the IO_STATUS_BLOCK.
>When you say it succeeds a random number of times does that mean that
on >>the same volume it succeeds a different number of times each time
you run >>the test?
Yes. I run the sample several times in succession (the volume is hard
coded). I have seen it loop 2 to 6 times. It varies with each
execution.
I am guessing that this is either unique to NtQueryDirectoryFile or
Srv03 Sp1.
I am also using NtQueryDirectoryFile and have run it on Srv03 SP2 and I am seeing it work as I described. Without seeing your code I cannot think of anything else that would explain it.
I sent you the code directly. Your spam filter may have caught it.
I figured it out. Once I set FILE_SYNCHRONOUS_IO_NONALERT into the
CreateOptions and SYNCHRONIZE into the DesiredAccess, I started getting
the bytes in the Information member of IO_STATUS_BLOCK and it now
iterates the correct number of times.