From 1bf28bdfa4d42548ef27e2b599ccb1a12f37e69e Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 21 Apr 2016 11:49:11 -0700 Subject: [PATCH] fsctl: FSP_FSCTL_TRANSACT_REQ: add Req.QueryDirectory.Pattern --- inc/winfsp/fsctl.h | 1 + inc/winfsp/winfsp.h | 5 +++++ src/dll/fsop.c | 2 ++ src/sys/dirctl.c | 23 +++++++++++++++-------- tst/memfs/memfs.cpp | 1 + 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 8017b9bc..8ca152ab 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -273,6 +273,7 @@ typedef struct UINT64 Address; UINT64 Offset; UINT32 Length; + FSP_FSCTL_TRANSACT_BUF Pattern; } QueryDirectory; struct { diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 05e4304e..23caf5b0 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -534,6 +534,10 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE * two entries returned by ReadDirectory should always be the "." and ".." entries. * @param Length * Length of data to read. + * @param Pattern + * The pattern to match against files in this directory. Can be NULL. The file system + * can choose to ignore this parameter as the FSD will always perform its own pattern + * matching on the returned results. * @param PBytesTransferred [out] * Pointer to a memory location that will receive the actual number of bytes read. * @return @@ -545,6 +549,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE NTSTATUS (*ReadDirectory)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length, + PWSTR Pattern, PULONG PBytesTransferred); } FSP_FILE_SYSTEM_INTERFACE; typedef struct _FSP_FILE_SYSTEM diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 94d12ad5..96eb5baa 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -630,6 +630,8 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem, (PVOID)Request->Req.QueryDirectory.Address, Request->Req.QueryDirectory.Offset, Request->Req.QueryDirectory.Length, + 0 != Request->Req.QueryDirectory.Pattern.Size ? + (PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0, &BytesTransferred); if (!NT_SUCCESS(Result)) return Result; diff --git a/src/sys/dirctl.c b/src/sys/dirctl.c index f21e761f..0c5fb30a 100644 --- a/src/sys/dirctl.c +++ b/src/sys/dirctl.c @@ -398,13 +398,6 @@ static NTSTATUS FspFsvolQueryDirectoryRetry( * - If the requsted DirectoryPattern is the MatchAll pattern then we set * the SystemBufferLength to the requested (IRP) length as it is actually * counter-productive to try to read more than we need. - * - * Note that we have made the decision not to forward the directory pattern - * to user mode and instead do all pattern matching in kernel mode. The - * primary reason for this decision was considerations about the DirInfo meta - * cache. If it is determined that this was a bad decision in the future, - * we can always start sending the directory pattern to user mode under some - * circumstances (e.g. when doing non-cached reads). */ #define GetSystemBufferLengthMaybeCached()\ (0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryOffset) ||\ @@ -534,7 +527,10 @@ static NTSTATUS FspFsvolQueryDirectoryRetry( } /* create request */ - Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolQueryDirectoryRequestFini, &Request); + Result = FspIopCreateRequestEx(Irp, 0, + FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ? + FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0, + FspFsvolQueryDirectoryRequestFini, &Request); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); @@ -547,6 +543,17 @@ static NTSTATUS FspFsvolQueryDirectoryRetry( Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset; Request->Req.QueryDirectory.Length = SystemBufferLength; + if (FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer) + { + Request->Req.QueryDirectory.Pattern.Offset = Request->FileName.Size; + Request->Req.QueryDirectory.Pattern.Size = + FileDesc->DirectoryPattern.Length + sizeof(WCHAR); + RtlCopyMemory(Request->Buffer + Request->FileName.Size, + FileDesc->DirectoryPattern.Buffer, FileDesc->DirectoryPattern.Length); + *(PWSTR)(Request->Buffer + Request->FileName.Size + FileDesc->DirectoryPattern.Length) = + L'\0'; + } + FspFileNodeSetOwner(FileNode, Full, Request); FspIopRequestContext(Request, RequestFileNode) = FileNode; diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index a1513ffa..280c80da 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -878,6 +878,7 @@ static BOOLEAN ReadDirectoryEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0) static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length, + PWSTR Pattern, PULONG PBytesTransferred) { MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;