Fix file status detection issue under Windows XP (32-bit only)

Close #4226
This commit is contained in:
d0vgan 2018-02-26 11:59:40 +02:00 committed by Don HO
parent 6c9a5a2afe
commit 58fa70b580
2 changed files with 72 additions and 2 deletions

View File

@ -34,6 +34,7 @@
#include "Common.h"
#include "../Utf8.h"
#include <Parameters.h>
WcharMbcsConvertor* WcharMbcsConvertor::_pSelf = new WcharMbcsConvertor;
@ -1192,4 +1193,65 @@ bool isAssoCommandExisting(LPCTSTR FullPathName)
}
return isAssoCommandExisting;
}
}
#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_cast<decltype(_Stat->st_atime)>(filetime_to_time_ull(&accessTime));
_Stat->st_ctime = static_cast<decltype(_Stat->st_ctime)>(filetime_to_time_ull(&creationTime));
_Stat->st_mtime = static_cast<decltype(_Stat->st_mtime)>(filetime_to_time_ull(&writeTime));
_Stat->st_size = static_cast<decltype(_Stat->st_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

View File

@ -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<TCHAR> 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