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);

Reply via email to