summaryrefslogtreecommitdiff
path: root/zen/FindFilePlus
diff options
context:
space:
mode:
Diffstat (limited to 'zen/FindFilePlus')
-rw-r--r--zen/FindFilePlus/FindFilePlus.vcxproj4
-rw-r--r--zen/FindFilePlus/find_file_plus.cpp38
2 files changed, 26 insertions, 16 deletions
diff --git a/zen/FindFilePlus/FindFilePlus.vcxproj b/zen/FindFilePlus/FindFilePlus.vcxproj
index d7dfe219..73b7f70e 100644
--- a/zen/FindFilePlus/FindFilePlus.vcxproj
+++ b/zen/FindFilePlus/FindFilePlus.vcxproj
@@ -172,7 +172,7 @@
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>false</GenerateDebugInformation>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -209,7 +209,7 @@
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>false</GenerateDebugInformation>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
diff --git a/zen/FindFilePlus/find_file_plus.cpp b/zen/FindFilePlus/find_file_plus.cpp
index fdabc46f..ea58005e 100644
--- a/zen/FindFilePlus/find_file_plus.cpp
+++ b/zen/FindFilePlus/find_file_plus.cpp
@@ -113,10 +113,10 @@ public:
FileSearcher(const wchar_t* dirname); //throw NtFileError
~FileSearcher();
- void readDir(FileInformation& output); //throw NtFileError
+ bool readDir(FileInformation& output); //throw NtFileError; returns false if "no more files"
private:
- template <class QueryPolicy> void readDirImpl(FileInformation& output); //throw NtFileError
+ template <class QueryPolicy> bool readDirImpl(FileInformation& output); //throw NtFileError
UNICODE_STRING dirnameNt; //it seems hDir implicitly keeps a reference to this, at least ::FindFirstFile() does no cleanup before ::FindClose()!
HANDLE hDir;
@@ -271,11 +271,11 @@ struct DirQueryFileId
inline
-void FileSearcher::readDir(FileInformation& output) { readDirImpl<DirQueryFileId>(output); } //throw NtFileError
+bool FileSearcher::readDir(FileInformation& output) { return readDirImpl<DirQueryFileId>(output); } //throw NtFileError
template <class QueryPolicy>
-void FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError
+bool FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError; returns false if "no more files"
{
//although FILE_ID_FULL_DIR_INFORMATION should suffice for our purposes, there are problems on Windows XP for certain directories, e.g. "\\Vboxsvr\build"
//making NtQueryDirectoryFile() return with STATUS_INVALID_PARAMETER while other directories, e.g. "C:\" work fine for some reason
@@ -337,25 +337,30 @@ void FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError
STATUS_NO_SUCH_FILE is abused by some citrix shares instead of "STATUS_INVALID_PARAMETER" so we treat it as such!
=> since the directory is "truly empty" a fallback won't hurt
*/
- if (rv == STATUS_INVALID_LEVEL ||
- rv == STATUS_NOT_SUPPORTED ||
+ if (rv == STATUS_NO_MORE_FILES) //perf: don't throw an exception in this common case! => 8% perf boost for FFS comparison phase!
+ return false;
+
+ if (rv == STATUS_NOT_SUPPORTED ||
+ rv == STATUS_INVALID_LEVEL ||
+ rv == STATUS_NO_SUCH_FILE || //[!]
rv == STATUS_UNEXPECTED_NETWORK_ERROR ||
rv == STATUS_INVALID_PARAMETER ||
rv == STATUS_INVALID_NETWORK_RESPONSE ||
rv == STATUS_INVALID_INFO_CLASS ||
+ //rv == STATUS_NOT_IMPLEMENTED || -> first confirm that these codes
+ //rv == STATUS_INVALID_DEVICE_REQUEST || -> are in fact used!
rv == STATUS_UNSUCCESSFUL ||
- rv == STATUS_ACCESS_VIOLATION ||
- rv == STATUS_NO_SUCH_FILE) //[!]
+ rv == STATUS_ACCESS_VIOLATION)
rv = STATUS_NOT_SUPPORTED;
throw NtFileError(rv); //throws STATUS_NO_MORE_FILES when finished
}
- //for (NTSTATUS i = 0xC0000000L; i != -1; ++i)
- //{
- // if (rtlNtStatusToDosError(i) == 59) //ERROR_UNEXP_NET_ERR
- // __asm int 3;
- //}
+ // for (NTSTATUS i = 0xC0000000L; i != -1; ++i)
+ // {
+ // if (rtlNtStatusToDosError(i) == 59) //ERROR_UNEXP_NET_ERR
+ // __debugbreak(); //__asm int 3;
+ // }
if (status.Information == 0) //except for the first call to call ::NtQueryDirectoryFile():
throw NtFileError(STATUS_BUFFER_OVERFLOW); //if buffer size is too small, return value is STATUS_SUCCESS and Information == 0 -> we don't expect this!
@@ -399,6 +404,7 @@ void FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError
static_assert(sizeof(output.lastWriteTime) == sizeof(dirInfo.LastWriteTime), "dang!");
static_assert(sizeof(output.fileSize) == sizeof(dirInfo.EndOfFile), "dang!");
static_assert(sizeof(output.fileAttributes) == sizeof(dirInfo.FileAttributes), "dang!");
+ return true;
}
@@ -425,7 +431,11 @@ bool findplus::readDir(FindHandle hnd, FileInformation& output)
{
try
{
- hnd->readDir(output); //throw NtFileError
+ if (!hnd->readDir(output)) //throw NtFileError
+ {
+ setWin32Error(rtlNtStatusToDosError(STATUS_NO_MORE_FILES));
+ return false;
+ }
return true;
}
catch (const NtFileError& e)
bgstack15