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:
parent
9cb8fce854
commit
a9d203a60a
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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?"),
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user