diff --git a/src/dll/fsop.c b/src/dll/fsop.c index ffc7a17c..3ef2827d 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -412,6 +412,7 @@ FSP_API NTSTATUS FspFileSystemOpRead(FSP_FILE_SYSTEM *FileSystem, if (0 == FileSystem->Interface->Read) return STATUS_INVALID_DEVICE_REQUEST; + BytesTransferred = 0; Result = FileSystem->Interface->Read(FileSystem, Request, (PVOID)Request->Req.Read.UserContext, (PVOID)Request->Req.Read.Address, @@ -441,6 +442,7 @@ FSP_API NTSTATUS FspFileSystemOpWrite(FSP_FILE_SYSTEM *FileSystem, if (0 == FileSystem->Interface->Write) return STATUS_INVALID_DEVICE_REQUEST; + BytesTransferred = 0; Result = FileSystem->Interface->Write(FileSystem, Request, (PVOID)Request->Req.Write.UserContext, (PVOID)Request->Req.Write.Address, @@ -606,6 +608,7 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem, if (0 == FileSystem->Interface->ReadDirectory) return STATUS_INVALID_DEVICE_REQUEST; + BytesTransferred = 0; Result = FileSystem->Interface->ReadDirectory(FileSystem, Request, (PVOID)Request->Req.QueryDirectory.UserContext, (PVOID)Request->Req.QueryDirectory.Address, diff --git a/tst/winfsp-tests/memfs.cpp b/tst/winfsp-tests/memfs.cpp index 076f1bc8..6bd790ba 100644 --- a/tst/winfsp-tests/memfs.cpp +++ b/tst/winfsp-tests/memfs.cpp @@ -26,6 +26,12 @@ int MemfsFileNameCompare(PWSTR a, PWSTR b) return wcscmp(a, b); } +static inline +BOOLEAN MemfsFileNameHasPrefix(PWSTR a, PWSTR b) +{ + return 0 == wcsncmp(a, b, wcslen(b)); +} + typedef struct _MEMFS_FILE_NODE { WCHAR FileName[MAX_PATH]; @@ -193,6 +199,26 @@ BOOLEAN MemfsFileNodeMapHasChild(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NO return Result; } +static inline +VOID MemfsFileNodeEnumerateChildren(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode, + BOOLEAN (*EnumFn)(MEMFS_FILE_NODE *, PVOID), PVOID Context) +{ + WCHAR Root[2] = L"\\"; + PWSTR Remain, Suffix; + MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName); + for (; FileNodeMap->end() != iter; ++iter) + { + if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName)) + break; + FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root); + if (0 == MemfsFileNameCompare(Remain, FileNode->FileName)) + { + if (!EnumFn(iter->second, Context)) + break; + } + } +} + static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode0, UINT64 FileSize, @@ -662,6 +688,46 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } +typedef struct _MEMFS_READ_DIRECTORY_CONTEXT +{ + PVOID Buffer; + UINT64 Offset; + ULONG Length; + PULONG PBytesTransferred; +} MEMFS_READ_DIRECTORY_CONTEXT; + +static BOOLEAN ReadDirectoryEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0) +{ + MEMFS_READ_DIRECTORY_CONTEXT *Context = (MEMFS_READ_DIRECTORY_CONTEXT *)Context0; + UINT8 DirInfoBuf[sizeof(FSP_FSCTL_DIR_INFO) + sizeof FileNode->FileName]; + FSP_FSCTL_DIR_INFO *DirInfo = (FSP_FSCTL_DIR_INFO *)DirInfoBuf; + + if (0 == *Context->PBytesTransferred && Context->Offset != FileNode->FileInfo.IndexNumber) + return TRUE; + + return FspFileSystemAddDirInfo(DirInfo, + Context->Buffer, Context->Length, Context->PBytesTransferred); +} + +static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length, + PULONG PBytesTransferred) +{ + MEMFS *Memfs = (MEMFS *)FileSystem->UserContext; + MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; + MEMFS_READ_DIRECTORY_CONTEXT Context; + + Context.Buffer = Buffer; + Context.Offset = Offset; + Context.Length = Length; + Context.PBytesTransferred = PBytesTransferred; + + MemfsFileNodeEnumerateChildren(Memfs->FileNodeMap, FileNode, ReadDirectoryEnumFn, &Context); + + return STATUS_SUCCESS; +} + static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = { GetVolumeInfo, @@ -682,6 +748,7 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = Rename, GetSecurity, SetSecurity, + ReadDirectory, }; static VOID MemfsEnterOperation(FSP_FILE_SYSTEM *FileSystem,