include/rtl/stringconcat.hxx                |    2 
 sal/osl/w32/security.cxx                    |  611 ++++++++++------------------
 sal/qa/rtl/strings/test_oustring_concat.cxx |    3 
 3 files changed, 233 insertions(+), 383 deletions(-)

New commits:
commit e1b2c00b0a69f7ecebcba7b5486a677b46c0ef1b
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Jul 12 19:33:48 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Jul 13 14:12:59 2025 +0200

    Refactor code to be more C++
    
    Use OUString and OUStringBuffer for memory management; use RAII to
    close handles. Deduplicate some code. Move things around to avoid
    forward declarations. Use o3tl::temporary to avoid dummy variables.
    Reduce memory allocations.
    
    Change-Id: I34b686d3e61a6a163a31b887484c29732ac04b74
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187777
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/sal/osl/w32/security.cxx b/sal/osl/w32/security.cxx
index 0e9bc96c9b78..46091a72e7f3 100644
--- a/sal/osl/w32/security.cxx
+++ b/sal/osl/w32/security.cxx
@@ -25,25 +25,171 @@
 #include <osl/diagnose.h>
 #include <osl/thread.h>
 #include <osl/file.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
 #include <systools/win32/comtools.hxx>
 #include <systools/win32/uwinapi.h>
 #include <sddl.h>
 #include <sal/macros.h>
 #include <sal/log.hxx>
 #include <o3tl/char16_t2wchar_t.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/temporary.hxx>
 #include "secimpl.hxx"
 
