Deprecate wstat/stat in favour of WinAPI GetFileAttributesEx - unifies code and behaviour between Windows versions

Fixes #4491, fixes #3969, fixes #2535, fixes #215, close #4541
This commit is contained in:
Silent 2018-05-31 16:13:01 +02:00 committed by Don HO
parent 9cb8fce854
commit a9d203a60a
6 changed files with 54 additions and 96 deletions

View File

@ -1194,64 +1194,3 @@ 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,11 +62,6 @@ const bool dirDown = false;
#define generic_sscanf swscanf
#define generic_fopen _wfopen
#define generic_fgets fgetws
#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;
@ -196,7 +191,3 @@ 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

View File

@ -1913,7 +1913,7 @@ void Notepad_plus::command(int id)
generic_string characterNumber = TEXT("");
Buffer * curBuf = _pEditView->getCurrentBuffer();
int fileLen = curBuf->getFileLength();
int64_t fileLen = curBuf->getFileLength();
if (fileLen != -1)
{
@ -1935,7 +1935,7 @@ void Notepad_plus::command(int id)
characterNumber += TEXT("\r");
characterNumber += fileLenLabel;
characterNumber += commafyInt(static_cast<UINT64>(fileLen)).c_str();
characterNumber += commafyInt(static_cast<size_t>(fileLen)).c_str();
characterNumber += TEXT("\r");
characterNumber += TEXT("\r");
}

View File

@ -1076,10 +1076,10 @@ bool NppParameters::load()
BOOL doRecover = FALSE;
if (::PathFileExists(langs_xml_path.c_str()))
{
struct _stat buf;
WIN32_FILE_ATTRIBUTE_DATA attributes;
if (generic_stat(langs_xml_path.c_str(), &buf)==0)
if (buf.st_size == 0)
if (GetFileAttributesEx(langs_xml_path.c_str(), GetFileExInfoStandard, &attributes) != 0)
if (attributes.nFileSizeLow == 0 && attributes.nFileSizeHigh == 0)
doRecover = _pNativeLangSpeaker->messageBox("LoadLangsFailed",
NULL,
TEXT("Load langs.xml failed!\rDo you want to recover your langs.xml?"),

View File

@ -313,17 +313,18 @@ void Buffer::reload()
}
}
int Buffer::getFileLength() const
int64_t Buffer::getFileLength() const
{
if (_currentStatus == DOC_UNNAMED)
return -1;
struct _stat buf;
if (PathFileExists(_fullPathName.c_str()))
WIN32_FILE_ATTRIBUTE_DATA attributes;
if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
{
if (!generic_stat(_fullPathName.c_str(), &buf))
return buf.st_size;
LARGE_INTEGER size;
size.LowPart = attributes.nFileSizeLow;
size.HighPart = attributes.nFileSizeHigh;
return size.QuadPart;
}
return -1;
}
@ -331,26 +332,53 @@ int Buffer::getFileLength() const
generic_string Buffer::getFileTime(fileTimeType ftt) const
{
if (_currentStatus == DOC_UNNAMED)
return generic_string();
generic_string result;
struct _stat buf;
if (PathFileExists(_fullPathName.c_str()))
if (_currentStatus != DOC_UNNAMED)
{
if (!generic_stat(_fullPathName.c_str(), &buf))
WIN32_FILE_ATTRIBUTE_DATA attributes;
if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
{
time_t rawtime = (ftt == ft_created ? buf.st_ctime : (ftt == ft_modified ? buf.st_mtime : buf.st_atime));
tm *timeinfo = localtime(&rawtime);
const int temBufLen = 64;
TCHAR tmpbuf[temBufLen];
FILETIME rawtime;
switch (ftt)
{
case ft_created:
rawtime = attributes.ftCreationTime;
break;
case ft_modified:
rawtime = attributes.ftLastWriteTime;
break;
default:
rawtime = attributes.ftLastAccessTime;
break;
}
generic_strftime(tmpbuf, temBufLen, TEXT("%Y-%m-%d %H:%M:%S"), timeinfo);
return tmpbuf;
SYSTEMTIME utcSystemTime, localSystemTime;
FileTimeToSystemTime(&rawtime, &utcSystemTime);
SystemTimeToTzSpecificLocalTime(nullptr, &utcSystemTime, &localSystemTime);
int cbSize = GetDateFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, nullptr, 0);
if (cbSize != 0)
{
TCHAR* buf = new TCHAR[cbSize];
GetDateFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, buf, cbSize);
result += buf;
delete[] buf;
}
result += ' ';
cbSize = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, nullptr, 0);
if (cbSize != 0)
{
TCHAR* buf = new TCHAR[cbSize];
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, buf, cbSize);
result += buf;
delete[] buf;
}
}
}
return generic_string();
return result;
}

View File

@ -310,7 +310,7 @@ public:
return _pManager->docLength(_id);
}
int getFileLength() const; // return file length. -1 if file is not existing.
int64_t getFileLength() const; // return file length. -1 if file is not existing.
enum fileTimeType { ft_created, ft_modified, ft_accessed };
generic_string getFileTime(fileTimeType ftt) const;