sal/osl/w32/file_dirvol.cxx | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
New commits: commit eb3e271f4598d81d601eafee90a0d0d4223b8dc6 Author: Mike Kaganski <[email protected]> AuthorDate: Sat Oct 11 18:49:56 2025 +0500 Commit: Thorsten Behrens <[email protected]> CommitDate: Tue Oct 14 23:48:12 2025 +0200 tdf#150118: fix call to AccessCheck It turns out, that despite PrivilegeSet argument is documented as optional, the function fails without it. So my advise to avoid it was incorrect after all. Also, SAL_WARN takes area as the first argument, and a stream as the second. It makes no sense to "recode" GetLastError result: it is most informative as is. Change-Id: Ifd4d4ddc96f5e001c898f7331148b47aeee77f2f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192227 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> (cherry picked from commit 1a4f72f03b1bd49d486e52135e78971242fae649) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192231 Tested-by: allotropia jenkins <[email protected]> Reviewed-by: Thorsten Behrens <[email protected]> diff --git a/sal/osl/w32/file_dirvol.cxx b/sal/osl/w32/file_dirvol.cxx index b04f8e4b15b3..fb536914f9b3 100644 --- a/sal/osl/w32/file_dirvol.cxx +++ b/sal/osl/w32/file_dirvol.cxx @@ -1545,10 +1545,12 @@ oslFileError SAL_CALL osl_getFileStatus( = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }; DWORD grantedAccess = 0; BOOL accessStatus = TRUE; + PRIVILEGE_SET privSet; + DWORD privSetSize = sizeof(privSet); // https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-accesscheck BOOL bResult = AccessCheck(pSD, hImpersonationToken, FILE_GENERIC_WRITE, &mapping, - nullptr, nullptr, &grantedAccess, &accessStatus); + &privSet, &privSetSize, &grantedAccess, &accessStatus); if (bResult) { @@ -1560,13 +1562,13 @@ oslFileError SAL_CALL osl_getFileStatus( } else { - SAL_WARN("AccessCheck API failed with: ", oslTranslateFileError(GetLastError())); + SAL_WARN("sal.osl", "AccessCheck API failed with: " << GetLastError()); } LocalFree(pSD); // free memory } else { - SAL_WARN("GetNamedSecurityInfoW API failed with: ", aResult); + SAL_WARN("sal.osl", "GetNamedSecurityInfoW API failed with: " << aResult); } CloseHandle(hImpersonationToken); // free memory CloseHandle(hProcessToken); // free memory commit 673aa9fa646e7ed8f7dd81868185a140d2b5866f Author: Balazs Varga <[email protected]> AuthorDate: Fri Oct 10 09:38:42 2025 +0200 Commit: Thorsten Behrens <[email protected]> CommitDate: Tue Oct 14 23:47:57 2025 +0200 tdf#150118 check file permissions on windows if have no readonly attribute already set on a file. Check if the file has write access, if not, set the read only flag. Change-Id: Id3b16ffffd1d5aeb09feed7b5ff2da51fba9174c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192150 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Jenkins (cherry picked from commit 1b5d039d8b5861b5ea21ef00ff521c6e2565105f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192171 Tested-by: allotropia jenkins <[email protected]> diff --git a/sal/osl/w32/file_dirvol.cxx b/sal/osl/w32/file_dirvol.cxx index 7599be112a8d..b04f8e4b15b3 100644 --- a/sal/osl/w32/file_dirvol.cxx +++ b/sal/osl/w32/file_dirvol.cxx @@ -18,6 +18,7 @@ */ #include <systools/win32/uwinapi.h> +#include <aclapi.h> #include "file_url.hxx" #include "filetime.hxx" @@ -1521,6 +1522,56 @@ oslFileError SAL_CALL osl_getFileStatus( // https://learn.microsoft.com/en-us/windows/desktop/FileIO/file-attribute-constants if (pStatus->uAttributes & FILE_ATTRIBUTE_DIRECTORY) pStatus->uAttributes &= ~sal_uInt64(FILE_ATTRIBUTE_READONLY); + + // tdf#150118: if there is no Read Only attribute set, lets check if the user has write access on the file + if ( (pStatus->uAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY)) == 0 ) + { + HANDLE hProcessToken = nullptr; + OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &hProcessToken); + + HANDLE hImpersonationToken = nullptr; + DuplicateToken(hProcessToken, SecurityImpersonation, &hImpersonationToken); + + PSECURITY_DESCRIPTOR pSD = nullptr; + // https://learn.microsoft.com/en-us/windows/win32/api/aclapi/nf-aclapi-getnamedsecurityinfow + DWORD aResult = GetNamedSecurityInfoW( + o3tl::toW(sFullPath.getStr()), SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + nullptr, nullptr, nullptr, nullptr, &pSD); + + if (aResult == ERROR_SUCCESS) + { + GENERIC_MAPPING mapping + = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }; + DWORD grantedAccess = 0; + BOOL accessStatus = TRUE; + + // https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-accesscheck + BOOL bResult = AccessCheck(pSD, hImpersonationToken, FILE_GENERIC_WRITE, &mapping, + nullptr, nullptr, &grantedAccess, &accessStatus); + + if (bResult) + { + if (!accessStatus) + { + // User does NOT have write access: set Read Only attribute + pStatus->uAttributes |= sal_uInt64(FILE_ATTRIBUTE_READONLY); + } + } + else + { + SAL_WARN("AccessCheck API failed with: ", oslTranslateFileError(GetLastError())); + } + LocalFree(pSD); // free memory + } + else + { + SAL_WARN("GetNamedSecurityInfoW API failed with: ", aResult); + } + CloseHandle(hImpersonationToken); // free memory + CloseHandle(hProcessToken); // free memory + } + pStatus->uValidFields |= osl_FileStatus_Mask_Attributes; pStatus->uFileSize = static_cast<sal_uInt64>(pItemImpl->FindData.nFileSizeLow) + (static_cast<sal_uInt64>(pItemImpl->FindData.nFileSizeHigh) << 32);
