1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "system.h"
21 #include <userenv.h>
22 
23 #include <cassert>
24 #include <osl/security.h>
25 #include <osl/diagnose.h>
26 #include <osl/thread.h>
27 #include <osl/file.h>
28 #include <systools/win32/uwinapi.h>
29 #include <sddl.h>
30 #include <sal/macros.h>
31 #include <sal/log.hxx>
32 #include <o3tl/char16_t2wchar_t.hxx>
33 #include "secimpl.hxx"
34 
35 /* To get an impersonation token we need to create an impersonation
36    duplicate so every access token has to be created with duplicate
37    access rights */
38 
39 #define TOKEN_DUP_QUERY (TOKEN_QUERY|TOKEN_DUPLICATE)
40 
41 static bool GetSpecialFolder(rtl_uString **strPath, REFKNOWNFOLDERID rFolder);
42 // We use LPCTSTR here, because we use it with SE_foo_NAME constants
43 // which are defined in winnt.h as UNICODE-dependent TEXT("PrivilegeName")
44 static BOOL Privilege(LPCTSTR pszPrivilege, BOOL bEnable);
45 static bool getUserNameImpl(oslSecurity Security, rtl_uString **strName, bool bIncludeDomain);
46 
osl_getCurrentSecurity(void)47 oslSecurity SAL_CALL osl_getCurrentSecurity(void)
48 {
49     oslSecurityImpl* pSecImpl = static_cast<oslSecurityImpl *>(malloc(sizeof(oslSecurityImpl)));
50     if (pSecImpl)
51     {
52         pSecImpl->m_pNetResource = nullptr;
53         pSecImpl->m_User[0] = '\0';
54         pSecImpl->m_hToken = nullptr;
55         pSecImpl->m_hProfile = nullptr;
56     }
57     return pSecImpl;
58 }
59 
osl_loginUser(rtl_uString * strUserName,rtl_uString * strPasswd,oslSecurity * pSecurity)60 oslSecurityError SAL_CALL osl_loginUser( rtl_uString *strUserName, rtl_uString *strPasswd, oslSecurity *pSecurity )
61 {
62     oslSecurityError ret;
63 
64     sal_Unicode*    strUser;
65     sal_Unicode*    strDomain = o3tl::toU(_wcsdup(o3tl::toW(rtl_uString_getStr(strUserName))));
66     HANDLE  hUserToken;
67     LUID luid;
68 
69     if (nullptr != (strUser = o3tl::toU(wcschr(o3tl::toW(strDomain), L'/'))))
70         *strUser++ = L'\0';
71     else
72     {
73         strUser   = strDomain;
74         strDomain = nullptr;
75     }
76 
77     // this process must have the right: 'act as a part of operatingsystem'
78     OSL_ASSERT(LookupPrivilegeValue(nullptr, SE_TCB_NAME, &luid));
79     (void) luid;
80 
81     if (LogonUserW(o3tl::toW(strUser), strDomain ? o3tl::toW(strDomain) : L"", o3tl::toW(rtl_uString_getStr(strPasswd)),
82                   LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
83                    &hUserToken))
84     {
85         oslSecurityImpl* pSecImpl = static_cast<oslSecurityImpl *>(malloc(sizeof(oslSecurityImpl)));
86         if (pSecImpl)
87         {
88             pSecImpl->m_pNetResource = nullptr;
89             pSecImpl->m_hToken = hUserToken;
90             pSecImpl->m_hProfile = nullptr;
91             wcscpy(o3tl::toW(pSecImpl->m_User), o3tl::toW(strUser));
92         }
93         *pSecurity = pSecImpl;
94         ret = pSecImpl ? osl_Security_E_None : osl_Security_E_Unknown;
95     }
96     else
97     {
98         ret = osl_Security_E_UserUnknown;
99     }
100 
101     if (strDomain)
102         free(strDomain);
103     else
104         free(strUser);
105 
106     return ret;
107 }
108 
osl_loginUserOnFileServer(rtl_uString * strUserName,rtl_uString * strPasswd,rtl_uString * strFileServer,oslSecurity * pSecurity)109 oslSecurityError SAL_CALL osl_loginUserOnFileServer(rtl_uString *strUserName,
110                                                     rtl_uString *strPasswd,
111                                                     rtl_uString *strFileServer,
112                                                     oslSecurity *pSecurity)
113 {
114     oslSecurityError    ret;
115     DWORD               err;
116     NETRESOURCEW        netResource;
117     sal_Unicode*                remoteName;
118     sal_Unicode*                userName;
119 
120     remoteName  = static_cast<sal_Unicode *>(malloc((rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 4) * sizeof(sal_Unicode)));
121     userName    = static_cast<sal_Unicode *>(malloc((rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 2) * sizeof(sal_Unicode)));
122 
123     wcscpy(o3tl::toW(remoteName), L"\\\\");
124     wcscat(o3tl::toW(remoteName), o3tl::toW(rtl_uString_getStr(strFileServer)));
125     wcscat(o3tl::toW(remoteName), L"\\");
126     wcscat(o3tl::toW(remoteName), o3tl::toW(rtl_uString_getStr(strUserName)));
127 
128     wcscpy(o3tl::toW(userName), o3tl::toW(rtl_uString_getStr(strFileServer)));
129     wcscat(o3tl::toW(userName), L"\\");
130     wcscat(o3tl::toW(userName), o3tl::toW(rtl_uString_getStr(strUserName)));
131 
132     netResource.dwScope         = RESOURCE_GLOBALNET;
133     netResource.dwType          = RESOURCETYPE_DISK;
134     netResource.dwDisplayType   = RESOURCEDISPLAYTYPE_SHARE;
135     netResource.dwUsage         = RESOURCEUSAGE_CONNECTABLE;
136     netResource.lpLocalName     = nullptr;
137     netResource.lpRemoteName    = o3tl::toW(remoteName);
138     netResource.lpComment       = nullptr;
139     netResource.lpProvider      = nullptr;
140 
141     err = WNetAddConnection2W(&netResource, o3tl::toW(rtl_uString_getStr(strPasswd)), o3tl::toW(userName), 0);
142 
143     if ((err == NO_ERROR) || (err == ERROR_ALREADY_ASSIGNED))
144     {
145         oslSecurityImpl* pSecImpl = static_cast<oslSecurityImpl *>(malloc(sizeof(oslSecurityImpl)));
146         if (pSecImpl)
147         {
148             pSecImpl->m_pNetResource = static_cast<NETRESOURCEW *>(malloc(sizeof(NETRESOURCE)));
149             if (pSecImpl->m_pNetResource)
150             {
151                 *pSecImpl->m_pNetResource = netResource;
152                 pSecImpl->m_hToken = nullptr;
153                 pSecImpl->m_hProfile = nullptr;
154                 wcscpy(o3tl::toW(pSecImpl->m_User), o3tl::toW(rtl_uString_getStr(strUserName)));
155             }
156             else
157             {
158                 free(pSecImpl);
159                 pSecImpl = nullptr;
160             }
161         }
162         *pSecurity = pSecImpl;
163 
164         ret = pSecImpl ? osl_Security_E_None : osl_Security_E_Unknown;
165     }
166     else
167     {
168         ret = osl_Security_E_UserUnknown;
169     }
170 
171     free(remoteName);
172     free(userName);
173 
174     return ret;
175 }
176 
osl_isAdministrator(oslSecurity Security)177 sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
178 {
179     if (Security != nullptr)
180     {
181         HANDLE                      hImpersonationToken = nullptr;
182         PSID                        psidAdministrators;
183         SID_IDENTIFIER_AUTHORITY    siaNtAuthority = { SECURITY_NT_AUTHORITY };
184         bool                    bSuccess = false;
185 
186         /* If Security contains an access token we need to duplicate it to an impersonation
187            access token. NULL works with CheckTokenMembership() as the current effective
188            impersonation token
189          */
190 
191         if ( static_cast<oslSecurityImpl*>(Security)->m_hToken )
192         {
193             if ( !DuplicateToken (static_cast<oslSecurityImpl*>(Security)->m_hToken, SecurityImpersonation, &hImpersonationToken) )
194                 return false;
195         }
196 
197         /* CheckTokenMembership() can be used on W2K and higher (NT4 no longer supported by OOo)
198            and also works on Vista to retrieve the effective user rights. Just checking for
199            membership of Administrators group is not enough on Vista this would require additional
200            complicated checks as described in KB article Q118626: http://support.microsoft.com/kb/118626/en-us
201         */
202 
203         if (AllocateAndInitializeSid(&siaNtAuthority,
204                                      2,
205                                      SECURITY_BUILTIN_DOMAIN_RID,
206                                      DOMAIN_ALIAS_RID_ADMINS,
207                                      0, 0, 0, 0, 0, 0,
208                                      &psidAdministrators))
209         {
210             BOOL fSuccess = FALSE;
211 
212             if (CheckTokenMembership(hImpersonationToken, psidAdministrators, &fSuccess) && fSuccess)
213                 bSuccess = true;
214 
215             FreeSid(psidAdministrators);
216         }
217 
218         if (hImpersonationToken)
219             CloseHandle(hImpersonationToken);
220 
221         return bSuccess;
222     }
223     else
224     {
225         return false;
226     }
227 }
228 
osl_freeSecurityHandle(oslSecurity Security)229 void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
230 {
231     if (Security)
232     {
233         oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
234 
235         if (pSecImpl->m_pNetResource != nullptr)
236         {
237             WNetCancelConnection2W(pSecImpl->m_pNetResource->lpRemoteName, 0, true);
238 
239             free(pSecImpl->m_pNetResource->lpRemoteName);
240             free(pSecImpl->m_pNetResource);
241         }
242 
243         if (pSecImpl->m_hToken)
244             CloseHandle(pSecImpl->m_hToken);
245 
246         if ( pSecImpl->m_hProfile )
247             CloseHandle(pSecImpl->m_hProfile);
248 
249         free (pSecImpl);
250     }
251 }
252 
osl_getUserIdent(oslSecurity Security,rtl_uString ** strIdent)253 sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **strIdent)
254 {
255     if (Security != nullptr)
256     {
257         oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
258 
259         HANDLE hAccessToken = pSecImpl->m_hToken;
260 
261         if (hAccessToken == nullptr)
262             OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
263 
264         if (hAccessToken)
265         {
266             DWORD  nInfoBuffer = 512;
267             UCHAR* pInfoBuffer = static_cast<UCHAR *>(malloc(nInfoBuffer));
268 
269             while (!GetTokenInformation(hAccessToken, TokenUser,
270                                            pInfoBuffer, nInfoBuffer, &nInfoBuffer))
271             {
272                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
273                 {
274                     if (auto p = static_cast<UCHAR *>(realloc(pInfoBuffer, nInfoBuffer)))
275                         pInfoBuffer = p;
276                     else
277                     {
278                         free(pInfoBuffer);
279                         pInfoBuffer = nullptr;
280                         break;
281                     }
282                 }
283                 else
284                 {
285                     free(pInfoBuffer);
286                     pInfoBuffer = nullptr;
287                     break;
288                 }
289             }
290 
291             if (pSecImpl->m_hToken == nullptr)
292                 CloseHandle(hAccessToken);
293 
294             if (pInfoBuffer)
295             {
296                 PSID pSid = reinterpret_cast<PTOKEN_USER>(pInfoBuffer)->User.Sid;
297 
298                 LPWSTR pSidStr = nullptr;
299                 BOOL bResult = ConvertSidToStringSidW(pSid, &pSidStr);
300                 if (bResult)
301                 {
302                     rtl_uString_newFromStr(strIdent, o3tl::toU(pSidStr));
303                     LocalFree(pSidStr);
304                 }
305                 else
306                 {
307                     const DWORD dwError = GetLastError();
308                     SAL_WARN(
309                         "sal.osl",
310                         "ConvertSidToStringSidW failed. GetLastError returned: " << dwError);
311                 }
312 
313                 free(pInfoBuffer);
314 
315                 return bResult != FALSE;
316             }
317         }
318         else
319         {
320             DWORD needed = 0;
321 
322             WNetGetUserW(nullptr, nullptr, &needed);
323             if (needed < 16)
324                 needed = 16;
325 
326             if (auto Ident = static_cast<sal_Unicode *>(malloc(needed*sizeof(sal_Unicode))))
327             {
328                 if (WNetGetUserW(nullptr, o3tl::toW(Ident), &needed) != NO_ERROR)
329                 {
330                     wcscpy(o3tl::toW(Ident), L"unknown");
331                     Ident[7] = L'\0';
332                 }
333 
334                 rtl_uString_newFromStr( strIdent, Ident);
335                 free(Ident);
336                 return true;
337             }
338         }
339     }
340 
341     return false;
342 }
343 
osl_getUserName(oslSecurity Security,rtl_uString ** strName)344 sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **strName)
345 {
346     return getUserNameImpl(Security, strName, true);
347 }
348 
osl_getShortUserName(oslSecurity Security,rtl_uString ** strName)349 sal_Bool SAL_CALL osl_getShortUserName(oslSecurity Security, rtl_uString **strName)
350 {
351     return getUserNameImpl(Security, strName, false);
352 }
353 
osl_getHomeDir(oslSecurity Security,rtl_uString ** pustrDirectory)354 sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
355 {
356     rtl_uString *ustrSysDir = nullptr;
357     bool    bSuccess = false;
358 
359     if (Security != nullptr)
360     {
361         oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
362 
363         if (pSecImpl->m_pNetResource != nullptr)
364         {
365             rtl_uString_newFromStr( &ustrSysDir, o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
366 
367             bSuccess = osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory );
368         }
369         else
370         {
371                 bSuccess = GetSpecialFolder(&ustrSysDir, FOLDERID_Documents) &&
372                                      (osl_File_E_None == osl_getFileURLFromSystemPath(ustrSysDir, pustrDirectory));
373         }
374     }
375 
376     if ( ustrSysDir )
377         rtl_uString_release( ustrSysDir );
378 
379     return bSuccess;
380 }
381 
osl_getConfigDir(oslSecurity Security,rtl_uString ** pustrDirectory)382 sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
383 {
384     bool bSuccess = false;
385 
386     if (Security != nullptr)
387     {
388         oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
389 
390         if (pSecImpl->m_pNetResource != nullptr)
391         {
392             rtl_uString *ustrSysDir = nullptr;
393 
394             rtl_uString_newFromStr( &ustrSysDir, o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
395             bSuccess = osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory);
396 
397             if ( ustrSysDir )
398                 rtl_uString_release( ustrSysDir );
399         }
400         else
401         {
402             if (pSecImpl->m_hToken)
403             {
404                 /* not implemented */
405                 OSL_ASSERT(false);
406             }
407             else
408             {
409                 rtl_uString *ustrFile = nullptr;
410                 sal_Unicode sFile[_MAX_PATH];
411 
412                 if ( !GetSpecialFolder( &ustrFile, FOLDERID_RoamingAppData) )
413                 {
414                     OSL_VERIFY(GetWindowsDirectoryW(o3tl::toW(sFile), _MAX_DIR) > 0);
415 
416                     rtl_uString_newFromStr( &ustrFile, sFile);
417                 }
418 
419                 bSuccess = osl_File_E_None == osl_getFileURLFromSystemPath(ustrFile, pustrDirectory);
420 
421                 if ( ustrFile )
422                     rtl_uString_release( ustrFile );
423             }
424         }
425     }
426 
427     return bSuccess;
428 }
429 
osl_loadUserProfile(oslSecurity Security)430 sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
431 {
432     /*  CreateProcessAsUser does not load the specified user's profile
433         into the HKEY_USERS registry key. This means that access to information
434         in the HKEY_CURRENT_USER registry key may not produce results consistent
435         with a normal interactive logon.
436         It is your responsibility to load the user's registry hive into HKEY_USERS
437         with the LoadUserProfile function before calling CreateProcessAsUser.
438     */
439     bool bOk = false;
440 
441     RegCloseKey(HKEY_CURRENT_USER);
442 
443     if (Privilege(SE_RESTORE_NAME, TRUE))
444     {
445         HANDLE                  hAccessToken        = static_cast<oslSecurityImpl*>(Security)->m_hToken;
446 
447         /* try to create user profile */
448         if ( !hAccessToken )
449         {
450             /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
451             */
452             HANDLE hProcess = GetCurrentProcess();
453 
454             if (hProcess != nullptr)
455             {
456                 OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
457                 CloseHandle(hProcess);
458             }
459         }
460 
461         rtl_uString *buffer = nullptr;
462         PROFILEINFOW pi;
463 
464         getUserNameImpl(Security, &buffer, false);
465 
466         ZeroMemory(&pi, sizeof(pi));
467         pi.dwSize = sizeof(pi);
468         pi.lpUserName = o3tl::toW(rtl_uString_getStr(buffer));
469         pi.dwFlags = PI_NOUI;
470 
471         if (LoadUserProfileW(hAccessToken, &pi))
472         {
473             UnloadUserProfile(hAccessToken, pi.hProfile);
474 
475             bOk = true;
476         }
477 
478         rtl_uString_release(buffer);
479 
480         if (hAccessToken && (hAccessToken != static_cast<oslSecurityImpl*>(Security)->m_hToken))
481             CloseHandle(hAccessToken);
482     }
483 
484     return bOk;
485 }
486 
osl_unloadUserProfile(oslSecurity Security)487 void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
488 {
489     if ( static_cast<oslSecurityImpl*>(Security)->m_hProfile != nullptr )
490     {
491         HANDLE                  hAccessToken        = static_cast<oslSecurityImpl*>(Security)->m_hToken;
492 
493         if ( !hAccessToken )
494         {
495             /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
496             */
497             HANDLE hProcess = GetCurrentProcess();
498 
499             if (hProcess != nullptr)
500             {
501                 OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
502                 CloseHandle(hProcess);
503             }
504         }
505 
506         /* unloading the user profile */
507         UnloadUserProfile(hAccessToken, static_cast<oslSecurityImpl*>(Security)->m_hProfile);
508 
509         static_cast<oslSecurityImpl*>(Security)->m_hProfile = nullptr;
510 
511         if (hAccessToken && (hAccessToken != static_cast<oslSecurityImpl*>(Security)->m_hToken))
512             CloseHandle(hAccessToken);
513     }
514 }
515 
GetSpecialFolder(rtl_uString ** strPath,REFKNOWNFOLDERID rFolder)516 static bool GetSpecialFolder(rtl_uString **strPath, REFKNOWNFOLDERID rFolder)
517 {
518     bool bRet = false;
519     PWSTR PathW;
520     if (SUCCEEDED(SHGetKnownFolderPath(rFolder, KF_FLAG_CREATE, nullptr, &PathW)))
521     {
522         rtl_uString_newFromStr(strPath, o3tl::toU(PathW));
523         CoTaskMemFree(PathW);
524         bRet = true;
525     }
526 
527     return bRet;
528 }
529 
530 // We use LPCTSTR here, because we use it with SE_foo_NAME constants
531 // which are defined in winnt.h as UNICODE-dependent TEXT("PrivilegeName")
Privilege(LPCTSTR strPrivilege,BOOL bEnable)532 static BOOL Privilege(LPCTSTR strPrivilege, BOOL bEnable)
533 {
534     HANDLE           hToken;
535     TOKEN_PRIVILEGES tp;
536 
537     // obtain the processes token
538     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_DUP_QUERY, &hToken))
539         return FALSE;
540 
541     // get the luid
542     if (!LookupPrivilegeValue(nullptr, strPrivilege, &tp.Privileges[0].Luid))
543         return FALSE;
544 
545     tp.PrivilegeCount = 1;
546 
547     if (bEnable)
548         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
549     else
550         tp.Privileges[0].Attributes = 0;
551 
552     // enable or disable the privilege
553     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, nullptr, nullptr))
554         return FALSE;
555 
556     if (!CloseHandle(hToken))
557         return FALSE;
558 
559     return TRUE;
560 }
561 
getUserNameImpl(oslSecurity Security,rtl_uString ** strName,bool bIncludeDomain)562 static bool getUserNameImpl(oslSecurity Security, rtl_uString **strName,  bool bIncludeDomain)
563 {
564     if (Security != nullptr)
565     {
566         oslSecurityImpl *pSecImpl = static_cast<oslSecurityImpl*>(Security);
567 
568         HANDLE hAccessToken = pSecImpl->m_hToken;
569 
570         if (hAccessToken == nullptr)
571             OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
572 
573         if (hAccessToken)
574         {
575             DWORD  nInfoBuffer = 512;
576             UCHAR* pInfoBuffer = static_cast<UCHAR *>(malloc(nInfoBuffer));
577 
578             while (!GetTokenInformation(hAccessToken, TokenUser,
579                                            pInfoBuffer, nInfoBuffer, &nInfoBuffer))
580             {
581                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
582                 {
583                     if (auto p = static_cast<UCHAR *>(realloc(pInfoBuffer, nInfoBuffer)))
584                         pInfoBuffer = p;
585                     else
586                     {
587                         free(pInfoBuffer);
588                         pInfoBuffer = nullptr;
589                         break;
590                     }
591                 }
592                 else
593                 {
594                     free(pInfoBuffer);
595                     pInfoBuffer = nullptr;
596                     break;
597                 }
598             }
599 
600             if (pSecImpl->m_hToken == nullptr)
601                 CloseHandle(hAccessToken);
602 
603             if (pInfoBuffer)
604             {
605                 sal_Unicode  UserName[128];
606                 sal_Unicode  DomainName[128];
607                 sal_Unicode  Name[257];
608                 DWORD nUserName   = SAL_N_ELEMENTS(UserName);
609                 DWORD nDomainName = SAL_N_ELEMENTS(DomainName);
610                 SID_NAME_USE sUse;
611 
612                 if (LookupAccountSidW(nullptr, reinterpret_cast<PTOKEN_USER>(pInfoBuffer)->User.Sid,
613                                         o3tl::toW(UserName), &nUserName,
614                                         o3tl::toW(DomainName), &nDomainName, &sUse))
615                 {
616                     if (bIncludeDomain)
617                     {
618                         wcscpy(o3tl::toW(Name), o3tl::toW(DomainName));
619                         wcscat(o3tl::toW(Name), L"/");
620                         wcscat(o3tl::toW(Name), o3tl::toW(UserName));
621                     }
622                     else
623                     {
624                         wcscpy(o3tl::toW(Name), o3tl::toW(UserName));
625                     }
626 
627                     rtl_uString_newFromStr(strName, Name);
628                     free(pInfoBuffer);
629                     return true;
630                 }
631             }
632         }
633         else
634         {
635             DWORD needed=0;
636             sal_Unicode *pNameW=nullptr;
637 
638             WNetGetUserW(nullptr, nullptr, &needed);
639             pNameW = static_cast<sal_Unicode *>(malloc (needed*sizeof(sal_Unicode)));
640             assert(pNameW); // Don't handle OOM conditions
641 
642             if (WNetGetUserW(nullptr, o3tl::toW(pNameW), &needed) == NO_ERROR)
643             {
644                 rtl_uString_newFromStr( strName, pNameW);
645 
646                 if (pNameW)
647                     free(pNameW);
648                 return true;
649             }
650             else if (pSecImpl->m_User[0] != '\0')
651             {
652                 rtl_uString_newFromStr(strName, o3tl::toU(pSecImpl->m_pNetResource->lpRemoteName));
653 
654                 if (pNameW)
655                     free(pNameW);
656 
657                 return true;
658             }
659 
660             if (pNameW)
661                 free(pNameW);
662         }
663     }
664 
665     return false;
666 }
667 
668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
669