/** * WinPR: Windows Portable Runtime * Shell Functions * * Copyright 2015 Dell Software * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include /** * shell32.dll: * * GetUserProfileDirectoryA * GetUserProfileDirectoryW */ #ifndef _WIN32 #include #ifdef WINPR_HAVE_UNISTD_H #include #endif #include #include #include "../handle/handle.h" #include "../security/security.h" BOOL GetUserProfileDirectoryA(HANDLE hToken, LPSTR lpProfileDir, LPDWORD lpcchSize) { struct passwd pwd = WINPR_C_ARRAY_INIT; struct passwd* pw = nullptr; WINPR_ACCESS_TOKEN* token = (WINPR_ACCESS_TOKEN*)hToken; if (!AccessTokenIsValid(hToken)) return FALSE; if (!lpcchSize) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } long buflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (buflen < 0) buflen = 8196; const size_t s = 1ULL + (size_t)buflen; char* buf = calloc(s, sizeof(char)); if (!buf) return FALSE; const int status = getpwnam_r(token->Username, &pwd, buf, WINPR_ASSERTING_INT_CAST(size_t, buflen), &pw); if ((status != 0) || !pw) { SetLastError(ERROR_INVALID_PARAMETER); free(buf); return FALSE; } const size_t cchDirSize = strlen(pw->pw_dir) + 1; if (cchDirSize > UINT32_MAX) { SetLastError(ERROR_INVALID_PARAMETER); free(buf); return FALSE; } if (!lpProfileDir || (*lpcchSize < cchDirSize)) { *lpcchSize = (UINT32)cchDirSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); free(buf); return FALSE; } ZeroMemory(lpProfileDir, *lpcchSize); (void)sprintf_s(lpProfileDir, *lpcchSize, "%s", pw->pw_dir); *lpcchSize = (UINT32)cchDirSize; free(buf); return TRUE; } BOOL GetUserProfileDirectoryW(HANDLE hToken, LPWSTR lpProfileDir, LPDWORD lpcchSize) { BOOL bStatus = 0; DWORD cchSizeA = 0; LPSTR lpProfileDirA = nullptr; if (!lpcchSize) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } cchSizeA = *lpcchSize; lpProfileDirA = nullptr; if (lpProfileDir) { lpProfileDirA = (LPSTR)malloc(cchSizeA); if (lpProfileDirA == nullptr) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } } bStatus = GetUserProfileDirectoryA(hToken, lpProfileDirA, &cchSizeA); if (bStatus) { SSIZE_T size = ConvertUtf8NToWChar(lpProfileDirA, cchSizeA, lpProfileDir, *lpcchSize); bStatus = size >= 0; } if (lpProfileDirA) { free(lpProfileDirA); } *lpcchSize = cchSizeA; return bStatus; } #endif