From 34546def3c459fd9c41637020ae507e7ccac0d22 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 25 Sep 2017 19:46:36 -0700 Subject: [PATCH] sys,dll: GetDirInfoByName --- inc/winfsp/fsctl.h | 1 + inc/winfsp/winfsp.h | 22 +++++++++++++++- src/dll/fsop.c | 61 ++++++++++++++++++++++++++++++++++++++------- src/sys/dirctl.c | 21 ++++++++++++---- 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 77d7bf9b..4cf17541 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -347,6 +347,7 @@ typedef struct FSP_FSCTL_TRANSACT_BUF Pattern; FSP_FSCTL_TRANSACT_BUF Marker; UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */ + UINT32 PatternIsFileName:1; /* Pattern does not contain wildcards */ } QueryDirectory; struct { diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index b2c97a57..0daf7667 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -802,12 +802,32 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE NTSTATUS (*GetStreamInfo)(FSP_FILE_SYSTEM *FileSystem, PVOID FileContext, PVOID Buffer, ULONG Length, PULONG PBytesTransferred); + /** + * Get directory information for a single file or directory within a parent directory. + * + * @param FileSystem + * The file system on which this request is posted. + * @param FileContext + * The file context of the parent directory. + * @param FileName + * The name of the file or directory to get information for. This name is relative + * to the parent directory and is a single path component. + * @param DirInfo [out] + * Pointer to a structure that will receive the directory information on successful + * return from this call. This information includes the file name, but also file + * attributes, file times, etc. + * @return + * STATUS_SUCCESS or error code. + */ + NTSTATUS (*GetDirInfoByName)(FSP_FILE_SYSTEM *FileSystem, + PVOID FileContext, PWSTR FileName, + FSP_FSCTL_DIR_INFO *DirInfo); /* * This ensures that this interface will always contain 64 function pointers. * Please update when changing the interface as it is important for future compatibility. */ - NTSTATUS (*Reserved[40])(); + NTSTATUS (*Reserved[39])(); } FSP_FILE_SYSTEM_INTERFACE; FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()), "FSP_FILE_SYSTEM_INTERFACE must have 64 entries."); diff --git a/src/dll/fsop.c b/src/dll/fsop.c index b28b6bcf..2e8163f5 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -1121,6 +1121,39 @@ FSP_API NTSTATUS FspFileSystemOpSetVolumeInformation(FSP_FILE_SYSTEM *FileSystem return STATUS_SUCCESS; } +static NTSTATUS FspFileSystemOpQueryDirectory_GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem, + PVOID FileContext, PWSTR FileName, BOOLEAN HasMarker, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) +{ + NTSTATUS Result; + union + { + FSP_FSCTL_DIR_INFO V; + UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + 255 * sizeof(WCHAR)]; + } DirInfoBuf; + FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.V; + + memset(DirInfo, 0, sizeof *DirInfo); + + if (!HasMarker) + { + Result = FileSystem->Interface->GetDirInfoByName(FileSystem, + FileContext, FileName, DirInfo); + if (!NT_SUCCESS(Result)) + return Result; + + if (FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred)) + FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred); + } + else + { + Result = STATUS_SUCCESS; + FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred); + } + + return Result; +} + FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { @@ -1131,15 +1164,25 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem, return STATUS_INVALID_DEVICE_REQUEST; BytesTransferred = 0; - Result = FileSystem->Interface->ReadDirectory(FileSystem, - (PVOID)ValOfFileContext(Request->Req.QueryDirectory), - 0 != Request->Req.QueryDirectory.Pattern.Size ? - (PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0, - 0 != Request->Req.QueryDirectory.Marker.Size ? - (PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : 0, - (PVOID)Request->Req.QueryDirectory.Address, - Request->Req.QueryDirectory.Length, - &BytesTransferred); + if (0 != FileSystem->Interface->GetDirInfoByName && + 0 != Request->Req.QueryDirectory.Pattern.Size && Request->Req.QueryDirectory.PatternIsFileName) + Result = FspFileSystemOpQueryDirectory_GetDirInfoByName(FileSystem, + (PVOID)ValOfFileContext(Request->Req.QueryDirectory), + (PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset), + 0 != Request->Req.QueryDirectory.Marker.Size, + (PVOID)Request->Req.QueryDirectory.Address, + Request->Req.QueryDirectory.Length, + &BytesTransferred); + else + Result = FileSystem->Interface->ReadDirectory(FileSystem, + (PVOID)ValOfFileContext(Request->Req.QueryDirectory), + 0 != Request->Req.QueryDirectory.Pattern.Size ? + (PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0, + 0 != Request->Req.QueryDirectory.Marker.Size ? + (PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : 0, + (PVOID)Request->Req.QueryDirectory.Address, + Request->Req.QueryDirectory.Length, + &BytesTransferred); if (!NT_SUCCESS(Result)) return Result; diff --git a/src/sys/dirctl.c b/src/sys/dirctl.c index 957c53f7..3d4afb92 100644 --- a/src/sys/dirctl.c +++ b/src/sys/dirctl.c @@ -480,6 +480,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry( PVOID DirInfoBuffer; ULONG DirInfoSize; FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); + BOOLEAN PassQueryDirectoryPattern, PatternIsFileName; BOOLEAN Success; ASSERT(FileNode == FileDesc->FileNode); @@ -566,10 +567,20 @@ static NTSTATUS FspFsvolQueryDirectoryRetry( } /* create request */ + PassQueryDirectoryPattern = PatternIsFileName = FALSE; + if (FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern && + FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer) + { + PassQueryDirectoryPattern = TRUE; + PatternIsFileName = !FsRtlDoesNameContainWildCards(&FileDesc->DirectoryPattern); + } + else if (!FsRtlDoesNameContainWildCards(&FileDesc->DirectoryPattern)) + { + PassQueryDirectoryPattern = TRUE; + PatternIsFileName = TRUE; + } Result = FspIopCreateRequestEx(Irp, 0, - (FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern && - FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ? - FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0) + + (PassQueryDirectoryPattern ? FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0) + (FsvolDeviceExtension->VolumeParams.MaxComponentLength + 1) * sizeof(WCHAR), FspFsvolQueryDirectoryRequestFini, &Request); if (!NT_SUCCESS(Result)) @@ -584,9 +595,9 @@ static NTSTATUS FspFsvolQueryDirectoryRetry( Request->Req.QueryDirectory.Length = SystemBufferLength; Request->Req.QueryDirectory.CaseSensitive = FileDesc->CaseSensitive; - if (FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern && - FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer) + if (PassQueryDirectoryPattern) { + Request->Req.QueryDirectory.PatternIsFileName = PatternIsFileName; Request->Req.QueryDirectory.Pattern.Offset = Request->FileName.Size; Request->Req.QueryDirectory.Pattern.Size =