+namespace
+{
 /* To get an impersonation token we need to create an impersonation
    duplicate so every access token has to be created with duplicate
    access rights */
 
-#define TOKEN_DUP_QUERY (TOKEN_QUERY|TOKEN_DUPLICATE)
+constexpr auto TOKEN_DUP_QUERY = TOKEN_QUERY | TOKEN_DUPLICATE;
+
+OUString GetSpecialFolder(REFKNOWNFOLDERID rFolder)
+{
+    sal::systools::CoTaskMemAllocated<wchar_t> PathW;
+    if (SUCCEEDED(SHGetKnownFolderPath(rFolder, KF_FLAG_CREATE, nullptr, 
&PathW)))
+        return OUString(o3tl::toU(PathW));
+
+    return {};
+}
+
+class SafeHandle
+{
+public:
+    SafeHandle(HANDLE h = nullptr, bool close = true) : handle(h), 
needToClose(close) {}
+    SafeHandle(const SafeHandle&) = delete;
+    SafeHandle(SafeHandle&&) = delete;
+    void operator=(const SafeHandle&) = delete;
+    void operator=(SafeHandle&&) = delete;
+    ~SafeHandle()
+    {
+        if (needToClose && handle)
+            CloseHandle(handle);
+    }
+    operator HANDLE() const { return handle; }
+    HANDLE* operator&() { return &handle; }
+
+private:
+    HANDLE handle;
+    bool needToClose;
+};
+
+SafeHandle getAccessToken(const oslSecurity Security, DWORD desiredAccess = 
TOKEN_DUP_QUERY)
+{
+    if (auto* pSecImpl = static_cast<oslSecurityImpl*>(Security))
+        if (pSecImpl->m_hToken)
+            return SafeHandle(pSecImpl->m_hToken, false);
+
+    HANDLE token = nullptr;
+    OpenProcessToken(GetCurrentProcess(), desiredAccess, &token);
+    return SafeHandle(token);
+}
 
-static bool GetSpecialFolder(rtl_uString **strPath, REFKNOWNFOLDERID rFolder);
 // We use LPCTSTR here, because we use it with SE_foo_NAME constants
 // which are defined in winnt.h as UNICODE-dependent TEXT("PrivilegeName")
-static bool Privilege(LPCTSTR pszPrivilege, bool bEnable);
-static bool getUserNameImpl(oslSecurity Security, rtl_uString **strName, bool 
bIncludeDomain);
+bool Privilege(LPCTSTR strPrivilege, bool bEnable)
+{
+    TOKEN_PRIVILEGES tp{ .PrivilegeCount = 1 };
+
+    // get the luid
+    if (!LookupPrivilegeValue(nullptr, strPrivilege, &tp.Privileges[0].Luid))
+        return false;
+
+    tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
+
+    // obtain the processes token
+    auto hToken = getAccessToken(nullptr, TOKEN_ADJUST_PRIVILEGES | 
TOKEN_DUP_QUERY);
+
+    // enable or disable the privilege
+    return hToken && AdjustTokenPrivileges(hToken, FALSE, &tp, 0, nullptr, 
nullptr);
+}
+
+// Returned pointer must be free()d
+PTOKEN_USER getUserTokenInfo(HANDLE hAccessToken)
+{
+    DWORD nInfoBuffer = 512;
+    auto pInfoBuffer = static_cast<PTOKEN_USER>(malloc(nInfoBuffer));
+    assert(pInfoBuffer);
+
+    while (!GetTokenInformation(hAccessToken, TokenUser, pInfoBuffer, 
nInfoBuffer, &nInfoBuffer))
+    {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        {
+            if (auto p = static_cast<PTOKEN_USER>(realloc(pInfoBuffer, 
nInfoBuffer)))
+            {
+                pInfoBuffer = p;
+                continue;
+            }
+        }
+
+        free(pInfoBuffer);
+        return nullptr;
+    }
+
+    return pInfoBuffer;
+}
+
+bool getUserNameFromWNet(rtl_uString** strName)
+{
+    DWORD needed = 0;
+    WNetGetUserW(nullptr, nullptr, &needed);
+
+    if (needed > 1 && needed <= o3tl::make_unsigned(SAL_MAX_INT32))
+    {
+        // OUStringBuffer has space for an extra zero character
+        if (OUStringBuffer buffer(needed - 1);
+            WNetGetUserW(nullptr, o3tl::toW(buffer.appendUninitialized(needed 
- 1)), &needed)
+            == NO_ERROR)
+        {
+            rtl_uString_assign(strName, buffer.makeStringAndClear().pData);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool getUserNameImpl(oslSecurity Security, rtl_uString** strName, bool 
bIncludeDomain)
+{
+    if (!Security)
+        return false;
+
+    if (auto hAccessToken = getAccessToken(Security))
+    {
+        PTOKEN_USER pInfoBuffer = getUserTokenInfo(hAccessToken);
+        if (!pInfoBuffer)
+            return false;
+
+        sal_Unicode UserName[256];
+        sal_Unicode DomainName[256];
+        DWORD nUserName = std::size(UserName);
+        DWORD nDomainName = std::size(DomainName);
+
+        bool bResult = LookupAccountSidW(nullptr, pInfoBuffer->User.Sid, 
o3tl::toW(UserName),
+                                         &nUserName, o3tl::toW(DomainName), 
&nDomainName,
+                                         &o3tl::temporary(SID_NAME_USE()));
+        free(pInfoBuffer);
+        if (!bResult)
+            return false;
+
+        OUString aResult
+            = bIncludeDomain ? OUString::Concat(DomainName) + "/" + UserName : 
OUString(UserName);
+        rtl_uString_assign(strName, aResult.pData);
+        return true;
+    }
+
+    if (getUserNameFromWNet(strName))
+        return true;
+
+    if (auto pSecImpl = static_cast<oslSecurityImpl*>(Security); 
pSecImpl->m_User[0] != '
+    {
+        rtl_uString_newFromStr(strName, 
o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
+        return true;
+    }
+
+    return false;
+}
+} // namespace
 
 oslSecurity SAL_CALL osl_getCurrentSecurity(void)
 {
@@ -62,12 +208,10 @@ oslSecurityError SAL_CALL osl_loginUser( rtl_uString 
*strUserName, rtl_uString *
 {
     oslSecurityError ret;
 
-    sal_Unicode*    strUser;
-    sal_Unicode*    strDomain = 
o3tl::toU(_wcsdup(o3tl::toW(rtl_uString_getStr(strUserName))));
-    HANDLE  hUserToken;
-    LUID luid;
+    wchar_t* strDomain = _wcsdup(o3tl::toW(rtl_uString_getStr(strUserName)));
+    wchar_t* strUser = wcschr(strDomain, L'/');
 
-    if (nullptr != (strUser = o3tl::toU(wcschr(o3tl::toW(strDomain), L'/'))))
+    if (strUser)
         *strUser++ = L'
     else
     {
@@ -76,10 +220,10 @@ oslSecurityError SAL_CALL osl_loginUser( rtl_uString 
*strUserName, rtl_uString *
     }
 
     // this process must have the right: 'act as a part of operatingsystem'
-    OSL_ASSERT(LookupPrivilegeValue(nullptr, SE_TCB_NAME, &luid));
-    (void) luid;
+    OSL_ASSERT(LookupPrivilegeValue(nullptr, SE_TCB_NAME, 
&o3tl::temporary(LUID())));
 
-    if (LogonUserW(o3tl::toW(strUser), strDomain ? o3tl::toW(strDomain) : L"", 
o3tl::toW(rtl_uString_getStr(strPasswd)),
+    HANDLE  hUserToken;
+    if (LogonUserW(strUser, strDomain ? strDomain : L"", 
o3tl::toW(rtl_uString_getStr(strPasswd)),
                   LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    &hUserToken))
     {
@@ -89,8 +233,10 @@ oslSecurityError SAL_CALL osl_loginUser( rtl_uString 
*strUserName, rtl_uString *
             pSecImpl->m_pNetResource = nullptr;
             pSecImpl->m_hToken = hUserToken;
             pSecImpl->m_hProfile = nullptr;
-            wcscpy(o3tl::toW(pSecImpl->m_User), o3tl::toW(strUser));
+            wcscpy(o3tl::toW(pSecImpl->m_User), strUser);
         }
+        else
+            CloseHandle(hUserToken);
         *pSecurity = pSecImpl;
         ret = pSecImpl ? osl_Security_E_None : osl_Security_E_Unknown;
     }
@@ -112,67 +258,43 @@ oslSecurityError SAL_CALL 
osl_loginUserOnFileServer(rtl_uString *strUserName,
                                                     rtl_uString *strFileServer,
                                                     oslSecurity *pSecurity)
 {
-    oslSecurityError    ret;
-    DWORD               err;
-    NETRESOURCEW        netResource;
-    sal_Unicode*                remoteName;
-    sal_Unicode*                userName;
-
-    remoteName  = static_cast<sal_Unicode 
*>(malloc((rtl_uString_getLength(strFileServer) + 
rtl_uString_getLength(strUserName) + 4) * sizeof(sal_Unicode)));
-    userName    = static_cast<sal_Unicode 
*>(malloc((rtl_uString_getLength(strFileServer) + 
rtl_uString_getLength(strUserName) + 2) * sizeof(sal_Unicode)));
-
-    wcscpy(o3tl::toW(remoteName), L"\\");
-    wcscat(o3tl::toW(remoteName), 
o3tl::toW(rtl_uString_getStr(strFileServer)));
-    wcscat(o3tl::toW(remoteName), L"\");
-    wcscat(o3tl::toW(remoteName), o3tl::toW(rtl_uString_getStr(strUserName)));
-
-    wcscpy(o3tl::toW(userName), o3tl::toW(rtl_uString_getStr(strFileServer)));
-    wcscat(o3tl::toW(userName), L"\");
-    wcscat(o3tl::toW(userName), o3tl::toW(rtl_uString_getStr(strUserName)));
-
-    netResource.dwScope         = RESOURCE_GLOBALNET;
-    netResource.dwType          = RESOURCETYPE_DISK;
-    netResource.dwDisplayType   = RESOURCEDISPLAYTYPE_SHARE;
-    netResource.dwUsage         = RESOURCEUSAGE_CONNECTABLE;
-    netResource.lpLocalName     = nullptr;
-    netResource.lpRemoteName    = o3tl::toW(remoteName);
-    netResource.lpComment       = nullptr;
-    netResource.lpProvider      = nullptr;
-
-    err = WNetAddConnection2W(&netResource, 
o3tl::toW(rtl_uString_getStr(strPasswd)), o3tl::toW(userName), 0);
+    OUString remoteName
+        = "\\" + OUString::unacquired(&strFileServer) + "\" + 
OUString::unacquired(&strUserName);
+    OUString userName
+        = OUString::unacquired(&strFileServer) + "\" + 
OUString::unacquired(&strUserName);
+
+    NETRESOURCEW netResource{ .dwScope = RESOURCE_GLOBALNET,
+                              .dwType = RESOURCETYPE_DISK,
+                              .dwDisplayType = RESOURCEDISPLAYTYPE_SHARE,
+                              .dwUsage = RESOURCEUSAGE_CONNECTABLE,
+                              .lpRemoteName = 
o3tl::toW(rtl_uString_getStr(remoteName.pData)) };
+
+    DWORD err = WNetAddConnection2W(&netResource, 
o3tl::toW(rtl_uString_getStr(strPasswd)),
+                                    o3tl::toW(userName.getStr()), 0);
 
     if ((err == NO_ERROR) || (err == ERROR_ALREADY_ASSIGNED))
     {
-        oslSecurityImpl* pSecImpl = static_cast<oslSecurityImpl 
*>(malloc(sizeof(oslSecurityImpl)));
-        if (pSecImpl)
+        // Allocate it all in one memory block
+        const size_t implSize = sizeof(oslSecurityImpl) + sizeof(NETRESOURCEW)
+                                + (remoteName.getLength() + 1) * 
sizeof(wchar_t);
+        if (oslSecurityImpl* pSecImpl = 
static_cast<oslSecurityImpl*>(malloc(implSize)))
         {
-            pSecImpl->m_pNetResource = static_cast<NETRESOURCEW 
*>(malloc(sizeof(NETRESOURCE)));
-            if (pSecImpl->m_pNetResource)
-            {
-                *pSecImpl->m_pNetResource = netResource;
-                pSecImpl->m_hToken = nullptr;
-                pSecImpl->m_hProfile = nullptr;
-                wcscpy(o3tl::toW(pSecImpl->m_User), 
o3tl::toW(rtl_uString_getStr(strUserName)));
-            }
-            else
-            {
-                free(pSecImpl);
-                pSecImpl = nullptr;
-            }
-        }
-        *pSecurity = pSecImpl;
+            pSecImpl->m_pNetResource = 
reinterpret_cast<NETRESOURCEW*>(pSecImpl + 1);
+            *pSecImpl->m_pNetResource = netResource;
+            pSecImpl->m_pNetResource->lpRemoteName
+                = reinterpret_cast<wchar_t*>(pSecImpl->m_pNetResource + 1);
+            wcscpy(pSecImpl->m_pNetResource->lpRemoteName, 
o3tl::toW(remoteName.getStr()));
+            pSecImpl->m_hToken = nullptr;
+            pSecImpl->m_hProfile = nullptr;
+            assert(o3tl::make_unsigned(strUserName->length) < 
std::size(pSecImpl->m_User));
+            wcscpy(o3tl::toW(pSecImpl->m_User), 
o3tl::toW(rtl_uString_getStr(strUserName)));
 
-        ret = pSecImpl ? osl_Security_E_None : osl_Security_E_Unknown;
-    }
-    else
-    {
-        ret = osl_Security_E_UserUnknown;
+            *pSecurity = pSecImpl;
+            return osl_Security_E_None;
+        }
     }
 
-    free(remoteName);
-    free(userName);
-
-    return ret;
+    return osl_Security_E_UserUnknown;
 }
 
 sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
@@ -180,19 +302,15 @@ sal_Bool SAL_CALL osl_isAdministrator(oslSecurity 
Security)
     if (!Security)
         return false;
 
-    HANDLE                      hImpersonationToken = nullptr;
-    PSID                        psidAdministrators;
-    SID_IDENTIFIER_AUTHORITY    siaNtAuthority = { SECURITY_NT_AUTHORITY };
-    bool                    bSuccess = false;
-
     /* If Security contains an access token we need to duplicate it to an 
impersonation
        access token. NULL works with CheckTokenMembership() as the current 
effective
        impersonation token
      */
 
-    if ( static_cast<oslSecurityImpl*>(Security)->m_hToken )
+    SafeHandle hImpersonationToken;
+    if (HANDLE hToken = static_cast<oslSecurityImpl*>(Security)->m_hToken)
     {
-        if ( !DuplicateToken 
(static_cast<oslSecurityImpl*>(Security)->m_hToken, SecurityImpersonation, 
&hImpersonationToken) )
+        if (!DuplicateToken(hToken, SecurityImpersonation, 
&hImpersonationToken))
             return false;
     }
 
@@ -202,6 +320,9 @@ sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
        complicated checks as described in KB article Q118626: 
http://support.microsoft.com/kb/118626/en-us
     */
 
+    PSID psidAdministrators;
+    SID_IDENTIFIER_AUTHORITY siaNtAuthority = { SECURITY_NT_AUTHORITY };
+    bool bSuccess = false;
     if (AllocateAndInitializeSid(&siaNtAuthority,
                                  2,
                                  SECURITY_BUILTIN_DOMAIN_RID,
@@ -217,9 +338,6 @@ sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
         FreeSid(psidAdministrators);
     }
 
-    if (hImpersonationToken)
-        CloseHandle(hImpersonationToken);
-
     return bSuccess;
 }
 
@@ -231,13 +349,8 @@ void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
     oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
 
     if (pSecImpl->m_pNetResource != nullptr)
-    {
         WNetCancelConnection2W(pSecImpl->m_pNetResource->lpRemoteName, 0, 
true);
 
-        free(pSecImpl->m_pNetResource->lpRemoteName);
-        free(pSecImpl->m_pNetResource);
-    }
-
     if (pSecImpl->m_hToken)
         CloseHandle(pSecImpl->m_hToken);
 
@@ -252,49 +365,12 @@ sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, 
rtl_uString **strIdent)
     if (!Security)
        return false;
 
-    oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
-
-    HANDLE hAccessToken = pSecImpl->m_hToken;
-
-    if (hAccessToken == nullptr)
-        OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
-
-    if (hAccessToken)
+    if (auto hAccessToken = getAccessToken(Security))
     {
-        DWORD  nInfoBuffer = 512;
-        UCHAR* pInfoBuffer = static_cast<UCHAR *>(malloc(nInfoBuffer));
-
-        while (!GetTokenInformation(hAccessToken, TokenUser,
-                                       pInfoBuffer, nInfoBuffer, &nInfoBuffer))
-        {
-            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-            {
-                if (auto p = static_cast<UCHAR *>(realloc(pInfoBuffer, 
nInfoBuffer)))
-                    pInfoBuffer = p;
-                else
-                {
-                    free(pInfoBuffer);
-                    pInfoBuffer = nullptr;
-                    break;
-                }
-            }
-            else
-            {
-                free(pInfoBuffer);
-                pInfoBuffer = nullptr;
-                break;
-            }
-        }
-
-        if (pSecImpl->m_hToken == nullptr)
-            CloseHandle(hAccessToken);
-
-        if (pInfoBuffer)
+        if (PTOKEN_USER pInfoBuffer = getUserTokenInfo(hAccessToken))
         {
-            PSID pSid = reinterpret_cast<PTOKEN_USER>(pInfoBuffer)->User.Sid;
-
             LPWSTR pSidStr = nullptr;
-            bool bResult = ConvertSidToStringSidW(pSid, &pSidStr);
+            bool bResult = ConvertSidToStringSidW(pInfoBuffer->User.Sid, 
&pSidStr);
             if (bResult)
             {
                 rtl_uString_newFromStr(strIdent, o3tl::toU(pSidStr));
@@ -315,24 +391,9 @@ sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, 
rtl_uString **strIdent)
     }
     else
     {
-        DWORD needed = 0;
-
-        WNetGetUserW(nullptr, nullptr, &needed);
-        if (needed < 16)
-            needed = 16;
-
-        if (auto Ident = static_cast<sal_Unicode 
*>(malloc(needed*sizeof(sal_Unicode))))
-        {
-            if (WNetGetUserW(nullptr, o3tl::toW(Ident), &needed) != NO_ERROR)
-            {
-                wcscpy(o3tl::toW(Ident), L"unknown");
-                Ident[7] = L'
-            }
-
-            rtl_uString_newFromStr( strIdent, Ident);
-            free(Ident);
-            return true;
-        }
+        if (!getUserNameFromWNet(strIdent))
+            rtl_uString_newFromStr(strIdent, u"unknown");
+        return true;
     }
     return false;
 }
@@ -352,27 +413,14 @@ sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, 
rtl_uString **pustrDirect
     if (!Security)
         return false;
 
-    rtl_uString *ustrSysDir = nullptr;
-    bool bSuccess = false;
-
     oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
 
-    if (pSecImpl->m_pNetResource != nullptr)
-    {
-        rtl_uString_newFromStr( &ustrSysDir, 
o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
-
-        bSuccess = osl_File_E_None == osl_getFileURLFromSystemPath( 
ustrSysDir, pustrDirectory );
-    }
-    else
-    {
-            bSuccess = GetSpecialFolder(&ustrSysDir, FOLDERID_Documents) &&
-                                 (osl_File_E_None == 
osl_getFileURLFromSystemPath(ustrSysDir, pustrDirectory));
-    }
-
-    if ( ustrSysDir )
-        rtl_uString_release( ustrSysDir );
+    OUString aSysDir = pSecImpl->m_pNetResource
+                           ? 
OUString(o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName))
+                           : GetSpecialFolder(FOLDERID_Documents);
 
-    return bSuccess;
+    return !aSysDir.isEmpty()
+           && osl_File_E_None == osl_getFileURLFromSystemPath(aSysDir.pData, 
pustrDirectory);
 }
 
 sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString 
**pustrDirectory)
@@ -380,46 +428,33 @@ sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, 
rtl_uString **pustrDire
     if (!Security)
         return false;
 
-    bool bSuccess = false;
     oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
 
     if (pSecImpl->m_pNetResource != nullptr)
     {
-        rtl_uString *ustrSysDir = nullptr;
-
-        rtl_uString_newFromStr( &ustrSysDir, 
o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
-        bSuccess = osl_File_E_None == osl_getFileURLFromSystemPath( 
ustrSysDir, pustrDirectory);
+        OUString aSysDir(o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
+        return osl_File_E_None == osl_getFileURLFromSystemPath(aSysDir.pData, 
pustrDirectory);
+    }
 
-        if ( ustrSysDir )
-            rtl_uString_release( ustrSysDir );
+    if (pSecImpl->m_hToken)
+    {
+        /* not implemented */
+        OSL_ASSERT(false);
     }
     else
     {
-        if (pSecImpl->m_hToken)
-        {
-            /* not implemented */
-            OSL_ASSERT(false);
-        }
-        else
+        OUString aFile = GetSpecialFolder(FOLDERID_RoamingAppData);
+        if (aFile.isEmpty())
         {
-            rtl_uString *ustrFile = nullptr;
             sal_Unicode sFile[_MAX_PATH];
-
-            if ( !GetSpecialFolder( &ustrFile, FOLDERID_RoamingAppData) )
-            {
-                OSL_VERIFY(GetWindowsDirectoryW(o3tl::toW(sFile), _MAX_DIR) > 
0);
-
-                rtl_uString_newFromStr( &ustrFile, sFile);
-            }
-
-            bSuccess = osl_File_E_None == 
osl_getFileURLFromSystemPath(ustrFile, pustrDirectory);
-
-            if ( ustrFile )
-                rtl_uString_release( ustrFile );
+            OSL_VERIFY(GetWindowsDirectoryW(o3tl::toW(sFile), 
std::size(sFile)) > 0);
+            aFile = sFile;
         }
+
+        return osl_File_E_None == osl_getFileURLFromSystemPath(aFile.pData, 
pustrDirectory);
     }
 
-    return bSuccess;
+    return false;
 }
 
 sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
@@ -437,46 +472,24 @@ sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity 
Security)
     if (!Privilege(SE_RESTORE_NAME, true))
         return false;
 
-    bool bOk = false;
-    HANDLE hAccessToken = static_cast<oslSecurityImpl*>(Security)->m_hToken;
+    auto hAccessToken = getAccessToken(Security, TOKEN_IMPERSONATE);
 
     /* try to create user profile */
-    if ( !hAccessToken )
-    {
-        /* retrieve security handle if not done before e.g. 
osl_getCurrentSecurity()
-        */
-        HANDLE hProcess = GetCurrentProcess();
-
-        if (hProcess != nullptr)
-        {
-            OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
-            CloseHandle(hProcess);
-        }
-    }
-
-    rtl_uString *buffer = nullptr;
-    PROFILEINFOW pi;
 
-    getUserNameImpl(Security, &buffer, false);
+    OUString buffer;
+    getUserNameImpl(Security, &buffer.pData, false);
 
-    ZeroMemory(&pi, sizeof(pi));
-    pi.dwSize = sizeof(pi);
-    pi.lpUserName = o3tl::toW(rtl_uString_getStr(buffer));
-    pi.dwFlags = PI_NOUI;
+    PROFILEINFOW pi{ .dwSize = sizeof(pi),
+                     .dwFlags = PI_NOUI,
+                     .lpUserName = o3tl::toW(rtl_uString_getStr(buffer.pData)) 
};
 
     if (LoadUserProfileW(hAccessToken, &pi))
     {
         UnloadUserProfile(hAccessToken, pi.hProfile);
-
-        bOk = true;
+        return true;
     }
 
-    rtl_uString_release(buffer);
-
-    if (hAccessToken && (hAccessToken != 
static_cast<oslSecurityImpl*>(Security)->m_hToken))
-        CloseHandle(hAccessToken);
-
-    return bOk;
+    return false;
 }
 
 void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
@@ -484,178 +497,12 @@ void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
     if ( static_cast<oslSecurityImpl*>(Security)->m_hProfile == nullptr )
         return;
 
-    HANDLE hAccessToken = static_cast<oslSecurityImpl*>(Security)->m_hToken;
-
-    if ( !hAccessToken )
-    {
-        /* retrieve security handle if not done before e.g. 
osl_getCurrentSecurity()
-        */
-        HANDLE hProcess = GetCurrentProcess();
-
-        if (hProcess != nullptr)
-        {
-            OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
-            CloseHandle(hProcess);
-        }
-    }
+    auto hAccessToken = getAccessToken(Security, TOKEN_IMPERSONATE);
 
     /* unloading the user profile */
     UnloadUserProfile(hAccessToken, 
static_cast<oslSecurityImpl*>(Security)->m_hProfile);
 
     static_cast<oslSecurityImpl*>(Security)->m_hProfile = nullptr;
-
-    if (hAccessToken && (hAccessToken != 
static_cast<oslSecurityImpl*>(Security)->m_hToken))
-        CloseHandle(hAccessToken);
-}
-
-static bool GetSpecialFolder(rtl_uString **strPath, REFKNOWNFOLDERID rFolder)
-{
-    sal::systools::CoTaskMemAllocated<wchar_t> PathW;
-    if (SUCCEEDED(SHGetKnownFolderPath(rFolder, KF_FLAG_CREATE, nullptr, 
&PathW)))
-    {
-        rtl_uString_newFromStr(strPath, o3tl::toU(PathW));
-        return true;
-    }
-
-    return false;
-}
-
-// We use LPCTSTR here, because we use it with SE_foo_NAME constants
-// which are defined in winnt.h as UNICODE-dependent TEXT("PrivilegeName")
-static bool Privilege(LPCTSTR strPrivilege, bool bEnable)
-{
-    HANDLE           hToken;
-    TOKEN_PRIVILEGES tp;
-
-    // obtain the processes token
-    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | 
TOKEN_DUP_QUERY, &hToken))
-        return false;
-
-    // get the luid
-    if (!LookupPrivilegeValue(nullptr, strPrivilege, &tp.Privileges[0].Luid))
-        return false;
-
-    tp.PrivilegeCount = 1;
-
-    if (bEnable)
-        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-    else
-        tp.Privileges[0].Attributes = 0;
-
-    // enable or disable the privilege
-    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, nullptr, nullptr))
-        return false;
-
-    if (!CloseHandle(hToken))
-        return false;
-
-    return true;
-}
-
-static bool getUserNameImpl(oslSecurity Security, rtl_uString **strName,  bool 
bIncludeDomain)
-{
-    if (!Security)
-        return false;
-
-    oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
-
-    HANDLE hAccessToken = pSecImpl->m_hToken;
-
-    if (hAccessToken == nullptr)
-        OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
-
-    if (hAccessToken)
-    {
-        DWORD  nInfoBuffer = 512;
-        UCHAR* pInfoBuffer = static_cast<UCHAR *>(malloc(nInfoBuffer));
-
-        while (!GetTokenInformation(hAccessToken, TokenUser,
-                                       pInfoBuffer, nInfoBuffer, &nInfoBuffer))
-        {
-            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-            {
-                if (auto p = static_cast<UCHAR *>(realloc(pInfoBuffer, 
nInfoBuffer)))
-                    pInfoBuffer = p;
-                else
-                {
-                    free(pInfoBuffer);
-                    pInfoBuffer = nullptr;
-                    break;
-                }
-            }
-            else
-            {
-                free(pInfoBuffer);
-                pInfoBuffer = nullptr;
-                break;
-            }
-        }
-
-        if (pSecImpl->m_hToken == nullptr)
-            CloseHandle(hAccessToken);
-
-        if (pInfoBuffer)
-        {
-            sal_Unicode  UserName[128];
-            sal_Unicode  DomainName[128];
-            sal_Unicode  Name[257];
-            DWORD nUserName   = SAL_N_ELEMENTS(UserName);
-            DWORD nDomainName = SAL_N_ELEMENTS(DomainName);
-            SID_NAME_USE sUse;
-
-            if (LookupAccountSidW(nullptr, 
reinterpret_cast<PTOKEN_USER>(pInfoBuffer)->User.Sid,
-                                    o3tl::toW(UserName), &nUserName,
-                                    o3tl::toW(DomainName), &nDomainName, 
&sUse))
-            {
-                if (bIncludeDomain)
-                {
-                    wcscpy(o3tl::toW(Name), o3tl::toW(DomainName));
-                    wcscat(o3tl::toW(Name), L"/");
-                    wcscat(o3tl::toW(Name), o3tl::toW(UserName));
-                }
-                else
-                {
-                    wcscpy(o3tl::toW(Name), o3tl::toW(UserName));
-                }
-
-                rtl_uString_newFromStr(strName, Name);
-                free(pInfoBuffer);
-                return true;
-            }
-        }
-    }
-    else
-    {
-        DWORD needed=0;
-        sal_Unicode *pNameW=nullptr;
-
-        WNetGetUserW(nullptr, nullptr, &needed);
-        pNameW = static_cast<sal_Unicode *>(malloc 
(needed*sizeof(sal_Unicode)));
-        assert(pNameW); // Don't handle OOM conditions
-
-        if (WNetGetUserW(nullptr, o3tl::toW(pNameW), &needed) == NO_ERROR)
-        {
-            rtl_uString_newFromStr( strName, pNameW);
-
-            if (pNameW)
-                free(pNameW);
-            return true;
-        }
-        else if (pSecImpl->m_User[0] != '
-        {
-            rtl_uString_newFromStr(strName, 
o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
-
-            if (pNameW)
-                free(pNameW);
-
-            return true;
-        }
-
-        if (pNameW)
-            free(pNameW);
-    }
-
-    return false;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d1ed511e42b94b0c4196a60e7a9e8c1744e45243
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Jul 13 11:47:57 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Jul 13 14:12:52 2025 +0200

    Fix ToStringHelper<sal_Unicode[ N ]>
    
    It must only add characters up to terminating null, as its counterpart
    ToStringHelper< char[ N ] > does, and as its own length implies.
    
    Was this way ever since commit f1769094af821860dd9e1aa00904ba7123d27d1a
    (round out StringConcat helpers with sal_Unicode* overloads, 2019-10-11).
    
    Change-Id: I3e267789333dac23754e67b19ff596ad359868aa
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187791
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/include/rtl/stringconcat.hxx b/include/rtl/stringconcat.hxx
index 216670e0d635..7009f7e98ccf 100644
--- a/include/rtl/stringconcat.hxx
+++ b/include/rtl/stringconcat.hxx
@@ -151,7 +151,7 @@ struct ToStringHelper<sal_Unicode[ N ]>
         return std::char_traits<char16_t>::length( str );
     }
     sal_Unicode * operator()(sal_Unicode * buffer, sal_Unicode const str[N]) 
const
-    { return addDataHelper(buffer, str, N - 1); }
+    { return addDataString(buffer, str); }
 };
 
 template<std::size_t N>
diff --git a/sal/qa/rtl/strings/test_oustring_concat.cxx 
b/sal/qa/rtl/strings/test_oustring_concat.cxx
index 55f28ac3b0a2..3f3af2c5a7f6 100644
--- a/sal/qa/rtl/strings/test_oustring_concat.cxx
+++ b/sal/qa/rtl/strings/test_oustring_concat.cxx
@@ -73,6 +73,7 @@ void test::oustring::StringConcat::checkConcat()
     CPPUNIT_ASSERT_EQUAL( u"fooxyz"_ustr, OUString( u"foo"_ustr + d2 ));
     CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const 
sal_Unicode* > )), typeid( u"foo"_ustr + d2 ));
     const sal_Unicode d3[] = u"xyz";
+    sal_Unicode d4[5] = u"xyz"; // non-const array: text is copied only up to 
terminating null
     CPPUNIT_ASSERT_EQUAL( u"foobar"_ustr, OUString( OUString::Concat( "foo" ) 
+ "bar" ));
     CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< 
rtl::OUStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( 
OUString::Concat( "foo" ) + "bar" ));
     CPPUNIT_ASSERT_EQUAL( u"xyzbar"_ustr, OUString( OUString::Concat( d1 ) + 
"bar" ));
@@ -83,6 +84,8 @@ void test::oustring::StringConcat::checkConcat()
     CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< 
rtl::OUStringConcatMarker, const sal_Unicode* >, const char[ 4 ] > )), typeid( 
OUString::Concat( d2 ) + "bar" ));
     CPPUNIT_ASSERT_EQUAL( u"xyzbar"_ustr, OUString( OUString::Concat( d3 ) + 
"bar" ));
     CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< 
rtl::OUStringConcatMarker, const sal_Unicode[ 4 ] >, const char[ 4 ] > )), 
typeid( OUString::Concat( d3 ) + "bar" ));
+    CPPUNIT_ASSERT_EQUAL( u"xyzbar"_ustr, OUString( OUString::Concat( d4 ) + 
"bar" ));
+    CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< 
rtl::OUStringConcatMarker, sal_Unicode[ 5 ] >, const char[ 4 ] > )), typeid( 
OUString::Concat( d4 ) + "bar" ));
 
     CPPUNIT_ASSERT_EQUAL( u"num10"_ustr, OUString( u"num"_ustr + 
OUString::number( 10 )));
     CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, StringNumber< 
sal_Unicode, RTL_USTR_MAX_VALUEOFINT32 > > )), typeid( u"num"_ustr + 
OUString::number( 10 )));

Reply via email to