From e38016e3f52e49eaf22974008e46f98fc85ef080 Mon Sep 17 00:00:00 2001 From: xomx Date: Tue, 24 Jun 2025 00:01:19 +0200 Subject: [PATCH] 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 --- PowerEditor/src/MISC/Common/Common.cpp | 20 ++++++++++++++------ PowerEditor/src/MISC/Common/Common.h | 2 +- PowerEditor/src/NppCommands.cpp | 7 ++++--- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp index e74537982..a29ecd888 100644 --- a/PowerEditor/src/MISC/Common/Common.cpp +++ b/PowerEditor/src/MISC/Common/Common.cpp @@ -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 diff --git a/PowerEditor/src/MISC/Common/Common.h b/PowerEditor/src/MISC/Common/Common.h index 7159eb732..7c624ab00 100644 --- a/PowerEditor/src/MISC/Common/Common.h +++ b/PowerEditor/src/MISC/Common/Common.h @@ -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); diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp index 2dc5dfec0..5aaffe055 100644 --- a/PowerEditor/src/NppCommands.cpp +++ b/PowerEditor/src/NppCommands.cpp @@ -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;