From 669df123648aaa6aeccc70206b5417bc48b4e9ae Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:26:50 +0200 Subject: 5.19 --- zen/FindFilePlus/find_file_plus.cpp | 38 +++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'zen/FindFilePlus/find_file_plus.cpp') 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 void readDirImpl(FileInformation& output); //throw NtFileError + template 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(output); } //throw NtFileError +bool FileSearcher::readDir(FileInformation& output) { return readDirImpl(output); } //throw NtFileError template -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) -- cgit