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