FreeRDP
library.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/crt.h>
23 #include <winpr/platform.h>
24 
25 #include <winpr/library.h>
26 
27 #include "../log.h"
28 #define TAG WINPR_TAG("library")
29 
65 #if !defined(_WIN32) || defined(_UWP)
66 
67 #ifndef _WIN32
68 
69 #include <dlfcn.h>
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <unistd.h>
73 #include <sys/types.h>
74 #include <sys/stat.h>
75 
76 #ifdef __MACOSX__
77 #include <mach-o/dyld.h>
78 #endif
79 
80 #if defined(__FreeBSD__)
81 #include <sys/sysctl.h>
82 #endif
83 
84 #endif
85 
86 DLL_DIRECTORY_COOKIE AddDllDirectory(PCWSTR NewDirectory)
87 {
88  /* TODO: Implement */
89  WLog_ERR(TAG, "not implemented");
90  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
91  return NULL;
92 }
93 
94 BOOL RemoveDllDirectory(DLL_DIRECTORY_COOKIE Cookie)
95 {
96  /* TODO: Implement */
97  WLog_ERR(TAG, "not implemented");
98  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
99  return FALSE;
100 }
101 
102 BOOL SetDefaultDllDirectories(DWORD DirectoryFlags)
103 {
104  /* TODO: Implement */
105  WLog_ERR(TAG, "not implemented");
106  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
107  return FALSE;
108 }
109 
110 HMODULE LoadLibraryA(LPCSTR lpLibFileName)
111 {
112 #if defined(_UWP)
113  int status;
114  HMODULE hModule = NULL;
115  WCHAR* filenameW = NULL;
116 
117  if (!lpLibFileName)
118  return NULL;
119 
120  filenameW = ConvertUtf8ToWCharAlloc(lpLibFileName, NULL);
121  if (filenameW)
122  return NULL;
123 
124  hModule = LoadLibraryW(filenameW);
125  free(filenameW);
126  return hModule;
127 #else
128  HMODULE library = NULL;
129  library = dlopen(lpLibFileName, RTLD_LOCAL | RTLD_LAZY);
130 
131  if (!library)
132  {
133  const char* err = dlerror();
134  WLog_ERR(TAG, "failed with %s", err);
135  return NULL;
136  }
137 
138  return library;
139 #endif
140 }
141 
142 HMODULE LoadLibraryW(LPCWSTR lpLibFileName)
143 {
144  if (!lpLibFileName)
145  return NULL;
146 #if defined(_UWP)
147  return LoadPackagedLibrary(lpLibFileName, 0);
148 #else
149  HMODULE module = NULL;
150  char* name = ConvertWCharToUtf8Alloc(lpLibFileName, NULL);
151  if (!name)
152  return NULL;
153 
154  module = LoadLibraryA(name);
155  free(name);
156  return module;
157 #endif
158 }
159 
160 HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
161 {
162  if (dwFlags != 0)
163  WLog_WARN(TAG, "does not support dwFlags 0x%08" PRIx32, dwFlags);
164 
165  if (hFile)
166  WLog_WARN(TAG, "does not support hFile != NULL");
167 
168  return LoadLibraryA(lpLibFileName);
169 }
170 
171 HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
172 {
173  if (dwFlags != 0)
174  WLog_WARN(TAG, "does not support dwFlags 0x%08" PRIx32, dwFlags);
175 
176  if (hFile)
177  WLog_WARN(TAG, "does not support hFile != NULL");
178 
179  return LoadLibraryW(lpLibFileName);
180 }
181 
182 #endif
183 
184 #if !defined(_WIN32) && !defined(__CYGWIN__)
185 
186 FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
187 {
188  FARPROC proc = NULL;
189  proc = dlsym(hModule, lpProcName);
190 
191  if (proc == NULL)
192  {
193  WLog_ERR(TAG, "GetProcAddress: could not find procedure %s: %s", lpProcName, dlerror());
194  return (FARPROC)NULL;
195  }
196 
197  return proc;
198 }
199 
200 BOOL FreeLibrary(HMODULE hLibModule)
201 {
202  int status = 0;
203  status = dlclose(hLibModule);
204 
205  if (status != 0)
206  return FALSE;
207 
208  return TRUE;
209 }
210 
211 HMODULE GetModuleHandleA(LPCSTR lpModuleName)
212 {
213  /* TODO: Implement */
214  WLog_ERR(TAG, "not implemented");
215  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
216  return NULL;
217 }
218 
219 HMODULE GetModuleHandleW(LPCWSTR lpModuleName)
220 {
221  /* TODO: Implement */
222  WLog_ERR(TAG, "not implemented");
223  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
224  return NULL;
225 }
226 
235 DWORD GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
236 {
237  DWORD status = 0;
238  if (!lpFilename)
239  {
240  SetLastError(ERROR_INTERNAL_ERROR);
241  return 0;
242  }
243 
244  char* name = calloc(nSize, sizeof(char));
245  if (!name)
246  {
247  SetLastError(ERROR_INTERNAL_ERROR);
248  return 0;
249  }
250  status = GetModuleFileNameA(hModule, name, nSize);
251 
252  if ((status > INT_MAX) || (nSize > INT_MAX))
253  {
254  SetLastError(ERROR_INTERNAL_ERROR);
255  status = 0;
256  }
257 
258  if (status > 0)
259  {
260  if (ConvertUtf8NToWChar(name, status, lpFilename, nSize) < 0)
261  {
262  free(name);
263  SetLastError(ERROR_INTERNAL_ERROR);
264  return 0;
265  }
266  }
267 
268  free(name);
269  return status;
270 }
271 
272 #if defined(__linux__) || defined(__NetBSD__) || defined(__DragonFly__)
273 static DWORD module_from_proc(const char* proc, LPSTR lpFilename, DWORD nSize)
274 {
275  char buffer[8192] = { 0 };
276  ssize_t status = readlink(proc, buffer, ARRAYSIZE(buffer) - 1);
277 
278  if ((status < 0) || ((size_t)status >= ARRAYSIZE(buffer)))
279  {
280  SetLastError(ERROR_INTERNAL_ERROR);
281  return 0;
282  }
283 
284  const size_t length = strnlen(buffer, ARRAYSIZE(buffer));
285 
286  if (length < nSize)
287  {
288  CopyMemory(lpFilename, buffer, length);
289  lpFilename[length] = '\0';
290  return (DWORD)length;
291  }
292 
293  CopyMemory(lpFilename, buffer, nSize - 1);
294  lpFilename[nSize - 1] = '\0';
295  SetLastError(ERROR_INSUFFICIENT_BUFFER);
296  return nSize;
297 }
298 #endif
299 
300 DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
301 {
302  if (hModule)
303  {
304  WLog_ERR(TAG, "is not implemented");
305  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
306  return 0;
307  }
308 
309 #if defined(__linux__)
310  return module_from_proc("/proc/self/exe", lpFilename, nSize);
311 #elif defined(__FreeBSD__)
312  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
313  size_t cb = nSize;
314 
315  {
316  const int rc = sysctl(mib, ARRAYSIZE(mib), NULL, &cb, NULL, 0);
317  if (rc != 0)
318  {
319  SetLastError(ERROR_INTERNAL_ERROR);
320  return 0;
321  }
322  }
323 
324  char* fullname = calloc(cb + 1, sizeof(char));
325  if (!fullname)
326  {
327  SetLastError(ERROR_INTERNAL_ERROR);
328  return 0;
329  }
330 
331  {
332  size_t cb2 = cb;
333  const int rc = sysctl(mib, ARRAYSIZE(mib), fullname, &cb2, NULL, 0);
334  if ((rc != 0) || (cb2 != cb))
335  {
336  SetLastError(ERROR_INTERNAL_ERROR);
337  free(fullname);
338  return 0;
339  }
340  }
341 
342  if (nSize > 0)
343  {
344  strncpy(lpFilename, fullname, nSize - 1);
345  lpFilename[nSize - 1] = '\0';
346  }
347  free(fullname);
348 
349  if (nSize < cb)
350  SetLastError(ERROR_INSUFFICIENT_BUFFER);
351 
352  return (DWORD)MIN(nSize, cb);
353 #elif defined(__NetBSD__)
354  return module_from_proc("/proc/curproc/exe", lpFilename, nSize);
355 #elif defined(__DragonFly__)
356  return module_from_proc("/proc/curproc/file", lpFilename, nSize);
357 #elif defined(__MACOSX__)
358  char path[4096] = { 0 };
359  char buffer[4096] = { 0 };
360  uint32_t size = sizeof(path);
361  const int status = _NSGetExecutablePath(path, &size);
362 
363  if (status != 0)
364  {
365  /* path too small */
366  SetLastError(ERROR_INTERNAL_ERROR);
367  return 0;
368  }
369 
370  /*
371  * _NSGetExecutablePath may not return the canonical path,
372  * so use realpath to find the absolute, canonical path.
373  */
374  realpath(path, buffer);
375  const size_t length = strnlen(buffer, sizeof(buffer));
376 
377  if (length < nSize)
378  {
379  CopyMemory(lpFilename, buffer, length);
380  lpFilename[length] = '\0';
381  return (DWORD)length;
382  }
383 
384  CopyMemory(lpFilename, buffer, nSize - 1);
385  lpFilename[nSize - 1] = '\0';
386  SetLastError(ERROR_INSUFFICIENT_BUFFER);
387  return nSize;
388 #endif
389  WLog_ERR(TAG, "is not implemented");
390  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
391  return 0;
392 }
393 
394 #endif
395 
396 HMODULE LoadLibraryX(LPCSTR lpLibFileName)
397 {
398  if (!lpLibFileName)
399  return NULL;
400 
401 #if defined(_WIN32)
402  HMODULE hm = NULL;
403  WCHAR* wstr = ConvertUtf8ToWCharAlloc(lpLibFileName, NULL);
404 
405  if (wstr)
406  hm = LoadLibraryW(wstr);
407  free(wstr);
408  return hm;
409 #else
410  return LoadLibraryA(lpLibFileName);
411 #endif
412 }
413 
414 HMODULE LoadLibraryExX(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
415 {
416  if (!lpLibFileName)
417  return NULL;
418 #if defined(_WIN32)
419  HMODULE hm = NULL;
420  WCHAR* wstr = ConvertUtf8ToWCharAlloc(lpLibFileName, NULL);
421  if (wstr)
422  hm = LoadLibraryExW(wstr, hFile, dwFlags);
423  free(wstr);
424  return hm;
425 #else
426  return LoadLibraryExA(lpLibFileName, hFile, dwFlags);
427 #endif
428 }