From 58fa70b5808592533adc1224daa783fe39837f8e Mon Sep 17 00:00:00 2001 From: d0vgan Date: Mon, 26 Feb 2018 11:59:40 +0200 Subject: [PATCH] Fix file status detection issue under Windows XP (32-bit only) Close #4226 --- PowerEditor/src/MISC/Common/Common.cpp | 64 +++++++++++++++++++++++++- PowerEditor/src/MISC/Common/Common.h | 10 +++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp index 3767864b..cc444a9a 100644 --- a/PowerEditor/src/MISC/Common/Common.cpp +++ b/PowerEditor/src/MISC/Common/Common.cpp @@ -34,6 +34,7 @@ #include "Common.h" #include "../Utf8.h" +#include WcharMbcsConvertor* WcharMbcsConvertor::_pSelf = new WcharMbcsConvertor; @@ -1192,4 +1193,65 @@ bool isAssoCommandExisting(LPCTSTR FullPathName) } return isAssoCommandExisting; -} \ No newline at end of file +} + +#ifndef _WIN64 +static bool IsWindows2000orXP() +{ + bool isWin2kXP = false; + switch (NppParameters::getInstance()->getWinVersion()) + { + case WV_W2K: + case WV_XP: + case WV_S2003: + isWin2kXP = true; + break; + } + return isWin2kXP; +} + +static ULONGLONG filetime_to_time_ull(const FILETIME* ft) +{ + ULARGE_INTEGER ull; + ull.LowPart = ft->dwLowDateTime; + ull.HighPart = ft->dwHighDateTime; + return (ull.QuadPart / 10000000ULL - 11644473600ULL); +} + +int custom_wstat(wchar_t const* _FileName, struct _stat* _Stat) +{ + static bool isWin2kXP = IsWindows2000orXP(); + if (!isWin2kXP) + return _wstat(_FileName, _Stat); + + // In Visual Studio 2015, _wstat always returns -1 in Windows XP. + // So here is a WinAPI-based implementation of _wstat. + int nResult = -1; + HANDLE hFile = ::CreateFile(_FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + LARGE_INTEGER fileSize; + FILETIME creationTime, accessTime, writeTime; + if (::GetFileSizeEx(hFile, &fileSize) && + ::GetFileTime(hFile, &creationTime, &accessTime, &writeTime)) + { + DWORD dwAttr = ::GetFileAttributes(_FileName); + ::ZeroMemory(_Stat, sizeof(struct _stat)); + _Stat->st_atime = static_castst_atime)>(filetime_to_time_ull(&accessTime)); + _Stat->st_ctime = static_castst_ctime)>(filetime_to_time_ull(&creationTime)); + _Stat->st_mtime = static_castst_mtime)>(filetime_to_time_ull(&writeTime)); + _Stat->st_size = static_castst_size)>(fileSize.QuadPart); + _Stat->st_mode = _S_IREAD | _S_IEXEC; // S_IEXEC : Execute (for ordinary files) or search (for directories) + if ((dwAttr & FILE_ATTRIBUTE_READONLY) == 0) + _Stat->st_mode |= _S_IWRITE; + if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0) + _Stat->st_mode |= _S_IFDIR; + else + _Stat->st_mode |= _S_IFREG; + nResult = 0; + } + ::CloseHandle(hFile); + } + return nResult; +} +#endif diff --git a/PowerEditor/src/MISC/Common/Common.h b/PowerEditor/src/MISC/Common/Common.h index 7f130bdf..a7514812 100644 --- a/PowerEditor/src/MISC/Common/Common.h +++ b/PowerEditor/src/MISC/Common/Common.h @@ -62,7 +62,11 @@ const bool dirDown = false; #define generic_sscanf swscanf #define generic_fopen _wfopen #define generic_fgets fgetws -#define generic_stat _wstat +#ifdef _WIN64 + #define generic_stat _wstat +#else + #define generic_stat custom_wstat +#endif #define COPYDATA_FILENAMES COPYDATA_FILENAMESW typedef std::basic_string generic_string; @@ -192,3 +196,7 @@ HWND CreateToolTip(int toolID, HWND hDlg, HINSTANCE hInst, const PTSTR pszText); bool isCertificateValidated(const generic_string & fullFilePath, const generic_string & subjectName2check); bool isAssoCommandExisting(LPCTSTR FullPathName); + +#ifndef _WIN64 +int custom_wstat(wchar_t const* _FileName, struct _stat* _Stat); +#endif