FreeRDP
shell/shell.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/shell.h>
23 
31 #ifndef _WIN32
32 
33 #include <winpr/crt.h>
34 
35 #ifdef WINPR_HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 
39 #include <pwd.h>
40 #include <grp.h>
41 
42 #include "../handle/handle.h"
43 
44 #include "../security/security.h"
45 
46 BOOL GetUserProfileDirectoryA(HANDLE hToken, LPSTR lpProfileDir, LPDWORD lpcchSize)
47 {
48  struct passwd pwd = { 0 };
49  struct passwd* pw = NULL;
50  WINPR_ACCESS_TOKEN* token = (WINPR_ACCESS_TOKEN*)hToken;
51 
52  if (!AccessTokenIsValid(hToken))
53  return FALSE;
54 
55  if (!lpcchSize)
56  {
57  SetLastError(ERROR_INVALID_PARAMETER);
58  return FALSE;
59  }
60 
61  long buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
62  if (buflen < 0)
63  buflen = 8196;
64 
65  const size_t s = 1ULL + (size_t)buflen;
66  char* buf = calloc(s, sizeof(char));
67 
68  if (!buf)
69  return FALSE;
70 
71  const int status = getpwnam_r(token->Username, &pwd, buf, buflen, &pw);
72 
73  if ((status != 0) || !pw)
74  {
75  SetLastError(ERROR_INVALID_PARAMETER);
76  free(buf);
77  return FALSE;
78  }
79 
80  const size_t cchDirSize = strlen(pw->pw_dir) + 1;
81  if (cchDirSize > UINT32_MAX)
82  {
83  SetLastError(ERROR_INVALID_PARAMETER);
84  free(buf);
85  return FALSE;
86  }
87 
88  if (!lpProfileDir || (*lpcchSize < cchDirSize))
89  {
90  *lpcchSize = (UINT32)cchDirSize;
91  SetLastError(ERROR_INSUFFICIENT_BUFFER);
92  free(buf);
93  return FALSE;
94  }
95 
96  ZeroMemory(lpProfileDir, *lpcchSize);
97  (void)sprintf_s(lpProfileDir, *lpcchSize, "%s", pw->pw_dir);
98  *lpcchSize = (UINT32)cchDirSize;
99  free(buf);
100  return TRUE;
101 }
102 
103 BOOL GetUserProfileDirectoryW(HANDLE hToken, LPWSTR lpProfileDir, LPDWORD lpcchSize)
104 {
105  BOOL bStatus = 0;
106  DWORD cchSizeA = 0;
107  LPSTR lpProfileDirA = NULL;
108 
109  if (!lpcchSize)
110  {
111  SetLastError(ERROR_INVALID_PARAMETER);
112  return FALSE;
113  }
114 
115  cchSizeA = *lpcchSize;
116  lpProfileDirA = NULL;
117 
118  if (lpProfileDir)
119  {
120  lpProfileDirA = (LPSTR)malloc(cchSizeA);
121 
122  if (lpProfileDirA == NULL)
123  {
124  SetLastError(ERROR_OUTOFMEMORY);
125  return FALSE;
126  }
127  }
128 
129  bStatus = GetUserProfileDirectoryA(hToken, lpProfileDirA, &cchSizeA);
130 
131  if (bStatus)
132  {
133  SSIZE_T size = ConvertUtf8NToWChar(lpProfileDirA, cchSizeA, lpProfileDir, *lpcchSize);
134  bStatus = size >= 0;
135  }
136 
137  if (lpProfileDirA)
138  {
139  free(lpProfileDirA);
140  }
141 
142  *lpcchSize = cchSizeA;
143  return bStatus;
144 }
145 
146 #endif