From 8787f2c528c625fdffead3543ece03c7dafb43be Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 14 Apr 2017 00:01:08 -0700 Subject: [PATCH] inc: winfsp.hpp: FileSystem: ReadDirectoryEntry and friends --- inc/winfsp/winfsp.hpp | 128 ++++++++++++++++++------ tst/passthrough-cpp/passthrough-cpp.cpp | 101 ++++++++++--------- 2 files changed, 148 insertions(+), 81 deletions(-) diff --git a/inc/winfsp/winfsp.hpp b/inc/winfsp/winfsp.hpp index 8a7602d6..dab68c89 100644 --- a/inc/winfsp/winfsp.hpp +++ b/inc/winfsp/winfsp.hpp @@ -236,44 +236,95 @@ public: return _FileSystem; } - /* helpers: directories/streams */ - static BOOLEAN AcquireDirectoryBuffer(PVOID *PDirBuffer, - BOOLEAN Reset, PNTSTATUS PResult) - { - return FspFileSystemAcquireDirectoryBuffer(PDirBuffer, Reset, PResult); - } - static BOOLEAN FillDirectoryBuffer(PVOID *PDirBuffer, - DirInfo *DirInfo, PNTSTATUS PResult) - { - return FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, PResult); - } - static VOID ReleaseDirectoryBuffer(PVOID *PDirBuffer) - { - FspFileSystemReleaseDirectoryBuffer(PDirBuffer); - } - static VOID ReadDirectoryBuffer(PVOID *PDirBuffer, + /* helpers */ + NTSTATUS SeekableReadDirectory( + PVOID FileNode, + PVOID FileDesc, + PWSTR Pattern, PWSTR Marker, - PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + PVOID Buffer, + ULONG Length, + PULONG PBytesTransferred) { - FspFileSystemReadDirectoryBuffer(PDirBuffer, - Marker, Buffer, Length, PBytesTransferred); + PVOID Context = 0; + union + { + UINT8 B[FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)]; + FileSystem::DirInfo D; + } DirInfoBuf; + FileSystem::DirInfo *DirInfo = &DirInfoBuf.D; + NTSTATUS Result = STATUS_SUCCESS; + *PBytesTransferred = 0; + for (;;) + { + Result = ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker, &Context, DirInfo); + if (STATUS_NO_MORE_FILES == Result) + { + Result = STATUS_SUCCESS; + break; + } + if (!NT_SUCCESS(Result)) + break; + if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred)) + break; + } + if (!NT_SUCCESS(Result)) + return Result; + return STATUS_SUCCESS; + } + NTSTATUS BufferedReadDirectory( + PVOID *PDirBuffer, + PVOID FileNode, + PVOID FileDesc, + PWSTR Pattern, + PWSTR Marker, + PVOID Buffer, + ULONG Length, + PULONG PBytesTransferred) + { + PVOID Context = 0; + union + { + UINT8 B[FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)]; + FileSystem::DirInfo D; + } DirInfoBuf; + FileSystem::DirInfo *DirInfo = &DirInfoBuf.D; + NTSTATUS Result = STATUS_SUCCESS; + *PBytesTransferred = 0; + if (FspFileSystemAcquireDirectoryBuffer(PDirBuffer, 0 == Marker, &Result)) + { + try + { + for (;;) + { + Result = ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker, &Context, DirInfo); + if (STATUS_NO_MORE_FILES == Result) + { + Result = STATUS_SUCCESS; + break; + } + if (!NT_SUCCESS(Result)) + break; + if (!FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, &Result)) + break; + } + } + catch (...) + { + FspFileSystemReleaseDirectoryBuffer(PDirBuffer); + throw; + } + FspFileSystemReleaseDirectoryBuffer(PDirBuffer); + } + if (!NT_SUCCESS(Result)) + return Result; + FspFileSystemReadDirectoryBuffer(PDirBuffer, Marker, Buffer, Length, PBytesTransferred); + return STATUS_SUCCESS; } static VOID DeleteDirectoryBuffer(PVOID *PDirBuffer) { FspFileSystemDeleteDirectoryBuffer(PDirBuffer); } - static BOOLEAN AddDirInfo(DirInfo *DirInfo, - PVOID Buffer, ULONG Length, PULONG PBytesTransferred) - { - return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred); - } - static BOOLEAN AddStreamInfo(StreamInfo *StreamInfo, - PVOID Buffer, ULONG Length, PULONG PBytesTransferred) - { - return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred); - } - - /* helpers: reparse points */ BOOLEAN FindReparsePoint( PWSTR FileName, PUINT32 PReparsePointIndex) { @@ -288,6 +339,11 @@ public: CurrentReparseData, CurrentReparseDataSize, ReplaceReparseData, ReplaceReparseDataSize); } + static BOOLEAN AddStreamInfo(StreamInfo *StreamInfo, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + { + return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred); + } protected: /* operations */ @@ -460,6 +516,16 @@ protected: { return STATUS_INVALID_DEVICE_REQUEST; } + virtual NTSTATUS ReadDirectoryEntry( + PVOID FileNode, + PVOID FileDesc, + PWSTR Pattern, + PWSTR Marker, + PVOID *PContext, + DirInfo *DirInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } virtual NTSTATUS ResolveReparsePoints( PWSTR FileName, UINT32 ReparsePointIndex, diff --git a/tst/passthrough-cpp/passthrough-cpp.cpp b/tst/passthrough-cpp/passthrough-cpp.cpp index 7e03a9ba..f1683bde 100644 --- a/tst/passthrough-cpp/passthrough-cpp.cpp +++ b/tst/passthrough-cpp/passthrough-cpp.cpp @@ -148,6 +148,13 @@ protected: PVOID Buffer, ULONG Length, PULONG PBytesTransferred); + NTSTATUS ReadDirectoryEntry( + PVOID FileNode, + PVOID FileDesc, + PWSTR Pattern, + PWSTR Marker, + PVOID *PContext, + DirInfo *DirInfo); private: PWSTR _Path; @@ -729,8 +736,21 @@ NTSTATUS Ptfs::ReadDirectory( PWSTR Pattern, PWSTR Marker, PVOID Buffer, - ULONG BufferLength, + ULONG Length, PULONG PBytesTransferred) +{ + PtfsFileDesc *FileDesc = (PtfsFileDesc *)FileDesc0; + return BufferedReadDirectory(&FileDesc->DirBuffer, + FileNode, FileDesc, Pattern, Marker, Buffer, Length, PBytesTransferred); +} + +NTSTATUS Ptfs::ReadDirectoryEntry( + PVOID FileNode, + PVOID FileDesc0, + PWSTR Pattern, + PWSTR Marker, + PVOID *PContext, + DirInfo *DirInfo) { PtfsFileDesc *FileDesc = (PtfsFileDesc *)FileDesc0; HANDLE Handle = FileDesc->Handle; @@ -738,16 +758,8 @@ NTSTATUS Ptfs::ReadDirectory( ULONG Length, PatternLength; HANDLE FindHandle; WIN32_FIND_DATAW FindData; - union - { - UINT8 B[FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)]; - FileSystem::DirInfo D; - } DirInfoBuf; - FileSystem::DirInfo *DirInfo = &DirInfoBuf.D; - NTSTATUS DirBufferResult; - DirBufferResult = STATUS_SUCCESS; - if (AcquireDirectoryBuffer(&FileDesc->DirBuffer, 0 == Marker, &DirBufferResult)) + if (0 == *PContext) { if (0 == Pattern) Pattern = L"*"; @@ -755,14 +767,9 @@ NTSTATUS Ptfs::ReadDirectory( Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0); if (0 == Length) - DirBufferResult = NtStatusFromWin32(GetLastError()); - else if (Length + 1 + PatternLength >= FULLPATH_SIZE) - DirBufferResult = STATUS_OBJECT_NAME_INVALID; - if (!NT_SUCCESS(DirBufferResult)) - { - ReleaseDirectoryBuffer(&FileDesc->DirBuffer); - return DirBufferResult; - } + return NtStatusFromWin32(GetLastError()); + if (Length + 1 + PatternLength >= FULLPATH_SIZE) + return STATUS_OBJECT_NAME_INVALID; if (L'\\' != FullPath[Length - 1]) FullPath[Length++] = L'\\'; @@ -770,43 +777,37 @@ NTSTATUS Ptfs::ReadDirectory( FullPath[Length + PatternLength] = L'\0'; FindHandle = FindFirstFileW(FullPath, &FindData); - if (INVALID_HANDLE_VALUE != FindHandle) + if (INVALID_HANDLE_VALUE == FindHandle) + return STATUS_NO_MORE_FILES; + + *PContext = FindHandle; + } + else + { + FindHandle = *PContext; + if (!FindNextFileW(FindHandle, &FindData)) { - do - { - memset(DirInfo, 0, sizeof *DirInfo); - Length = (ULONG)wcslen(FindData.cFileName); - DirInfo->Size = (UINT16)(FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + - Length * sizeof(WCHAR)); - DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes; - DirInfo->FileInfo.ReparseTag = 0; - DirInfo->FileInfo.FileSize = - ((UINT64)FindData.nFileSizeHigh << 32) | (UINT64)FindData.nFileSizeLow; - DirInfo->FileInfo.AllocationSize = (DirInfo->FileInfo.FileSize + ALLOCATION_UNIT - 1) - / ALLOCATION_UNIT * ALLOCATION_UNIT; - DirInfo->FileInfo.CreationTime = ((PLARGE_INTEGER)&FindData.ftCreationTime)->QuadPart; - DirInfo->FileInfo.LastAccessTime = ((PLARGE_INTEGER)&FindData.ftLastAccessTime)->QuadPart; - DirInfo->FileInfo.LastWriteTime = ((PLARGE_INTEGER)&FindData.ftLastWriteTime)->QuadPart; - DirInfo->FileInfo.ChangeTime = DirInfo->FileInfo.LastWriteTime; - DirInfo->FileInfo.IndexNumber = 0; - DirInfo->FileInfo.HardLinks = 0; - memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR)); - - if (!FillDirectoryBuffer(&FileDesc->DirBuffer, DirInfo, &DirBufferResult)) - break; - } while (FindNextFileW(FindHandle, &FindData)); - FindClose(FindHandle); + return STATUS_NO_MORE_FILES; } - - ReleaseDirectoryBuffer(&FileDesc->DirBuffer); } - if (!NT_SUCCESS(DirBufferResult)) - return DirBufferResult; - - ReadDirectoryBuffer(&FileDesc->DirBuffer, - Marker, Buffer, BufferLength, PBytesTransferred); + memset(DirInfo, 0, sizeof *DirInfo); + Length = (ULONG)wcslen(FindData.cFileName); + DirInfo->Size = (UINT16)(FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + Length * sizeof(WCHAR)); + DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes; + DirInfo->FileInfo.ReparseTag = 0; + DirInfo->FileInfo.FileSize = + ((UINT64)FindData.nFileSizeHigh << 32) | (UINT64)FindData.nFileSizeLow; + DirInfo->FileInfo.AllocationSize = (DirInfo->FileInfo.FileSize + ALLOCATION_UNIT - 1) + / ALLOCATION_UNIT * ALLOCATION_UNIT; + DirInfo->FileInfo.CreationTime = ((PLARGE_INTEGER)&FindData.ftCreationTime)->QuadPart; + DirInfo->FileInfo.LastAccessTime = ((PLARGE_INTEGER)&FindData.ftLastAccessTime)->QuadPart; + DirInfo->FileInfo.LastWriteTime = ((PLARGE_INTEGER)&FindData.ftLastWriteTime)->QuadPart; + DirInfo->FileInfo.ChangeTime = DirInfo->FileInfo.LastWriteTime; + DirInfo->FileInfo.IndexNumber = 0; + DirInfo->FileInfo.HardLinks = 0; + memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR)); return STATUS_SUCCESS; }