diff --git a/.gitignore b/.gitignore index 672c4ec7..ef3d5d09 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,5 @@ ReleasePS *.bak *.log *.msi -*.wixpdb \ No newline at end of file +*.wixpdb +/dokan_fuse/out/build/x64-Debug diff --git a/CHANGELOG.md b/CHANGELOG.md index d807b114..3f8c978d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2.3.8.1000] - 2026-01-14 + +### Added +- Library - Callbacks FindFiles/FindFilesWithPattern can return STATUS_MORE_ENTRIES to signal availability of more entries +- Library - Added Field ForceScan to structure DOKAN_FILE_INFO, that indicates to the callback, that the IRP requests a new scan instead of continuing a former one + ## [2.3.1.1000] - 2025-09-28 ### Changed diff --git a/documentations/mainpage.md b/documentations/mainpage.md index 2fb39559..854ccf5c 100644 --- a/documentations/mainpage.md +++ b/documentations/mainpage.md @@ -96,6 +96,10 @@ library. Wildcard matching can be controlled by implementing DOKAN_OPERATIONS.FindFilesWithPattern function. The function \ref DokanIsNameInExpression exported can be used to process wildcard matching. +The functions may return STATUS_MORE_ENTRIES to request the library to call them again to fetch more directory entries. +This can be used to add directory entries in chunks, instead of adding all entries in one call. +If DOKAN_FILE_INFO.ForceScan is TRUE, the functions must start a new listing. + ### Mounting As stated above, the file system can be mounted by invoking \ref DokanMain function or \ref DokanCreateFileSystem. diff --git a/dokan/directory.c b/dokan/directory.c index ce6be2ad..39697be0 100644 --- a/dokan/directory.c +++ b/dokan/directory.c @@ -387,7 +387,9 @@ LONG MatchFiles(PDOKAN_IO_EVENT IoEvent, PDOKAN_VECTOR DirList) { IoEvent->EventContext->Operation.Directory.BufferLength; PVOID currentBuffer = IoEvent->EventResult->Buffer; PVOID lastBuffer = currentBuffer; - ULONG index = 0; + + // Why should we always start at the beginning of the list over and over again ? + ULONG index = IoEvent->EventContext->Operation.Directory.FileIndex; BOOL patternCheck = FALSE; PWCHAR pattern = NULL; BOOL bufferOverFlow = FALSE; @@ -407,7 +409,7 @@ LONG MatchFiles(PDOKAN_IO_EVENT IoEvent, PDOKAN_VECTOR DirList) { patternCheck = TRUE; } - for (size_t i = 0; i < DokanVector_GetCount(DirList); ++i) { + for (size_t i = index; i < DokanVector_GetCount(DirList); ++i) { PDOKAN_FIND_DATA find = (PDOKAN_FIND_DATA)DokanVector_GetItem(DirList, i); DbgPrintW(L"FileMatch? : %s (%s,%d,%d)\n", find->FindData.cFileName, (pattern ? pattern : L"null"), @@ -680,6 +682,36 @@ VOID DispatchDirectoryInformation(PDOKAN_IO_EVENT IoEvent) { : FALSE; if (!forceScan) { status = WriteDirectoryResults(IoEvent, openInfo->DirList); + + if ((STATUS_NO_MORE_FILES == status) && (openInfo->MoreItems == TRUE)) { + // Let's see, if there's more to come from the callback + IoEvent->EventResult->Status = STATUS_SUCCESS; + IoEvent->DokanFileInfo.ProcessingContext = openInfo->DirList; + IoEvent->DokanFileInfo.ForceScan = FALSE; + + if (!openInfo->UnimplementedFindFilesWithPattern) { + status = + IoEvent->DokanInstance->DokanOperations->FindFilesWithPattern( + IoEvent->EventContext->Operation.Directory.DirectoryName, + searchPattern ? searchPattern : L"*", DokanFillFileData, + &IoEvent->DokanFileInfo); + } else { + status = IoEvent->DokanInstance->DokanOperations->FindFiles( + IoEvent->EventContext->Operation.Directory.DirectoryName, + DokanFillFileData, &IoEvent->DokanFileInfo); + } + + openInfo->MoreItems = FALSE; + if (status == STATUS_MORE_ENTRIES) { + openInfo->MoreItems = TRUE; + status = STATUS_SUCCESS; + } + + if (STATUS_SUCCESS == status) { + // try again + status = WriteDirectoryResults(IoEvent, openInfo->DirList); + } + } } } LeaveCriticalSection(&openInfo->CriticalSection); @@ -707,6 +739,9 @@ VOID DispatchDirectoryInformation(PDOKAN_IO_EVENT IoEvent) { status = STATUS_NOT_IMPLEMENTED; + IoEvent->DokanFileInfo.ForceScan = TRUE; + openInfo->MoreItems = FALSE; + // Reminder: FindFilesWithPattern may not be implemented by returning STATUS_NOT_IMPLEMENTED. if (IoEvent->DokanInstance->DokanOperations->FindFilesWithPattern) { status = IoEvent->DokanInstance->DokanOperations->FindFilesWithPattern( @@ -729,6 +764,10 @@ VOID DispatchDirectoryInformation(PDOKAN_IO_EVENT IoEvent) { } if (status != STATUS_NOT_IMPLEMENTED) { + if (status == STATUS_MORE_ENTRIES) { + openInfo->MoreItems = TRUE; + status = STATUS_SUCCESS; + } EndFindFilesCommon(IoEvent, status); } else { // Neither FindFilesWithPattern nor FindFiles are implemented. diff --git a/dokan/dokan.c b/dokan/dokan.c index c926c837..6c74d2b0 100644 --- a/dokan/dokan.c +++ b/dokan/dokan.c @@ -291,6 +291,8 @@ VOID SetupIOEventForProcessing(PDOKAN_IO_EVENT IoEvent) { if (IoEvent->EventContext->FileFlags & DOKAN_NOCACHE) { IoEvent->DokanFileInfo.Nocache = 1; } + + IoEvent->DokanFileInfo.ForceScan = FALSE; } VOID HandleUnknownEvent(PDOKAN_IO_EVENT IoEvent) { diff --git a/dokan/dokan.h b/dokan/dokan.h index bc272fd1..21e6e41c 100644 --- a/dokan/dokan.h +++ b/dokan/dokan.h @@ -56,7 +56,7 @@ extern "C" { /** @{ */ /** The current Dokan version (200 means ver 2.0.0). \ref DOKAN_OPTIONS.Version */ -#define DOKAN_VERSION 231 +#define DOKAN_VERSION 238 /** Minimum Dokan version (ver 2.0.0) accepted. */ #define DOKAN_MINIMUM_COMPATIBLE_VERSION 200 /** Driver file name including the DOKAN_MAJOR_API_VERSION */ @@ -220,6 +220,8 @@ typedef struct _DOKAN_FILE_INFO { UCHAR Nocache; /** If \c TRUE, write to the current end of file instead of using the Offset parameter. */ UCHAR WriteToEndOfFile; + /** If \c TRUE, start a new directory scan in FindFiles/WithPattern. */ + UCHAR ForceScan; } DOKAN_FILE_INFO, *PDOKAN_FILE_INFO; #define DOKAN_EXCEPTION_NOT_INITIALIZED 0x0f0ff0ff diff --git a/dokan/dokan.rc b/dokan/dokan.rc index ba2598bd..89225c9e 100644 --- a/dokan/dokan.rc +++ b/dokan/dokan.rc @@ -16,8 +16,8 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,3,1,1000 - PRODUCTVERSION 2,3,1,1000 + FILEVERSION 2,3,8,1000 + PRODUCTVERSION 2,3,8,1000 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -32,14 +32,14 @@ BEGIN BEGIN BLOCK "000004e3" BEGIN - VALUE "CompanyName", "Dokan Project" - VALUE "FileDescription", "Dokan Library" - VALUE "FileVersion", "2.3.1.1000" + VALUE "CompanyName", "dataglobal Bochum GmbH" + VALUE "FileDescription", "Dokan Library - ChunkFindFiles" + VALUE "FileVersion", "2.3.8.1000" VALUE "InternalName", "dokan.dll" VALUE "LegalCopyright", "Copyright (C) 2025" VALUE "OriginalFilename", "dokan.dll" VALUE "ProductName", "Dokan" - VALUE "ProductVersion", "2.3.1.1000" + VALUE "ProductVersion", "2.3.8.1000" END END BLOCK "VarFileInfo" diff --git a/dokan/dokani.h b/dokan/dokani.h index 796c81fe..e3b6de73 100644 --- a/dokan/dokani.h +++ b/dokan/dokani.h @@ -109,6 +109,8 @@ typedef struct _DOKAN_OPEN_INFO { PWCHAR DirListSearchPattern; /** Whether the FindFilesWithPattern has returned STATUS_NOT_IMPLEMENTED */ BOOLEAN UnimplementedFindFilesWithPattern; + /** Wether former FindFiles/WithPattern returned STATUS_MORE_ENTRIES to signal more entries to come */ + BOOLEAN MoreItems; /** User Context see DOKAN_FILE_INFO.Context */ LONG64 UserContext; /** Event Id */