xref: /aoo41x/main/sal/osl/w32/security.c (revision cdf0e10c)
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