diff --git a/plugins/arclite/changelog b/plugins/arclite/changelog index d8a957c340..809c008370 100644 --- a/plugins/arclite/changelog +++ b/plugins/arclite/changelog @@ -1,3 +1,7 @@ +w17 01.06.2017 13:48:57 +0300 - build 253 + +1. Работа в Junction папке + drkns 15.03.2017 12:29:40 +0000 - build 252 1. 0003408: Arclite не закрывает файл после неуспешного распознавания формата diff --git a/plugins/arclite/project.ini b/plugins/arclite/project.ini index ee2029d338..4a988b3e27 100644 --- a/plugins/arclite/project.ini +++ b/plugins/arclite/project.ini @@ -2,4 +2,4 @@ MODULE = arclite VER_MAJOR = 3 VER_MINOR = 0 -VER_BUILD = 252 +VER_BUILD = 253 diff --git a/plugins/arclite/sysutils.cpp b/plugins/arclite/sysutils.cpp index 236a7190e6..8c0a83c9c4 100644 --- a/plugins/arclite/sysutils.cpp +++ b/plugins/arclite/sysutils.cpp @@ -2,6 +2,12 @@ #include "farutils.hpp" #include "sysutils.hpp" +#ifdef _MSC_VER +# pragma warning (disable : 4996) +#endif + +namespace Far { extern FarStandardFunctions g_fsf; } + HINSTANCE g_h_instance = nullptr; CriticalSection& GetSync() @@ -243,11 +249,15 @@ bool File::get_info_nt(BY_HANDLE_FILE_INFORMATION& info) { } bool File::exists(const wstring& file_path) { + return attributes(file_path) != INVALID_FILE_ATTRIBUTES; +} + +DWORD File::attributes(const wstring& file_path) { ArclitePrivateInfo* system_functions = Far::get_system_functions(); if (system_functions) - return system_functions->GetFileAttributes(long_path(file_path).c_str()) != INVALID_FILE_ATTRIBUTES; + return system_functions->GetFileAttributes(long_path(file_path).c_str()); else - return GetFileAttributesW(long_path(file_path).c_str()) != INVALID_FILE_ATTRIBUTES; + return GetFileAttributesW(long_path(file_path).c_str()); } void File::set_attr(const wstring& file_path, DWORD attr) { @@ -563,6 +573,7 @@ bool Key::delete_sub_key_nt(const wchar_t* name) { } FileEnum::FileEnum(const wstring& file_mask): file_mask(file_mask), h_find(INVALID_HANDLE_VALUE) { + n_far_items = -1; } FileEnum::~FileEnum() { @@ -577,12 +588,60 @@ bool FileEnum::next() { return more; } +static int WINAPI find_cb(const struct PluginPanelItem *FData, const wchar_t *FullName, void *Param) +{ + (void)FullName; + return ((FileEnum *)Param)->far_emum_cb(*FData); +} + +int FileEnum::far_emum_cb(const PluginPanelItem& item) +{ + far_items.emplace_back(); + auto& fdata = far_items.back(); + + fdata.dwFileAttributes = static_cast(item.FileAttributes & 0xFFFFFFFF); + fdata.ftCreationTime = item.CreationTime; + fdata.ftLastAccessTime = item.LastAccessTime; + fdata.ftLastWriteTime = item.LastWriteTime; + fdata.nFileSizeHigh = static_cast((item.FileSize >> 32) & 0xFFFFFFFF); + fdata.nFileSizeLow = static_cast(item.FileSize & 0xFFFFFFFF); + fdata.dwReserved0 = static_cast(item.Reserved[0]); + fdata.dwReserved1 = static_cast(item.Reserved[1]); + wcscpy(fdata.cAlternateFileName, null_to_empty(item.AlternateFileName)); + wcsncpy(fdata.cFileName, null_to_empty(item.FileName), sizeof(fdata.cFileName)/sizeof(fdata.cFileName[0])); + + ++n_far_items; + return TRUE; +} + bool FileEnum::next_nt(bool& more) { - while (true) { + for (;;) { if (h_find == INVALID_HANDLE_VALUE) { - h_find = FindFirstFileW(long_path(file_mask).c_str(), &find_data); - if (h_find == INVALID_HANDLE_VALUE) - return false; + if (n_far_items >= 0) { + if (!(more = n_far_items > 0)) + return true; + find_data = far_items.front(); + far_items.pop_front(); + --n_far_items; + } + else { + if ((h_find = FindFirstFileW(long_path(file_mask).c_str(), &find_data)) == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_ACCESS_DENIED) { // + auto dir = extract_file_path(file_mask); // M$ FindFirst/NextFile doesn't work for junction/symlink folder. + auto msk = extract_file_name(file_mask); // Try to use FarRecursiveSearch in such case. + if (!dir.empty() && !msk.empty()) { // + auto attr = File::attributes(dir); // + if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) { + n_far_items = 0; + Far::g_fsf.FarRecursiveSearch(long_path(dir).data(), msk.data(), find_cb, FRS_NONE, this); + continue; + } + } + } + more = false; + return false; + } + } } else { if (!FindNextFileW(h_find, &find_data)) { diff --git a/plugins/arclite/sysutils.hpp b/plugins/arclite/sysutils.hpp index 6429fb799b..c527a82e35 100644 --- a/plugins/arclite/sysutils.hpp +++ b/plugins/arclite/sysutils.hpp @@ -93,6 +93,7 @@ class File: private NonCopyable { DWORD size_ret; return DeviceIoControl(h_file, code, nullptr, 0, &data, sizeof(Type), &size_ret, nullptr) != 0; } + static DWORD attributes(const wstring& file_path) throw(); static bool exists(const wstring& file_path) throw(); static void set_attr(const wstring& file_path, DWORD attr); static bool set_attr_nt(const wstring& file_path, DWORD attr) throw(); @@ -148,6 +149,8 @@ class FileEnum: private NonCopyable { wstring file_mask; HANDLE h_find; FindData find_data; + int n_far_items; + std::list far_items; public: FileEnum(const wstring& file_mask) throw(); ~FileEnum() throw(); @@ -156,6 +159,8 @@ class FileEnum: private NonCopyable { const FindData& data() const throw() { return find_data; } +public: + int far_emum_cb(const PluginPanelItem& item); }; class DirList: public FileEnum {