Fix toggling "Read-only attribute in Windows" command wrong behaviour

Fix toggling "Read-only attribute in Windows" command wrong behaviour due to invalid file attribute(s) or insufficient user rights.

Fix #16734, close #16733
This commit is contained in:
xomx 2025-06-24 00:01:19 +02:00 committed by Don HO
parent e8843222ae
commit e38016e3f5
3 changed files with 19 additions and 10 deletions

View File

@ -1517,21 +1517,29 @@ bool removeReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath)
return (::SetFileAttributes(fileFullPath, dwFileAttribs) != FALSE);
}
// return true when set to read-only, false otherwise
bool toggleReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath)
// return false when failed, otherwise true and then the isChangedToReadOnly output will be set
// accordingly to the changed file R/O-state
bool toggleReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath, bool& isChangedToReadOnly)
{
DWORD dwFileAttribs = ::GetFileAttributes(fileFullPath);
if (dwFileAttribs == INVALID_FILE_ATTRIBUTES || (dwFileAttribs & FILE_ATTRIBUTE_DIRECTORY))
return false;
if (dwFileAttribs & FILE_ATTRIBUTE_READONLY)
dwFileAttribs &= ~FILE_ATTRIBUTE_READONLY;
else
dwFileAttribs |= FILE_ATTRIBUTE_READONLY;
::SetFileAttributes(fileFullPath, dwFileAttribs);
return (dwFileAttribs & FILE_ATTRIBUTE_READONLY) != 0;
if (::SetFileAttributes(fileFullPath, dwFileAttribs))
{
isChangedToReadOnly = (dwFileAttribs & FILE_ATTRIBUTE_READONLY) != 0;
return true;
}
else
{
// probably the ERROR_ACCESS_DENIED (5) (TODO: UAC-prompt candidate)
return false;
}
}
// "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to disable all string parsing

View File

@ -220,7 +220,7 @@ std::wstring getDateTimeStrFrom(const std::wstring& dateTimeFormat, const SYSTEM
HFONT createFont(const wchar_t* fontName, int fontSize, bool isBold, HWND hDestParent);
bool removeReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath);
bool toggleReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath);
bool toggleReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath, bool& isChangedToReadOnly);
bool isWin32NamespacePrefixedFileName(const std::wstring& fileName);
bool isWin32NamespacePrefixedFileName(const wchar_t* szFileName);

View File

@ -2107,9 +2107,10 @@ void Notepad_plus::command(int id)
case IDM_EDIT_TOGGLESYSTEMREADONLY:
{
Buffer * buf = _pEditView->getCurrentBuffer();
bool isSysReadOnly = toggleReadOnlyFlagFromFileAttributes(buf->getFullPathName());
buf->setFileReadOnly(isSysReadOnly);
Buffer* buf = _pEditView->getCurrentBuffer();
bool isSysReadOnly = false;
if (toggleReadOnlyFlagFromFileAttributes(buf->getFullPathName(), isSysReadOnly))
buf->setFileReadOnly(isSysReadOnly);
}
break;