diff options
Diffstat (limited to 'sal/osl/w32/security.c')
-rw-r--r-- | sal/osl/w32/security.c | 991 |
1 files changed, 991 insertions, 0 deletions
diff --git a/sal/osl/w32/security.c b/sal/osl/w32/security.c new file mode 100644 index 000000000000..237ea67dc949 --- /dev/null +++ b/sal/osl/w32/security.c @@ -0,0 +1,991 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "system.h" + +#include <osl/security.h> +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <osl/file.h> +#include <systools/win32/uwinapi.h> +#include "secimpl.h" + +/*****************************************************************************/ +/* Data Type Definition */ +/*****************************************************************************/ + + +/* Data for use in (un)LoadProfile Functions */ +/* Declarations based on USERENV.H for Windows 2000 Beta 2 */ +#define PI_NOUI 0x00000001 // Prevents displaying of messages +#define PI_APPLYPOLICY 0x00000002 // Apply NT4 style policy + +typedef struct _PROFILEINFOW { + DWORD dwSize; // Must be set to sizeof(PROFILEINFO) + DWORD dwFlags; // See flags above + LPWSTR lpUserName; // User name (required) + LPWSTR lpProfilePath; // Roaming profile path + LPWSTR lpDefaultPath; // Default user profile path + LPWSTR lpServerName; // Validating DC name in netbios format + LPWSTR lpPolicyPath; // Path to the NT4 style policy file + HANDLE hProfile; // Registry key handle - filled by function +} PROFILEINFOW, FAR * LPPROFILEINFOW; + +/* Typedefs for function pointers in USERENV.DLL */ +typedef BOOL (STDMETHODCALLTYPE FAR * LPFNLOADUSERPROFILE) ( + HANDLE hToken, + LPPROFILEINFOW lpProfileInfo +); + +typedef BOOL (STDMETHODCALLTYPE FAR * LPFNUNLOADUSERPROFILE) ( + HANDLE hToken, + HANDLE hProfile +); + +typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) ( + HANDLE hToken, + LPTSTR lpProfileDir, + LPDWORD lpcchSize +); + +/* To get an impersonation token we need to create an impersonation + duplicate so every access token has to be created with duplicate + access rights */ + +#define TOKEN_DUP_QUERY (TOKEN_QUERY|TOKEN_DUPLICATE) + +/*****************************************************************************/ +/* Static Module Function Declarations */ +/*****************************************************************************/ + +static sal_Bool isWNT(void); +static sal_Bool GetSpecialFolder(rtl_uString **strPath,int nFolder); +static BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable); +static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain); + +/*****************************************************************************/ +/* Exported Module Functions */ +/*****************************************************************************/ + +oslSecurity SAL_CALL osl_getCurrentSecurity(void) +{ + oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl)); + + pSecImpl->m_pNetResource = NULL; + pSecImpl->m_User[0] = '\0'; + pSecImpl->m_hToken = NULL; + pSecImpl->m_hProfile = NULL; + + return ((oslSecurity)pSecImpl); +} + +oslSecurityError SAL_CALL osl_loginUser( rtl_uString *strUserName, rtl_uString *strPasswd, oslSecurity *pSecurity ) +{ + oslSecurityError ret; + + if (!isWNT()) + { + *pSecurity = osl_getCurrentSecurity(); + ret = osl_Security_E_None; + } + else + { + sal_Unicode* strUser; + sal_Unicode* strDomain = _wcsdup(rtl_uString_getStr(strUserName)); + HANDLE hUserToken; + + #if OSL_DEBUG_LEVEL > 0 + LUID luid; + #endif + + if (NULL != (strUser = wcschr(strDomain, L'/'))) + *strUser++ = L'\0'; + else + { + strUser = strDomain; + strDomain = NULL; + } + + // this process must have the right: 'act as a part of operatingsystem' + OSL_ASSERT(LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid)); + + if (LogonUserW(strUser, strDomain ? strDomain : L"", rtl_uString_getStr(strPasswd), + LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, + &hUserToken)) + { + oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl)); + + pSecImpl->m_pNetResource = NULL; + pSecImpl->m_hToken = hUserToken; + pSecImpl->m_hProfile = NULL; + wcscpy(pSecImpl->m_User, strUser); + + *pSecurity = (oslSecurity)pSecImpl; + ret = osl_Security_E_None; + } + else + ret = osl_Security_E_UserUnknown; + + if (strDomain) + free(strDomain); + else + free(strUser); + } + + return ret; +} + +oslSecurityError SAL_CALL osl_loginUserOnFileServer(rtl_uString *strUserName, + rtl_uString *strPasswd, + rtl_uString *strFileServer, + oslSecurity *pSecurity) +{ + oslSecurityError ret; + DWORD err; + NETRESOURCEW netResource; + sal_Unicode* remoteName; + sal_Unicode* userName; + + remoteName = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 4); + userName = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 2); + + wcscpy(remoteName, L"\\\\"); + wcscat(remoteName, rtl_uString_getStr(strFileServer)); + wcscat(remoteName, L"\\"); + wcscat(remoteName, rtl_uString_getStr(strUserName)); + + wcscpy(userName, rtl_uString_getStr(strFileServer)); + wcscat(userName, L"\\"); + wcscat(userName, rtl_uString_getStr(strUserName)); + + netResource.dwScope = RESOURCE_GLOBALNET; + netResource.dwType = RESOURCETYPE_DISK; + netResource.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; + netResource.dwUsage = RESOURCEUSAGE_CONNECTABLE; + netResource.lpLocalName = NULL; + netResource.lpRemoteName = remoteName; + netResource.lpComment = NULL; + netResource.lpProvider = NULL; + + err = WNetAddConnection2W(&netResource, rtl_uString_getStr(strPasswd), userName, 0); + + if ((err == NO_ERROR) || (err == ERROR_ALREADY_ASSIGNED)) + { + oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl)); + + pSecImpl->m_pNetResource = malloc(sizeof(NETRESOURCE)); + *pSecImpl->m_pNetResource = netResource; + + pSecImpl->m_hToken = NULL; + pSecImpl->m_hProfile = NULL; + wcscpy(pSecImpl->m_User, rtl_uString_getStr(strUserName)); + + *pSecurity = (oslSecurity)pSecImpl; + + ret = osl_Security_E_None; + } + else + ret = osl_Security_E_UserUnknown; + + free(remoteName); + free(userName); + + return ret; +} + + +static BOOL WINAPI CheckTokenMembership_Stub( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember ) +{ + typedef BOOL (WINAPI *CheckTokenMembership_PROC)( HANDLE, PSID, PBOOL ); + + static HMODULE hModule = NULL; + static CheckTokenMembership_PROC pCheckTokenMembership = NULL; + + if ( !hModule ) + { + /* SAL is always linked against ADVAPI32 so we can rely on that it is already mapped */ + + hModule = GetModuleHandleA( "ADVAPI32.DLL" ); + + pCheckTokenMembership = (CheckTokenMembership_PROC)GetProcAddress( hModule, "CheckTokenMembership" ); + } + + if ( pCheckTokenMembership ) + return pCheckTokenMembership( TokenHandle, SidToCheck, IsMember ); + else + { + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; + } + +} + + +sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security) +{ + if (Security != NULL) + { + /* ts: on Window 95 systems any user seems to be an adminstrator */ + if (!isWNT()) + { + return(sal_True); + } + else + { + HANDLE hImpersonationToken = NULL; + PSID psidAdministrators; + SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; + sal_Bool bSuccess = sal_False; + + + /* If Security contains an access token we need to duplicate it to an impersonation + access token. NULL works with CheckTokenMembership() as the current effective + impersonation token + */ + + if ( ((oslSecurityImpl*)Security)->m_hToken ) + { + if ( !DuplicateToken (((oslSecurityImpl*)Security)->m_hToken, SecurityImpersonation, &hImpersonationToken) ) + return sal_False; + } + + /* CheckTokenMembership() can be used on W2K and higher (NT4 no longer supported by OOo) + and also works on Vista to retrieve the effective user rights. Just checking for + membership of Administrators group is not enough on Vista this would require additional + complicated checks as described in KB arcticle Q118626: http://support.microsoft.com/kb/118626/en-us + */ + + if (AllocateAndInitializeSid(&siaNtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &psidAdministrators)) + { + BOOL fSuccess = FALSE; + + if ( CheckTokenMembership_Stub( hImpersonationToken, psidAdministrators, &fSuccess ) && fSuccess ) + bSuccess = sal_True; + + FreeSid(psidAdministrators); + } + + if ( hImpersonationToken ) + CloseHandle( hImpersonationToken ); + + return (bSuccess); + } + } + else + return (sal_False); +} + + +void SAL_CALL osl_freeSecurityHandle(oslSecurity Security) +{ + if (Security) + { + oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security; + + if (pSecImpl->m_pNetResource != NULL) + { + WNetCancelConnection2W(pSecImpl->m_pNetResource->lpRemoteName, 0, sal_True); + + free(pSecImpl->m_pNetResource->lpRemoteName); + free(pSecImpl->m_pNetResource); + } + + if (pSecImpl->m_hToken) + CloseHandle(pSecImpl->m_hToken); + + if ( pSecImpl->m_hProfile ) + CloseHandle(pSecImpl->m_hProfile); + + free (pSecImpl); + } +} + + +sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **strIdent) +{ + if (Security != NULL) + { + oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security; + + HANDLE hAccessToken = pSecImpl->m_hToken; + + if (hAccessToken == NULL) + OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken); + + if (hAccessToken) + { + sal_Char *Ident; + DWORD nInfoBuffer = 512; + UCHAR* pInfoBuffer = malloc(nInfoBuffer); + + + while (!GetTokenInformation(hAccessToken, TokenUser, + pInfoBuffer, nInfoBuffer, &nInfoBuffer)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer); + else + { + free(pInfoBuffer); + pInfoBuffer = NULL; + break; + } + } + + if (pSecImpl->m_hToken == NULL) + CloseHandle(hAccessToken); + + if (pInfoBuffer) + { + PSID pSid = ((PTOKEN_USER)pInfoBuffer)->User.Sid; + PSID_IDENTIFIER_AUTHORITY psia; + DWORD dwSubAuthorities; + DWORD dwSidRev=SID_REVISION; + DWORD dwCounter; + DWORD dwSidSize; + + /* obtain SidIdentifierAuthority */ + psia=GetSidIdentifierAuthority(pSid); + + /* obtain sidsubauthority count */ + dwSubAuthorities=min(*GetSidSubAuthorityCount(pSid), 5); + + /* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */ + Ident=malloc(88*sizeof(sal_Char)); + + /* prepare S-SID_REVISION- */ + dwSidSize=wsprintf(Ident, TEXT("S-%lu-"), dwSidRev); + + /* prepare SidIdentifierAuthority */ + if ((psia->Value[0] != 0) || (psia->Value[1] != 0)) + { + dwSidSize+=wsprintf(Ident + strlen(Ident), + TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), + (USHORT)psia->Value[0], + (USHORT)psia->Value[1], + (USHORT)psia->Value[2], + (USHORT)psia->Value[3], + (USHORT)psia->Value[4], + (USHORT)psia->Value[5]); + } + else + { + dwSidSize+=wsprintf(Ident + strlen(Ident), + TEXT("%lu"), + (ULONG)(psia->Value[5] ) + + (ULONG)(psia->Value[4] << 8) + + (ULONG)(psia->Value[3] << 16) + + (ULONG)(psia->Value[2] << 24) ); + } + + /* loop through SidSubAuthorities */ + for (dwCounter=0; dwCounter < dwSubAuthorities; dwCounter++) + { + dwSidSize+=wsprintf(Ident + dwSidSize, TEXT("-%lu"), + *GetSidSubAuthority(pSid, dwCounter) ); + } + + rtl_uString_newFromAscii( strIdent, Ident ); + + free(pInfoBuffer); + free(Ident); + + return (sal_True); + } + } + else + { + DWORD needed=0; + sal_Unicode *Ident; + + WNetGetUserA(NULL, NULL, &needed); + needed = max( 16 , needed ); + Ident=malloc(needed*sizeof(sal_Unicode)); + + if (WNetGetUserW(NULL, Ident, &needed) != NO_ERROR) + { + wcscpy(Ident, L"unknown"); + Ident[7] = L'\0'; + } + + rtl_uString_newFromStr( strIdent, Ident); + + free(Ident); + + return sal_True; + } + } + + return sal_False; +} + + + +sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **strName) +{ + return getUserNameImpl(Security, strName, sal_True); +} + + +sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory) +{ + rtl_uString *ustrSysDir = NULL; + sal_Bool bSuccess = sal_False; + + if (Security != NULL) + { + oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security; + + if (pSecImpl->m_pNetResource != NULL) + { + rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName); + + bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory )); + } + else + { +#if 0 + if (pSecImpl->m_hToken) + { + DWORD nInfoBuffer = 512; + UCHAR* pInfoBuffer = malloc(nInfoBuffer); + + while (!GetTokenInformation(pSecImpl->m_hToken, TokenUser, + pInfoBuffer, nInfoBuffer, &nInfoBuffer)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer); + else + { + free(pInfoBuffer); + pInfoBuffer = NULL; + break; + } + } + + /* not implemented */ + OSL_ASSERT(sal_False); + + if (pInfoBuffer) + { + /* if (EqualSid() ... */ + + } + } + else +#endif + + bSuccess = (sal_Bool)(GetSpecialFolder(&ustrSysDir, CSIDL_PERSONAL) && + (osl_File_E_None == osl_getFileURLFromSystemPath(ustrSysDir, pustrDirectory))); + } + } + + if ( ustrSysDir ) + rtl_uString_release( ustrSysDir ); + + return bSuccess; +} + +sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory) +{ + sal_Bool bSuccess = sal_False; + + if (Security != NULL) + { + oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security; + + if (pSecImpl->m_pNetResource != NULL) + { + rtl_uString *ustrSysDir = NULL; + + rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName); + bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory)); + + if ( ustrSysDir ) + rtl_uString_release( ustrSysDir ); + } + else + { + if (pSecImpl->m_hToken) + { + /* not implemented */ + OSL_ASSERT(sal_False); + } + else + { + rtl_uString *ustrFile = NULL; + sal_Unicode sFile[_MAX_PATH]; + + if ( !GetSpecialFolder( &ustrFile, CSIDL_APPDATA) ) + { + OSL_VERIFY(GetWindowsDirectoryW(sFile, _MAX_DIR) > 0); + + rtl_uString_newFromStr( &ustrFile, sFile); + } + + bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath(ustrFile, pustrDirectory)); + + if ( ustrFile ) + rtl_uString_release( ustrFile ); + } + } + } + + return bSuccess; +} + + +sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security) +{ + /* CreateProcessAsUser does not load the specified user's profile + into the HKEY_USERS registry key. This means that access to information + in the HKEY_CURRENT_USER registry key may not produce results consistent + with a normal interactive logon. + It is your responsibility to load the user's registry hive into HKEY_USERS + with the LoadUserProfile function before calling CreateProcessAsUser. + */ + BOOL bOk = FALSE; + + RegCloseKey(HKEY_CURRENT_USER); + + if (Privilege(SE_RESTORE_NAME, TRUE)) + { + HMODULE hUserEnvLib = NULL; + LPFNLOADUSERPROFILE fLoadUserProfile = NULL; + LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL; + HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken; + DWORD nError = 0; + + /* try to create user profile */ + if ( !hAccessToken ) + { + /* retrieve security handle if not done before e.g. osl_getCurrentSecurity() + */ + HANDLE hProcess = GetCurrentProcess(); + + if (hProcess != NULL) + { + OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken); + CloseHandle(hProcess); + } + } + + hUserEnvLib = LoadLibraryA("userenv.dll"); + + if (hUserEnvLib) + { + fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileW"); + fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile"); + + if (fLoadUserProfile && fUnloadUserProfile) + { + rtl_uString *buffer = 0; + PROFILEINFOW pi; + + getUserNameImpl(Security, &buffer, sal_False); + + ZeroMemory( &pi, sizeof(pi) ); + pi.dwSize = sizeof(pi); + pi.lpUserName = rtl_uString_getStr(buffer); + pi.dwFlags = PI_NOUI; + + if (fLoadUserProfile(hAccessToken, &pi)) + { + fUnloadUserProfile(hAccessToken, pi.hProfile); + + bOk = TRUE; + } + else + nError = GetLastError(); + + rtl_uString_release(buffer); + } + + FreeLibrary(hUserEnvLib); + } + + if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken)) + CloseHandle(hAccessToken); + } + + return (sal_Bool)bOk; +} + + +void SAL_CALL osl_unloadUserProfile(oslSecurity Security) +{ + if ( ((oslSecurityImpl*)Security)->m_hProfile != NULL ) + { + HMODULE hUserEnvLib = NULL; + LPFNLOADUSERPROFILE fLoadUserProfile = NULL; + LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL; + BOOL bOk = FALSE; + HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken; + + if ( !hAccessToken ) + { + /* retrieve security handle if not done before e.g. osl_getCurrentSecurity() + */ + HANDLE hProcess = GetCurrentProcess(); + + if (hProcess != NULL) + { + OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken); + CloseHandle(hProcess); + } + } + + hUserEnvLib = LoadLibrary("userenv.dll"); + + if (hUserEnvLib) + { + fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileA"); + fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile"); + + if (fLoadUserProfile && fUnloadUserProfile) + { + /* unloading the user profile */ + if (fLoadUserProfile && fUnloadUserProfile) + bOk = fUnloadUserProfile(hAccessToken, ((oslSecurityImpl*)Security)->m_hProfile); + + if (hUserEnvLib) + FreeLibrary(hUserEnvLib); + } + } + + ((oslSecurityImpl*)Security)->m_hProfile; + + if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken)) + { + CloseHandle(hAccessToken); + } + } +} + +/*****************************************************************************/ +/* Static Module Functions */ +/*****************************************************************************/ + + +static sal_Bool GetSpecialFolder(rtl_uString **strPath, int nFolder) +{ + sal_Bool bRet = sal_False; + HINSTANCE hLibrary; + sal_Char PathA[_MAX_PATH]; + sal_Unicode PathW[_MAX_PATH]; + + if ((hLibrary = LoadLibrary("shell32.dll")) != NULL) + { + BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL); + BOOL (WINAPI *pSHGetSpecialFolderPathW)(HWND, LPWSTR, int, BOOL); + + pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathA"); + pSHGetSpecialFolderPathW = (BOOL (WINAPI *)(HWND, LPWSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathW"); + + if (pSHGetSpecialFolderPathA) + { + if (pSHGetSpecialFolderPathA(GetActiveWindow(), PathA, nFolder, TRUE)) + { + rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS); + OSL_ASSERT(*strPath != NULL); + bRet = sal_True; + } + } + else if (pSHGetSpecialFolderPathW) + { + if (pSHGetSpecialFolderPathW(GetActiveWindow(), PathW, nFolder, TRUE)) + { + rtl_uString_newFromStr( strPath, PathW); + bRet = sal_True; + } + } + else + { + HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *) = (HRESULT (WINAPI *)(HWND, int, LPITEMIDLIST *))GetProcAddress(hLibrary, "SHGetSpecialFolderLocation"); + BOOL (WINAPI *pSHGetPathFromIDListA)(LPCITEMIDLIST, LPSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListA"); + BOOL (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPWSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListW"); + HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *) = (HRESULT (WINAPI *)(LPMALLOC *))GetProcAddress(hLibrary, "SHGetMalloc"); + + + if (pSHGetSpecialFolderLocation && (pSHGetPathFromIDListA || pSHGetPathFromIDListW ) && pSHGetMalloc ) + { + LPITEMIDLIST pidl; + LPMALLOC pMalloc; + HRESULT hr; + + hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl); + + /* Get SHGetSpecialFolderLocation fails if directory does not exists. */ + /* If it fails we try to create the directory and redo the call */ + if (! SUCCEEDED(hr)) + { + HKEY hRegKey; + + if (RegOpenKey(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + &hRegKey) == ERROR_SUCCESS) + { + LONG lRet; + DWORD lSize = elementsof(PathA); + DWORD Type = REG_SZ; + + switch (nFolder) + { + case CSIDL_APPDATA: + lRet = RegQueryValueEx(hRegKey, "AppData", NULL, &Type, (LPBYTE)PathA, &lSize); + break; + + case CSIDL_PERSONAL: + lRet = RegQueryValueEx(hRegKey, "Personal", NULL, &Type, (LPBYTE)PathA, &lSize); + break; + + default: + lRet = -1l; + } + + if ((lRet == ERROR_SUCCESS) && (Type == REG_SZ)) + { + if (_access(PathA, 0) < 0) + CreateDirectory(PathA, NULL); + + hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl); + } + + RegCloseKey(hRegKey); + } + } + + if (SUCCEEDED(hr)) + { + if (pSHGetPathFromIDListW && pSHGetPathFromIDListW(pidl, PathW)) + { + /* if directory does not exist, create it */ + if (_waccess(PathW, 0) < 0) + CreateDirectoryW(PathW, NULL); + + rtl_uString_newFromStr( strPath, PathW); + bRet = sal_True; + } + else if (pSHGetPathFromIDListA && pSHGetPathFromIDListA(pidl, PathA)) + { + /* if directory does not exist, create it */ + if (_access(PathA, 0) < 0) + CreateDirectoryA(PathA, NULL); + + rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS); + OSL_ASSERT(*strPath != NULL); + bRet = sal_True; + } + } + + if (SUCCEEDED(pSHGetMalloc(&pMalloc))) + { + pMalloc->lpVtbl->Free(pMalloc, pidl); + pMalloc->lpVtbl->Release(pMalloc); + } + } + } + } + + FreeLibrary(hLibrary); + + return (bRet); +} + + +static sal_Bool isWNT(void) +{ + static sal_Bool isInit = sal_False; + static sal_Bool isWNT = sal_False; + + if (!isInit) + { + OSVERSIONINFO VersionInformation = + + { + sizeof(OSVERSIONINFO), + 0, + 0, + 0, + 0, + "", + }; + + if ( + GetVersionEx(&VersionInformation) && + (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT) + ) + { + isWNT = sal_True; + } + + isInit = sal_True; + } + + return(isWNT); +} + +static BOOL Privilege(LPTSTR strPrivilege, BOOL bEnable) +{ + HANDLE hToken; + TOKEN_PRIVILEGES tp; + + /* + obtain the processes token + */ + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_DUP_QUERY, &hToken)) + return FALSE; + + /* + get the luid + */ + if (!LookupPrivilegeValue(NULL, strPrivilege, &tp.Privileges[0].Luid)) + return FALSE; + + tp.PrivilegeCount = 1; + + if (bEnable) + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + else + tp.Privileges[0].Attributes = 0; + + /* + enable or disable the privilege + */ + if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0)) + return FALSE; + + if (!CloseHandle(hToken)) + return FALSE; + + return TRUE; +} + +static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain) +{ + if (Security != NULL) + { + oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security; + + HANDLE hAccessToken = pSecImpl->m_hToken; + + if (hAccessToken == NULL) + OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken); + + if (hAccessToken) + { + DWORD nInfoBuffer = 512; + UCHAR* pInfoBuffer = malloc(nInfoBuffer); + + while (!GetTokenInformation(hAccessToken, TokenUser, + pInfoBuffer, nInfoBuffer, &nInfoBuffer)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer); + else + { + free(pInfoBuffer); + pInfoBuffer = NULL; + break; + } + } + + if (pSecImpl->m_hToken == NULL) + CloseHandle(hAccessToken); + + if (pInfoBuffer) + { + sal_Unicode UserName[128]; + sal_Unicode DomainName[128]; + sal_Unicode Name[257]; + DWORD nUserName = sizeof(UserName); + DWORD nDomainName = sizeof(DomainName); + SID_NAME_USE sUse; + + if (LookupAccountSidW(NULL, ((PTOKEN_USER)pInfoBuffer)->User.Sid, + UserName, &nUserName, + DomainName, &nDomainName, &sUse)) + { + if (bIncludeDomain) + { + wcscpy(Name, DomainName); + wcscat(Name, L"/"); + wcscat(Name, UserName); + } + else + { + wcscpy(Name, UserName); + } + } + rtl_uString_newFromStr( strName, Name); + + free(pInfoBuffer); + + return (sal_True); + } + } + else + { + DWORD needed=0; + sal_Unicode *pNameW=NULL; + + WNetGetUserW(NULL, NULL, &needed); + pNameW = malloc (needed*sizeof(sal_Unicode)); + + if (WNetGetUserW(NULL, pNameW, &needed) == NO_ERROR) + { + rtl_uString_newFromStr( strName, pNameW); + + if (pNameW) + free(pNameW); + return (sal_True); + } + else + if (wcslen(pSecImpl->m_User) > 0) + { + rtl_uString_newFromStr( strName, pSecImpl->m_pNetResource->lpRemoteName); + + if (pNameW) + free(pNameW); + + return (sal_True); + } + + if (pNameW) + free(pNameW); + } + } + + return sal_False; +} + |