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 nullptr;
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 nullptr;
114
115#if defined(_UWP)
116 int status;
117 HMODULE hModule = nullptr;
118 WCHAR* filenameW = nullptr;
119
120 filenameW = ConvertUtf8ToWCharAlloc(lpLibFileName, nullptr);
121 if (filenameW)
122 return nullptr;
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 nullptr;
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 = nullptr;
148
149 if (lpLibFileName)
150 name = ConvertWCharToUtf8Alloc(lpLibFileName, nullptr);
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 != nullptr");
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 != nullptr");
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 = nullptr;
187 proc = dlsym(hModule, lpProcName);
188
189 if (proc == nullptr)
190 {
191 // NOLINTNEXTLINE(concurrency-mt-unsafe)
192 WLog_ERR(TAG, "GetProcAddress: could not find procedure %s: %s", lpProcName, dlerror());
193 return (FARPROC) nullptr;
194 }
195
196 return proc;
197}
198
199BOOL FreeLibrary(HMODULE hLibModule)
200{
201 int status = 0;
202 status = dlclose(hLibModule);
203
204 return (status == 0);
205}
206
207HMODULE GetModuleHandleA(LPCSTR lpModuleName)
208{
209 return dlopen(lpModuleName, RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY);
210}
211
212HMODULE GetModuleHandleW(LPCWSTR lpModuleName)
213{
214 char* name = nullptr;
215 if (lpModuleName)
216 name = ConvertWCharToUtf8Alloc(lpModuleName, nullptr);
217 HANDLE hdl = GetModuleHandleA(name);
218 free(name);
219 return hdl;
220}
221
230DWORD GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
231{
232 DWORD status = 0;
233 if (!lpFilename)
234 {
235 SetLastError(ERROR_INTERNAL_ERROR);
236 return 0;
237 }
238
239 char* name = calloc(nSize, sizeof(char));
240 if (!name)
241 {
242 SetLastError(ERROR_INTERNAL_ERROR);
243 return 0;
244 }
245 status = GetModuleFileNameA(hModule, name, nSize);
246
247 if ((status > INT_MAX) || (nSize > INT_MAX))
248 {
249 SetLastError(ERROR_INTERNAL_ERROR);
250 status = 0;
251 }
252
253 if (status > 0)
254 {
255 if (ConvertUtf8NToWChar(name, status, lpFilename, nSize) < 0)
256 {
257 free(name);
258 SetLastError(ERROR_INTERNAL_ERROR);
259 return 0;
260 }
261 }
262
263 free(name);
264 return status;
265}
266
267#if defined(__linux__) || defined(__NetBSD__) || defined(__DragonFly__)
268static DWORD module_from_proc(const char* proc, LPSTR lpFilename, DWORD nSize)
269{
270 char buffer[8192] = WINPR_C_ARRAY_INIT;
271 ssize_t status = readlink(proc, buffer, ARRAYSIZE(buffer) - 1);
272
273 if ((status < 0) || ((size_t)status >= ARRAYSIZE(buffer)))
274 {
275 SetLastError(ERROR_INTERNAL_ERROR);
276 return 0;
277 }
278
279 const size_t length = strnlen(buffer, ARRAYSIZE(buffer));
280
281 if (length < nSize)
282 {
283 CopyMemory(lpFilename, buffer, length);
284 lpFilename[length] = '\0';
285 return (DWORD)length;
286 }
287
288 CopyMemory(lpFilename, buffer, nSize - 1);
289 lpFilename[nSize - 1] = '\0';
290 SetLastError(ERROR_INSUFFICIENT_BUFFER);
291 return nSize;
292}
293#endif
294
295DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
296{
297 if (hModule)
298 {
299 WLog_ERR(TAG, "is not implemented");
300 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
301 return 0;
302 }
303
304#if defined(__linux__)
305 return module_from_proc("/proc/self/exe", lpFilename, nSize);
306#elif defined(__FreeBSD__)
307 int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
308 size_t cb = nSize;
309
310 {
311 const int rc = sysctl(mib, ARRAYSIZE(mib), nullptr, &cb, nullptr, 0);
312 if (rc != 0)
313 {
314 SetLastError(ERROR_INTERNAL_ERROR);
315 return 0;
316 }
317 }
318
319 char* fullname = calloc(cb + 1, sizeof(char));
320 if (!fullname)
321 {
322 SetLastError(ERROR_INTERNAL_ERROR);
323 return 0;
324 }
325
326 {
327 size_t cb2 = cb;
328 const int rc = sysctl(mib, ARRAYSIZE(mib), fullname, &cb2, nullptr, 0);
329 if ((rc != 0) || (cb2 != cb))
330 {
331 SetLastError(ERROR_INTERNAL_ERROR);
332 free(fullname);
333 return 0;
334 }
335 }
336
337 if (nSize > 0)
338 {
339 strncpy(lpFilename, fullname, nSize - 1);
340 lpFilename[nSize - 1] = '\0';
341 }
342 free(fullname);
343
344 if (nSize < cb)
345 SetLastError(ERROR_INSUFFICIENT_BUFFER);
346
347 return (DWORD)MIN(nSize, cb);
348#elif defined(__NetBSD__)
349 return module_from_proc("/proc/curproc/exe", lpFilename, nSize);
350#elif defined(__DragonFly__)
351 return module_from_proc("/proc/curproc/file", lpFilename, nSize);
352#elif defined(__MACOSX__)
353 char path[4096] = WINPR_C_ARRAY_INIT;
354 char buffer[4096] = WINPR_C_ARRAY_INIT;
355 uint32_t size = sizeof(path);
356 const int status = _NSGetExecutablePath(path, &size);
357
358 if (status != 0)
359 {
360 /* path too small */
361 SetLastError(ERROR_INTERNAL_ERROR);
362 return 0;
363 }
364
365 /*
366 * _NSGetExecutablePath may not return the canonical path,
367 * so use realpath to find the absolute, canonical path.
368 */
369 realpath(path, buffer);
370 const size_t length = strnlen(buffer, sizeof(buffer));
371
372 if (length < nSize)
373 {
374 CopyMemory(lpFilename, buffer, length);
375 lpFilename[length] = '\0';
376 return (DWORD)length;
377 }
378
379 CopyMemory(lpFilename, buffer, nSize - 1);
380 lpFilename[nSize - 1] = '\0';
381 SetLastError(ERROR_INSUFFICIENT_BUFFER);
382 return nSize;
383#else
384 WLog_ERR(TAG, "is not implemented");
385 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
386 return 0;
387#endif
388}
389
390#endif
391
392HMODULE LoadLibraryX(LPCSTR lpLibFileName)
393{
394#if defined(_WIN32)
395 HMODULE hm = nullptr;
396 WCHAR* wstr = nullptr;
397
398 if (lpLibFileName)
399 wstr = ConvertUtf8ToWCharAlloc(lpLibFileName, nullptr);
400
401 hm = LoadLibraryW(wstr);
402 free(wstr);
403 return hm;
404#else
405 return LoadLibraryA(lpLibFileName);
406#endif
407}
408
409HMODULE LoadLibraryExX(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
410{
411 if (!lpLibFileName)
412 return nullptr;
413#if defined(_WIN32)
414 HMODULE hm = nullptr;
415 WCHAR* wstr = ConvertUtf8ToWCharAlloc(lpLibFileName, nullptr);
416 if (wstr)
417 hm = LoadLibraryExW(wstr, hFile, dwFlags);
418 free(wstr);
419 return hm;
420#else
421 return LoadLibraryExA(lpLibFileName, hFile, dwFlags);
422#endif
423}