Swapping buffers using MDLs

Hi experts,

I am looking at the swapBuffers sample and I have a question about swapping buffers in IRP_MJ_DIRECTORY_CONTROL. What if I’d like to return more entries to the user then was asked for? For example, let’s say the user passed iopb->Parameters.DirectoryControl.QueryDirectory.Length = sizeof(FILE_FULL_DIR_INFORMATION) * 10 however, I’d like to return 11 entries instead of 10. Could I just allocate more space for the MDL, meaning:

newBuf = ExAllocatePoolWithTag( NonPagedPool, iopb->Parameters.DirectoryControl.QueryDirectory.Length + sizeof(FILE_FULL_DIR_INFORMATION) , BUFFER_SWAP_TAG );

newMdl = IoAllocateMdl( newBuf, iopb->Parameters.DirectoryControl.QueryDirectory.Length + sizeof(FILE_FULL_DIR_INFORMATION), FALSE, FALSE, NULL );

and after that do all the swapping. If I understand correctly the system VA will reflect the new size correctly after calling MmGetSystemAddressForMdlSafe() but what about the user VA? Would this approach work? and if not, what the best way to solve such a problem?

Thank you.

It will not reflect in the user VA. Worse yet, how do you know the user space application is prepared to deal with more than 10 entries? This is a violation of the expected behavior of the user space API’s. A number of services I’ve seen would fail if they got more entries than they expected.

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

Don, thanks for a quick reply.

So under the current minifilter design (if I understand it correctly) I can only make the returned buffer smaller but not larger, right?

Thank you.

Or, rather, any length modification is not permitted at all…

You can mod8fy the buffer contents up to the size of the buffer.
You may not modify the buffer.

This has nkthing to do with dtivers, but basic C.

Know going into this that messing with directory enumerations sucks…Expect this to be quite painful.

You can certainly add entries to the directory enumeration. The way the directory enumeration interface works is the application first requests a new enumeration by specifying the SL_RESTART_SCAN bit. The file system then fills in as much as it can into the buffer, completes the request with success, and returns an opaque “index” value. The application then requests another enumeration with the previous index and the SL_INDEX_SPECIFIED flag. If there are more entries the file system fills in more entries and returns a new index. If there are no more entries the enumeration fails with STATUS_NO_MORE_FILES and the app knows to stop asking.

So, for example, if you want to add entries you just need to take a failing request from the file system and succeed it with your new entries. The application will then come asking again and you complete THAT request with STATUS_NO_MORE_FILES.

Best thing to do is build a copy of FASTFAT and make a test app that uses the native API for directory enumerations (ZwQueryDirectoryFile). Then you can get a feel for how the interface works and build a little test harness for yourself along the way. Also don’t forget that there are a zillion different directory enumeration information classes so the code gets super gnarly if you don’t design for that in the beginning.

> The way the

directory enumeration interface works is the application first requests a
new enumeration by specifying the SL_RESTART_SCAN bit. The file system then
fills in as much as it can into the buffer, completes the request with
success, and returns an opaque “index” value. The application then requests
another enumeration with the previous index and the SL_INDEX_SPECIFIED flag.

Hmm, during my latest project, I have seen this not to be true
extremely often. That is surely a possibility, but definitely not a
requirement.
I have almost never seen SL_RESTART_SCAN specified (technically, when
a folder is opened for enumeration, SL_RESTART_SCAN is presumed, and
not needed)

SL_INDEX_SPECIFIED - I don’t recall seeing this one.

True, SL_RESTART_SCAN is not required on the first scan. You only need it if you do multiple enumerations on the same handle.

SL_INDEX_SPECIFIED is also optional. If not specified the file system will use an internal pointer instead. See fastfat:

        if (IndexSpecified) {

            CurrentVbo = FileIndex + sizeof( DIRENT );

        } else if (RestartScan) {

            CurrentVbo = 0;

        } else {

            CurrentVbo = Ccb->OffsetToStartSearchFrom;

        }

The Windows I/O interface is a pain due to all the special cases that exist in the interface but aren’t necessarily commonly used. Internally we have a tool that allows us to script native API calls so we can test all the weird cases.

In any case, the application needs to keep asking until it gets back an error in order to know it has enumerated all the files. If you want to add things you (basically) just keep successfully completing query directories with your additional entries even after the file system has exhausted its own.