xref: /trunk/main/sal/osl/w32/security.c (revision fc9fd3f14a55d77b35643a64034752a178b2a5b0)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 #include "system.h"
30 
31 #include <osl/security.h>
32 #include <osl/diagnose.h>
33 #include <osl/thread.h>
34 #include <osl/file.h>
35 #include <systools/win32/uwinapi.h>
36 #include "secimpl.h"
37 
38 /*****************************************************************************/
39 /* Data Type Definition */
40 /*****************************************************************************/
41 
42 
43 /* Data for use in (un)LoadProfile Functions */
44 /* Declarations based on USERENV.H for Windows 2000 Beta 2 */
45 #define PI_NOUI         0x00000001   // Prevents displaying of messages
46 #define PI_APPLYPOLICY  0x00000002   // Apply NT4 style policy
47 
48 typedef struct _PROFILEINFOW {
49   DWORD    dwSize;          // Must be set to sizeof(PROFILEINFO)
50   DWORD    dwFlags;         // See flags above
51   LPWSTR   lpUserName;      // User name (required)
52   LPWSTR   lpProfilePath;   // Roaming profile path
53   LPWSTR   lpDefaultPath;   // Default user profile path
54   LPWSTR   lpServerName;    // Validating DC name in netbios format
55   LPWSTR   lpPolicyPath;    // Path to the NT4 style policy file
56   HANDLE   hProfile;        // Registry key handle - filled by function
57 } PROFILEINFOW, FAR * LPPROFILEINFOW;
58 
59 /* Typedefs for function pointers in USERENV.DLL */
60 typedef BOOL (STDMETHODCALLTYPE FAR * LPFNLOADUSERPROFILE) (
61   HANDLE hToken,
62   LPPROFILEINFOW lpProfileInfo
63 );
64 
65 typedef BOOL (STDMETHODCALLTYPE FAR * LPFNUNLOADUSERPROFILE) (
66   HANDLE hToken,
67   HANDLE hProfile
68 );
69 
70 typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (
71   HANDLE hToken,
72   LPTSTR lpProfileDir,
73   LPDWORD lpcchSize
74 );
75 
76 /* To get an impersonation token we need to create an impersonation
77    duplicate so every access token has to be created with duplicate
78    access rights */
79 
80 #define TOKEN_DUP_QUERY (TOKEN_QUERY|TOKEN_DUPLICATE)
81 
82 /*****************************************************************************/
83 /* Static Module Function Declarations */
84 /*****************************************************************************/
85 
86 static sal_Bool isWNT(void);
87 static sal_Bool GetSpecialFolder(rtl_uString **strPath,int nFolder);
88 static BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable);
89 static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain);
90 
91 /*****************************************************************************/
92 /* Exported Module Functions */
93 /*****************************************************************************/
94 
95 oslSecurity SAL_CALL osl_getCurrentSecurity(void)
96 {
97     oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
98 
99     pSecImpl->m_pNetResource = NULL;
100     pSecImpl->m_User[0] = '\0';
101     pSecImpl->m_hToken = NULL;
102     pSecImpl->m_hProfile = NULL;
103 
104     return ((oslSecurity)pSecImpl);
105 }
106 
107 oslSecurityError SAL_CALL osl_loginUser( rtl_uString *strUserName, rtl_uString *strPasswd, oslSecurity *pSecurity )
108 {
109     oslSecurityError ret;
110 
111     if (!isWNT())
112     {
113         *pSecurity = osl_getCurrentSecurity();
114         ret = osl_Security_E_None;
115     }
116     else
117     {
118         sal_Unicode*    strUser;
119         sal_Unicode*    strDomain = _wcsdup(rtl_uString_getStr(strUserName));
120         HANDLE  hUserToken;
121 
122         #if OSL_DEBUG_LEVEL > 0
123             LUID luid;
124         #endif
125 
126         if (NULL != (strUser = wcschr(strDomain, L'/')))
127             *strUser++ = L'\0';
128         else
129         {
130             strUser   = strDomain;
131             strDomain = NULL;
132         }
133 
134         // this process must have the right: 'act as a part of operatingsystem'
135         OSL_ASSERT(LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid));
136 
137         if (LogonUserW(strUser, strDomain ? strDomain : L"", rtl_uString_getStr(strPasswd),
138                       LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
139                       &hUserToken))
140         {
141             oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
142 
143             pSecImpl->m_pNetResource = NULL;
144             pSecImpl->m_hToken = hUserToken;
145             pSecImpl->m_hProfile = NULL;
146             wcscpy(pSecImpl->m_User, strUser);
147 
148             *pSecurity = (oslSecurity)pSecImpl;
149             ret = osl_Security_E_None;
150         }
151         else
152             ret = osl_Security_E_UserUnknown;
153 
154         if (strDomain)
155             free(strDomain);
156         else
157             free(strUser);
158     }
159 
160     return ret;
161 }
162 
163 oslSecurityError SAL_CALL osl_loginUserOnFileServer(rtl_uString *strUserName,
164                                                     rtl_uString *strPasswd,
165                                                     rtl_uString *strFileServer,
166                                                     oslSecurity *pSecurity)
167 {
168     oslSecurityError    ret;
169     DWORD               err;
170     NETRESOURCEW        netResource;
171     sal_Unicode*                remoteName;
172     sal_Unicode*                userName;
173 
174     remoteName  = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 4);
175     userName    = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 2);
176 
177     wcscpy(remoteName, L"\\\\");
178     wcscat(remoteName, rtl_uString_getStr(strFileServer));
179     wcscat(remoteName, L"\\");
180     wcscat(remoteName, rtl_uString_getStr(strUserName));
181 
182     wcscpy(userName, rtl_uString_getStr(strFileServer));
183     wcscat(userName, L"\\");
184     wcscat(userName, rtl_uString_getStr(strUserName));
185 
186     netResource.dwScope         = RESOURCE_GLOBALNET;
187     netResource.dwType          = RESOURCETYPE_DISK;
188     netResource.dwDisplayType   = RESOURCEDISPLAYTYPE_SHARE;
189     netResource.dwUsage         = RESOURCEUSAGE_CONNECTABLE;
190     netResource.lpLocalName     = NULL;
191     netResource.lpRemoteName    = remoteName;
192     netResource.lpComment       = NULL;
193     netResource.lpProvider      = NULL;
194 
195     err = WNetAddConnection2W(&netResource, rtl_uString_getStr(strPasswd), userName, 0);
196 
197     if ((err == NO_ERROR) || (err == ERROR_ALREADY_ASSIGNED))
198     {
199         oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
200 
201         pSecImpl->m_pNetResource = malloc(sizeof(NETRESOURCE));
202         *pSecImpl->m_pNetResource = netResource;
203 
204         pSecImpl->m_hToken = NULL;
205         pSecImpl->m_hProfile = NULL;
206         wcscpy(pSecImpl->m_User, rtl_uString_getStr(strUserName));
207 
208         *pSecurity = (oslSecurity)pSecImpl;
209 
210         ret = osl_Security_E_None;
211     }
212     else
213         ret = osl_Security_E_UserUnknown;
214 
215     free(remoteName);
216     free(userName);
217 
218     return ret;
219 }
220 
221 
222 static BOOL WINAPI CheckTokenMembership_Stub( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember )
223 {
224     typedef BOOL (WINAPI *CheckTokenMembership_PROC)( HANDLE, PSID, PBOOL );
225 
226     static HMODULE  hModule = NULL;
227     static CheckTokenMembership_PROC    pCheckTokenMembership = NULL;
228 
229     if ( !hModule )
230     {
231         /* SAL is always linked against ADVAPI32 so we can rely on that it is already mapped */
232 
233         hModule = GetModuleHandleA( "ADVAPI32.DLL" );
234 
235         pCheckTokenMembership = (CheckTokenMembership_PROC)GetProcAddress( hModule, "CheckTokenMembership" );
236     }
237 
238     if ( pCheckTokenMembership )
239         return pCheckTokenMembership( TokenHandle, SidToCheck, IsMember );
240     else
241     {
242         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
243         return FALSE;
244     }
245 
246 }
247 
248 
249 sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
250 {
251     if (Security != NULL)
252     {
253         /* ts: on Window 95 systems any user seems to be an adminstrator */
254         if (!isWNT())
255         {
256             return(sal_True);
257         }
258         else
259         {
260             HANDLE                      hImpersonationToken = NULL;
261             PSID                        psidAdministrators;
262             SID_IDENTIFIER_AUTHORITY    siaNtAuthority = SECURITY_NT_AUTHORITY;
263             sal_Bool                    bSuccess = sal_False;
264 
265 
266             /* If Security contains an access token we need to duplicate it to an impersonation
267                access token. NULL works with CheckTokenMembership() as the current effective
268                impersonation token
269              */
270 
271             if ( ((oslSecurityImpl*)Security)->m_hToken )
272             {
273                 if ( !DuplicateToken (((oslSecurityImpl*)Security)->m_hToken, SecurityImpersonation, &hImpersonationToken) )
274                     return sal_False;
275             }
276 
277             /* CheckTokenMembership() can be used on W2K and higher (NT4 no longer supported by OOo)
278                and also works on Vista to retrieve the effective user rights. Just checking for
279                membership of Administrators group is not enough on Vista this would require additional
280                complicated checks as described in KB arcticle Q118626: http://support.microsoft.com/kb/118626/en-us
281             */
282 
283             if (AllocateAndInitializeSid(&siaNtAuthority,
284                                          2,
285                                          SECURITY_BUILTIN_DOMAIN_RID,
286                                          DOMAIN_ALIAS_RID_ADMINS,
287                                          0, 0, 0, 0, 0, 0,
288                                          &psidAdministrators))
289             {
290                 BOOL    fSuccess = FALSE;
291 
292                 if ( CheckTokenMembership_Stub( hImpersonationToken, psidAdministrators, &fSuccess ) && fSuccess )
293                     bSuccess = sal_True;
294 
295                 FreeSid(psidAdministrators);
296             }
297 
298             if ( hImpersonationToken )
299                 CloseHandle( hImpersonationToken );
300 
301             return (bSuccess);
302         }
303     }
304     else
305         return (sal_False);
306 }
307 
308 
309 void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
310 {
311     if (Security)
312     {
313         oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
314 
315         if (pSecImpl->m_pNetResource != NULL)
316         {
317             WNetCancelConnection2W(pSecImpl->m_pNetResource->lpRemoteName, 0, sal_True);
318 
319             free(pSecImpl->m_pNetResource->lpRemoteName);
320             free(pSecImpl->m_pNetResource);
321         }
322 
323         if (pSecImpl->m_hToken)
324             CloseHandle(pSecImpl->m_hToken);
325 
326         if ( pSecImpl->m_hProfile )
327             CloseHandle(pSecImpl->m_hProfile);
328 
329         free (pSecImpl);
330     }
331 }
332 
333 
334 sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **strIdent)
335 {
336     if (Security != NULL)
337     {
338         oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
339 
340         HANDLE hAccessToken = pSecImpl->m_hToken;
341 
342         if (hAccessToken == NULL)
343             OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
344 
345         if (hAccessToken)
346         {
347             sal_Char        *Ident;
348             DWORD  nInfoBuffer = 512;
349             UCHAR* pInfoBuffer = malloc(nInfoBuffer);
350 
351 
352             while (!GetTokenInformation(hAccessToken, TokenUser,
353                                         pInfoBuffer, nInfoBuffer, &nInfoBuffer))
354             {
355                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
356                     pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
357                 else
358                 {
359                     free(pInfoBuffer);
360                     pInfoBuffer = NULL;
361                     break;
362                 }
363             }
364 
365             if (pSecImpl->m_hToken == NULL)
366                 CloseHandle(hAccessToken);
367 
368             if (pInfoBuffer)
369             {
370                 PSID pSid = ((PTOKEN_USER)pInfoBuffer)->User.Sid;
371                 PSID_IDENTIFIER_AUTHORITY psia;
372                 DWORD dwSubAuthorities;
373                 DWORD dwSidRev=SID_REVISION;
374                 DWORD dwCounter;
375                 DWORD dwSidSize;
376 
377                 /* obtain SidIdentifierAuthority */
378                 psia=GetSidIdentifierAuthority(pSid);
379 
380                 /* obtain sidsubauthority count */
381                 dwSubAuthorities=min(*GetSidSubAuthorityCount(pSid), 5);
382 
383                 /* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */
384                 Ident=malloc(88*sizeof(sal_Char));
385 
386                 /* prepare S-SID_REVISION- */
387                 dwSidSize=wsprintf(Ident, TEXT("S-%lu-"), dwSidRev);
388 
389                 /* prepare SidIdentifierAuthority */
390                 if ((psia->Value[0] != 0) || (psia->Value[1] != 0))
391                 {
392                     dwSidSize+=wsprintf(Ident + strlen(Ident),
393                                 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
394                                 (USHORT)psia->Value[0],
395                                 (USHORT)psia->Value[1],
396                                 (USHORT)psia->Value[2],
397                                 (USHORT)psia->Value[3],
398                                 (USHORT)psia->Value[4],
399                                 (USHORT)psia->Value[5]);
400                 }
401                 else
402                 {
403                     dwSidSize+=wsprintf(Ident + strlen(Ident),
404                                 TEXT("%lu"),
405                                 (ULONG)(psia->Value[5]      )   +
406                                 (ULONG)(psia->Value[4] <<  8)   +
407                                 (ULONG)(psia->Value[3] << 16)   +
408                                 (ULONG)(psia->Value[2] << 24)   );
409                 }
410 
411                 /* loop through SidSubAuthorities */
412                 for (dwCounter=0; dwCounter < dwSubAuthorities; dwCounter++)
413                 {
414                     dwSidSize+=wsprintf(Ident + dwSidSize, TEXT("-%lu"),
415                                 *GetSidSubAuthority(pSid, dwCounter) );
416                 }
417 
418                 rtl_uString_newFromAscii( strIdent, Ident );
419 
420                 free(pInfoBuffer);
421                 free(Ident);
422 
423                 return (sal_True);
424             }
425         }
426         else
427         {
428             DWORD needed=0;
429             sal_Unicode     *Ident;
430 
431             WNetGetUserA(NULL, NULL, &needed);
432             needed = max( 16 , needed );
433             Ident=malloc(needed*sizeof(sal_Unicode));
434 
435             if (WNetGetUserW(NULL, Ident, &needed) != NO_ERROR)
436             {
437                 wcscpy(Ident, L"unknown");
438                 Ident[7] = L'\0';
439             }
440 
441             rtl_uString_newFromStr( strIdent, Ident);
442 
443             free(Ident);
444 
445             return sal_True;
446         }
447     }
448 
449     return sal_False;
450 }
451 
452 
453 
454 sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **strName)
455 {
456     return getUserNameImpl(Security, strName, sal_True);
457 }
458 
459 
460 sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
461 {
462     rtl_uString *ustrSysDir = NULL;
463     sal_Bool    bSuccess = sal_False;
464 
465     if (Security != NULL)
466     {
467         oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
468 
469         if (pSecImpl->m_pNetResource != NULL)
470         {
471             rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName);
472 
473             bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory ));
474         }
475         else
476         {
477 #if 0
478             if (pSecImpl->m_hToken)
479             {
480                 DWORD  nInfoBuffer = 512;
481                 UCHAR* pInfoBuffer = malloc(nInfoBuffer);
482 
483                 while (!GetTokenInformation(pSecImpl->m_hToken, TokenUser,
484                                             pInfoBuffer, nInfoBuffer, &nInfoBuffer))
485                 {
486                     if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
487                         pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
488                     else
489                     {
490                         free(pInfoBuffer);
491                         pInfoBuffer = NULL;
492                         break;
493                     }
494                 }
495 
496                 /* not implemented */
497                 OSL_ASSERT(sal_False);
498 
499                 if (pInfoBuffer)
500                 {
501                     /* if (EqualSid() ... */
502 
503                 }
504             }
505             else
506 #endif
507 
508                 bSuccess = (sal_Bool)(GetSpecialFolder(&ustrSysDir, CSIDL_PERSONAL) &&
509                                      (osl_File_E_None == osl_getFileURLFromSystemPath(ustrSysDir, pustrDirectory)));
510         }
511     }
512 
513     if ( ustrSysDir )
514         rtl_uString_release( ustrSysDir );
515 
516     return bSuccess;
517 }
518 
519 sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
520 {
521     sal_Bool    bSuccess = sal_False;
522 
523     if (Security != NULL)
524     {
525         oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
526 
527         if (pSecImpl->m_pNetResource != NULL)
528         {
529             rtl_uString *ustrSysDir = NULL;
530 
531             rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName);
532             bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory));
533 
534             if ( ustrSysDir )
535                 rtl_uString_release( ustrSysDir );
536         }
537         else
538         {
539             if (pSecImpl->m_hToken)
540             {
541                 /* not implemented */
542                 OSL_ASSERT(sal_False);
543             }
544             else
545             {
546                 rtl_uString *ustrFile = NULL;
547                 sal_Unicode sFile[_MAX_PATH];
548 
549                 if ( !GetSpecialFolder( &ustrFile, CSIDL_APPDATA) )
550                 {
551                     OSL_VERIFY(GetWindowsDirectoryW(sFile, _MAX_DIR) > 0);
552 
553                     rtl_uString_newFromStr( &ustrFile, sFile);
554                 }
555 
556                 bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath(ustrFile, pustrDirectory));
557 
558                 if ( ustrFile )
559                     rtl_uString_release( ustrFile );
560             }
561         }
562     }
563 
564     return bSuccess;
565 }
566 
567 
568 sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
569 {
570     /*  CreateProcessAsUser does not load the specified user's profile
571         into the HKEY_USERS registry key. This means that access to information
572         in the HKEY_CURRENT_USER registry key may not produce results consistent
573         with a normal interactive logon.
574         It is your responsibility to load the user's registry hive into HKEY_USERS
575         with the LoadUserProfile function before calling CreateProcessAsUser.
576     */
577     BOOL bOk = FALSE;
578 
579     RegCloseKey(HKEY_CURRENT_USER);
580 
581     if (Privilege(SE_RESTORE_NAME, TRUE))
582     {
583         HMODULE                 hUserEnvLib         = NULL;
584         LPFNLOADUSERPROFILE     fLoadUserProfile    = NULL;
585         LPFNUNLOADUSERPROFILE   fUnloadUserProfile  = NULL;
586         HANDLE                  hAccessToken        = ((oslSecurityImpl*)Security)->m_hToken;
587         DWORD                   nError              = 0;
588 
589         /* try to create user profile */
590         if ( !hAccessToken )
591         {
592             /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
593             */
594             HANDLE hProcess = GetCurrentProcess();
595 
596             if (hProcess != NULL)
597             {
598                 OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
599                 CloseHandle(hProcess);
600             }
601         }
602 
603         hUserEnvLib = LoadLibraryA("userenv.dll");
604 
605         if (hUserEnvLib)
606         {
607             fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileW");
608             fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile");
609 
610             if (fLoadUserProfile && fUnloadUserProfile)
611             {
612                 rtl_uString     *buffer = 0;
613                 PROFILEINFOW    pi;
614 
615                 getUserNameImpl(Security, &buffer, sal_False);
616 
617                 ZeroMemory( &pi, sizeof(pi) );
618                 pi.dwSize = sizeof(pi);
619                 pi.lpUserName = rtl_uString_getStr(buffer);
620                 pi.dwFlags = PI_NOUI;
621 
622                 if (fLoadUserProfile(hAccessToken, &pi))
623                 {
624                     fUnloadUserProfile(hAccessToken, pi.hProfile);
625 
626                     bOk = TRUE;
627                 }
628                 else
629                     nError = GetLastError();
630 
631                 rtl_uString_release(buffer);
632             }
633 
634             FreeLibrary(hUserEnvLib);
635         }
636 
637         if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken))
638             CloseHandle(hAccessToken);
639     }
640 
641     return (sal_Bool)bOk;
642 }
643 
644 
645 void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
646 {
647     if ( ((oslSecurityImpl*)Security)->m_hProfile != NULL )
648     {
649         HMODULE                 hUserEnvLib         = NULL;
650         LPFNLOADUSERPROFILE     fLoadUserProfile    = NULL;
651         LPFNUNLOADUSERPROFILE   fUnloadUserProfile  = NULL;
652         BOOL                    bOk                 = FALSE;
653         HANDLE                  hAccessToken        = ((oslSecurityImpl*)Security)->m_hToken;
654 
655         if ( !hAccessToken )
656         {
657             /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
658             */
659             HANDLE hProcess = GetCurrentProcess();
660 
661             if (hProcess != NULL)
662             {
663                 OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
664                 CloseHandle(hProcess);
665             }
666         }
667 
668         hUserEnvLib = LoadLibrary("userenv.dll");
669 
670         if (hUserEnvLib)
671         {
672             fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileA");
673             fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile");
674 
675             if (fLoadUserProfile && fUnloadUserProfile)
676             {
677                 /* unloading the user profile */
678                 if (fLoadUserProfile && fUnloadUserProfile)
679                     bOk = fUnloadUserProfile(hAccessToken, ((oslSecurityImpl*)Security)->m_hProfile);
680 
681                 if (hUserEnvLib)
682                     FreeLibrary(hUserEnvLib);
683             }
684         }
685 
686         ((oslSecurityImpl*)Security)->m_hProfile;
687 
688         if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken))
689         {
690             CloseHandle(hAccessToken);
691         }
692     }
693 }
694 
695 /*****************************************************************************/
696 /* Static Module Functions */
697 /*****************************************************************************/
698 
699 
700 static sal_Bool GetSpecialFolder(rtl_uString **strPath, int nFolder)
701 {
702     sal_Bool bRet = sal_False;
703     HINSTANCE hLibrary;
704     sal_Char PathA[_MAX_PATH];
705     sal_Unicode PathW[_MAX_PATH];
706 
707     if ((hLibrary = LoadLibrary("shell32.dll")) != NULL)
708     {
709         BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
710         BOOL (WINAPI *pSHGetSpecialFolderPathW)(HWND, LPWSTR, int, BOOL);
711 
712         pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathA");
713         pSHGetSpecialFolderPathW = (BOOL (WINAPI *)(HWND, LPWSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathW");
714 
715         if (pSHGetSpecialFolderPathA)
716         {
717             if (pSHGetSpecialFolderPathA(GetActiveWindow(), PathA, nFolder, TRUE))
718             {
719                 rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
720                 OSL_ASSERT(*strPath != NULL);
721                 bRet = sal_True;
722             }
723         }
724         else if (pSHGetSpecialFolderPathW)
725         {
726             if (pSHGetSpecialFolderPathW(GetActiveWindow(), PathW, nFolder, TRUE))
727             {
728                 rtl_uString_newFromStr( strPath, PathW);
729                 bRet = sal_True;
730             }
731         }
732         else
733         {
734             HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *) = (HRESULT (WINAPI *)(HWND, int, LPITEMIDLIST *))GetProcAddress(hLibrary, "SHGetSpecialFolderLocation");
735             BOOL (WINAPI *pSHGetPathFromIDListA)(LPCITEMIDLIST, LPSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListA");
736             BOOL (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPWSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListW");
737             HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *) = (HRESULT (WINAPI *)(LPMALLOC *))GetProcAddress(hLibrary, "SHGetMalloc");
738 
739 
740             if (pSHGetSpecialFolderLocation && (pSHGetPathFromIDListA || pSHGetPathFromIDListW ) && pSHGetMalloc )
741             {
742                 LPITEMIDLIST pidl;
743                 LPMALLOC pMalloc;
744                 HRESULT  hr;
745 
746                 hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl);
747 
748                 /* Get SHGetSpecialFolderLocation fails if directory does not exists. */
749                 /* If it fails we try to create the directory and redo the call */
750                 if (! SUCCEEDED(hr))
751                 {
752                     HKEY hRegKey;
753 
754                     if (RegOpenKey(HKEY_CURRENT_USER,
755                                    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
756                                    &hRegKey) == ERROR_SUCCESS)
757                     {
758                         LONG lRet;
759                         DWORD lSize = elementsof(PathA);
760                         DWORD Type = REG_SZ;
761 
762                         switch (nFolder)
763                         {
764                             case CSIDL_APPDATA:
765                                 lRet = RegQueryValueEx(hRegKey, "AppData", NULL, &Type, (LPBYTE)PathA, &lSize);
766                                 break;
767 
768                             case CSIDL_PERSONAL:
769                                 lRet = RegQueryValueEx(hRegKey, "Personal", NULL, &Type, (LPBYTE)PathA, &lSize);
770                                 break;
771 
772                             default:
773                                 lRet = -1l;
774                         }
775 
776                         if ((lRet == ERROR_SUCCESS) && (Type == REG_SZ))
777                         {
778                             if (_access(PathA, 0) < 0)
779                                 CreateDirectory(PathA, NULL);
780 
781                             hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl);
782                         }
783 
784                         RegCloseKey(hRegKey);
785                     }
786                 }
787 
788                 if (SUCCEEDED(hr))
789                 {
790                     if (pSHGetPathFromIDListW && pSHGetPathFromIDListW(pidl, PathW))
791                     {
792                         /* if directory does not exist, create it */
793                         if (_waccess(PathW, 0) < 0)
794                             CreateDirectoryW(PathW, NULL);
795 
796                         rtl_uString_newFromStr( strPath, PathW);
797                         bRet = sal_True;
798                     }
799                     else if (pSHGetPathFromIDListA && pSHGetPathFromIDListA(pidl, PathA))
800                     {
801                         /* if directory does not exist, create it */
802                         if (_access(PathA, 0) < 0)
803                             CreateDirectoryA(PathA, NULL);
804 
805                         rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
806                         OSL_ASSERT(*strPath != NULL);
807                         bRet = sal_True;
808                     }
809                 }
810 
811                 if (SUCCEEDED(pSHGetMalloc(&pMalloc)))
812                 {
813                     pMalloc->lpVtbl->Free(pMalloc, pidl);
814                     pMalloc->lpVtbl->Release(pMalloc);
815                 }
816             }
817         }
818     }
819 
820     FreeLibrary(hLibrary);
821 
822     return (bRet);
823 }
824 
825 
826 static sal_Bool isWNT(void)
827 {
828     static sal_Bool isInit = sal_False;
829     static sal_Bool isWNT = sal_False;
830 
831     if (!isInit)
832     {
833         OSVERSIONINFO VersionInformation =
834 
835         {
836             sizeof(OSVERSIONINFO),
837             0,
838             0,
839             0,
840             0,
841             "",
842         };
843 
844         if (
845             GetVersionEx(&VersionInformation) &&
846             (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
847            )
848         {
849             isWNT = sal_True;
850         }
851 
852         isInit = sal_True;
853     }
854 
855     return(isWNT);
856 }
857 
858 static BOOL Privilege(LPTSTR strPrivilege, BOOL bEnable)
859 {
860     HANDLE           hToken;
861     TOKEN_PRIVILEGES tp;
862 
863     /*
864         obtain the processes token
865     */
866     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_DUP_QUERY, &hToken))
867         return FALSE;
868 
869     /*
870         get the luid
871     */
872     if (!LookupPrivilegeValue(NULL, strPrivilege, &tp.Privileges[0].Luid))
873         return FALSE;
874 
875     tp.PrivilegeCount = 1;
876 
877     if (bEnable)
878         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
879     else
880         tp.Privileges[0].Attributes = 0;
881 
882     /*
883         enable or disable the privilege
884     */
885     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
886         return FALSE;
887 
888     if (!CloseHandle(hToken))
889         return FALSE;
890 
891     return TRUE;
892 }
893 
894 static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName,  sal_Bool bIncludeDomain)
895 {
896     if (Security != NULL)
897     {
898         oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
899 
900         HANDLE hAccessToken = pSecImpl->m_hToken;
901 
902         if (hAccessToken == NULL)
903             OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
904 
905         if (hAccessToken)
906         {
907             DWORD  nInfoBuffer = 512;
908             UCHAR* pInfoBuffer = malloc(nInfoBuffer);
909 
910             while (!GetTokenInformation(hAccessToken, TokenUser,
911                                         pInfoBuffer, nInfoBuffer, &nInfoBuffer))
912             {
913                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
914                     pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
915                 else
916                 {
917                     free(pInfoBuffer);
918                     pInfoBuffer = NULL;
919                     break;
920                 }
921             }
922 
923             if (pSecImpl->m_hToken == NULL)
924                 CloseHandle(hAccessToken);
925 
926             if (pInfoBuffer)
927             {
928                 sal_Unicode  UserName[128];
929                 sal_Unicode  DomainName[128];
930                 sal_Unicode  Name[257];
931                 DWORD nUserName   = sizeof(UserName);
932                 DWORD nDomainName = sizeof(DomainName);
933                 SID_NAME_USE sUse;
934 
935                 if (LookupAccountSidW(NULL, ((PTOKEN_USER)pInfoBuffer)->User.Sid,
936                                      UserName, &nUserName,
937                                      DomainName, &nDomainName, &sUse))
938                 {
939                     if (bIncludeDomain)
940                     {
941                         wcscpy(Name, DomainName);
942                         wcscat(Name, L"/");
943                         wcscat(Name, UserName);
944                     }
945                     else
946                     {
947                         wcscpy(Name, UserName);
948                     }
949                 }
950                 rtl_uString_newFromStr( strName, Name);
951 
952                 free(pInfoBuffer);
953 
954                 return (sal_True);
955             }
956         }
957         else
958         {
959             DWORD needed=0;
960             sal_Unicode         *pNameW=NULL;
961 
962             WNetGetUserW(NULL, NULL, &needed);
963             pNameW = malloc (needed*sizeof(sal_Unicode));
964 
965             if (WNetGetUserW(NULL, pNameW, &needed) == NO_ERROR)
966             {
967                 rtl_uString_newFromStr( strName, pNameW);
968 
969                 if (pNameW)
970                     free(pNameW);
971                 return (sal_True);
972             }
973             else
974                 if (wcslen(pSecImpl->m_User) > 0)
975                 {
976                     rtl_uString_newFromStr( strName, pSecImpl->m_pNetResource->lpRemoteName);
977 
978                     if (pNameW)
979                         free(pNameW);
980 
981                     return (sal_True);
982                 }
983 
984             if (pNameW)
985                 free(pNameW);
986         }
987     }
988 
989     return sal_False;
990 }
991 
992