Coverage Report

Created: 2024-09-08 06:20

/src/FreeRDP/winpr/libwinpr/library/library.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Library Loader
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
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
30
/**
31
 * api-ms-win-core-libraryloader-l1-1-1.dll:
32
 *
33
 * AddDllDirectory
34
 * RemoveDllDirectory
35
 * SetDefaultDllDirectories
36
 * DisableThreadLibraryCalls
37
 * EnumResourceLanguagesExA
38
 * EnumResourceLanguagesExW
39
 * EnumResourceNamesExA
40
 * EnumResourceNamesExW
41
 * EnumResourceTypesExA
42
 * EnumResourceTypesExW
43
 * FindResourceExW
44
 * FindStringOrdinal
45
 * FreeLibrary
46
 * FreeLibraryAndExitThread
47
 * FreeResource
48
 * GetModuleFileNameA
49
 * GetModuleFileNameW
50
 * GetModuleHandleA
51
 * GetModuleHandleExA
52
 * GetModuleHandleExW
53
 * GetModuleHandleW
54
 * GetProcAddress
55
 * LoadLibraryExA
56
 * LoadLibraryExW
57
 * LoadResource
58
 * LoadStringA
59
 * LoadStringW
60
 * LockResource
61
 * QueryOptionalDelayLoadedAPI
62
 * SizeofResource
63
 */
64
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
#endif
81
82
DLL_DIRECTORY_COOKIE AddDllDirectory(PCWSTR NewDirectory)
83
0
{
84
  /* TODO: Implement */
85
0
  WLog_ERR(TAG, "not implemented");
86
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
87
0
  return NULL;
88
0
}
89
90
BOOL RemoveDllDirectory(DLL_DIRECTORY_COOKIE Cookie)
91
0
{
92
  /* TODO: Implement */
93
0
  WLog_ERR(TAG, "not implemented");
94
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
95
0
  return FALSE;
96
0
}
97
98
BOOL SetDefaultDllDirectories(DWORD DirectoryFlags)
99
0
{
100
  /* TODO: Implement */
101
0
  WLog_ERR(TAG, "not implemented");
102
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
103
0
  return FALSE;
104
0
}
105
106
HMODULE LoadLibraryA(LPCSTR lpLibFileName)
107
0
{
108
#if defined(_UWP)
109
  int status;
110
  HMODULE hModule = NULL;
111
  WCHAR* filenameW = NULL;
112
113
  if (!lpLibFileName)
114
    return NULL;
115
116
  filenameW = ConvertUtf8ToWCharAlloc(lpLibFileName, NULL);
117
  if (filenameW)
118
    return NULL;
119
120
  hModule = LoadLibraryW(filenameW);
121
  free(filenameW);
122
  return hModule;
123
#else
124
0
  HMODULE library = NULL;
125
0
  library = dlopen(lpLibFileName, RTLD_LOCAL | RTLD_LAZY);
126
127
0
  if (!library)
128
0
  {
129
0
    const char* err = dlerror();
130
0
    WLog_ERR(TAG, "failed with %s", err);
131
0
    return NULL;
132
0
  }
133
134
0
  return library;
135
0
#endif
136
0
}
137
138
HMODULE LoadLibraryW(LPCWSTR lpLibFileName)
139
0
{
140
0
  if (!lpLibFileName)
141
0
    return NULL;
142
#if defined(_UWP)
143
  return LoadPackagedLibrary(lpLibFileName, 0);
144
#else
145
0
  HMODULE module = NULL;
146
0
  char* name = ConvertWCharToUtf8Alloc(lpLibFileName, NULL);
147
0
  if (!name)
148
0
    return NULL;
149
150
0
  module = LoadLibraryA(name);
151
0
  free(name);
152
0
  return module;
153
0
#endif
154
0
}
155
156
HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
157
0
{
158
0
  if (dwFlags != 0)
159
0
    WLog_WARN(TAG, "does not support dwFlags 0x%08" PRIx32, dwFlags);
160
161
0
  if (hFile)
162
0
    WLog_WARN(TAG, "does not support hFile != NULL");
163
164
0
  return LoadLibraryA(lpLibFileName);
165
0
}
166
167
HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
168
0
{
169
0
  if (dwFlags != 0)
170
0
    WLog_WARN(TAG, "does not support dwFlags 0x%08" PRIx32, dwFlags);
171
172
0
  if (hFile)
173
0
    WLog_WARN(TAG, "does not support hFile != NULL");
174
175
0
  return LoadLibraryW(lpLibFileName);
176
0
}
177
178
#endif
179
180
#if !defined(_WIN32) && !defined(__CYGWIN__)
181
182
FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
183
0
{
184
0
  FARPROC proc = NULL;
185
0
  proc = dlsym(hModule, lpProcName);
186
187
0
  if (proc == NULL)
188
0
  {
189
0
    WLog_ERR(TAG, "GetProcAddress: could not find procedure %s: %s", lpProcName, dlerror());
190
0
    return (FARPROC)NULL;
191
0
  }
192
193
0
  return proc;
194
0
}
195
196
BOOL FreeLibrary(HMODULE hLibModule)
197
0
{
198
0
  int status = 0;
199
0
  status = dlclose(hLibModule);
200
201
0
  if (status != 0)
202
0
    return FALSE;
203
204
0
  return TRUE;
205
0
}
206
207
HMODULE GetModuleHandleA(LPCSTR lpModuleName)
208
0
{
209
  /* TODO: Implement */
210
0
  WLog_ERR(TAG, "not implemented");
211
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
212
0
  return NULL;
213
0
}
214
215
HMODULE GetModuleHandleW(LPCWSTR lpModuleName)
216
0
{
217
  /* TODO: Implement */
218
0
  WLog_ERR(TAG, "not implemented");
219
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
220
0
  return NULL;
221
0
}
222
223
/**
224
 * GetModuleFileName:
225
 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms683197/
226
 *
227
 * Finding current executable's path without /proc/self/exe:
228
 * http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
229
 */
230
231
DWORD GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
232
0
{
233
0
  DWORD status = 0;
234
0
  if (!lpFilename)
235
0
  {
236
0
    SetLastError(ERROR_INTERNAL_ERROR);
237
0
    return 0;
238
0
  }
239
240
0
  char* name = calloc(nSize, sizeof(char));
241
0
  if (!name)
242
0
  {
243
0
    SetLastError(ERROR_INTERNAL_ERROR);
244
0
    return 0;
245
0
  }
246
0
  status = GetModuleFileNameA(hModule, name, nSize);
247
248
0
  if ((status > INT_MAX) || (nSize > INT_MAX))
249
0
  {
250
0
    SetLastError(ERROR_INTERNAL_ERROR);
251
0
    status = 0;
252
0
  }
253
254
0
  if (status > 0)
255
0
  {
256
0
    if (ConvertUtf8NToWChar(name, status, lpFilename, nSize) < 0)
257
0
    {
258
0
      free(name);
259
0
      SetLastError(ERROR_INTERNAL_ERROR);
260
0
      return 0;
261
0
    }
262
0
  }
263
264
0
  free(name);
265
0
  return status;
266
0
}
267
268
DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
269
0
{
270
0
#if defined(__linux__)
271
0
  SSIZE_T status = 0;
272
0
  size_t length = 0;
273
0
  char path[64];
274
275
0
  if (!hModule)
276
0
  {
277
0
    char buffer[4096] = { 0 };
278
0
    (void)sprintf_s(path, ARRAYSIZE(path), "/proc/%d/exe", getpid());
279
0
    status = readlink(path, buffer, ARRAYSIZE(buffer) - 1);
280
281
0
    if ((status < 0) || ((size_t)status >= ARRAYSIZE(buffer)))
282
0
    {
283
0
      SetLastError(ERROR_INTERNAL_ERROR);
284
0
      return 0;
285
0
    }
286
287
0
    length = strnlen(buffer, ARRAYSIZE(buffer));
288
289
0
    if (length < nSize)
290
0
    {
291
0
      CopyMemory(lpFilename, buffer, length);
292
0
      lpFilename[length] = '\0';
293
0
      return (DWORD)length;
294
0
    }
295
296
0
    CopyMemory(lpFilename, buffer, nSize - 1);
297
0
    lpFilename[nSize - 1] = '\0';
298
0
    SetLastError(ERROR_INSUFFICIENT_BUFFER);
299
0
    return nSize;
300
0
  }
301
302
#elif defined(__MACOSX__)
303
  int status;
304
  size_t length;
305
306
  if (!hModule)
307
  {
308
    char path[4096];
309
    char buffer[4096];
310
    uint32_t size = sizeof(path);
311
    status = _NSGetExecutablePath(path, &size);
312
313
    if (status != 0)
314
    {
315
      /* path too small */
316
      SetLastError(ERROR_INTERNAL_ERROR);
317
      return 0;
318
    }
319
320
    /*
321
     * _NSGetExecutablePath may not return the canonical path,
322
     * so use realpath to find the absolute, canonical path.
323
     */
324
    realpath(path, buffer);
325
    length = strnlen(buffer, sizeof(buffer));
326
327
    if (length < nSize)
328
    {
329
      CopyMemory(lpFilename, buffer, length);
330
      lpFilename[length] = '\0';
331
      return (DWORD)length;
332
    }
333
334
    CopyMemory(lpFilename, buffer, nSize - 1);
335
    lpFilename[nSize - 1] = '\0';
336
    SetLastError(ERROR_INSUFFICIENT_BUFFER);
337
    return nSize;
338
  }
339
340
#endif
341
0
  WLog_ERR(TAG, "is not implemented");
342
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
343
0
  return 0;
344
0
}
345
346
#endif
347
348
HMODULE LoadLibraryX(LPCSTR lpLibFileName)
349
0
{
350
0
  if (!lpLibFileName)
351
0
    return NULL;
352
353
#if defined(_WIN32)
354
  HMODULE hm = NULL;
355
  WCHAR* wstr = ConvertUtf8ToWCharAlloc(lpLibFileName, NULL);
356
357
  if (wstr)
358
    hm = LoadLibraryW(wstr);
359
  free(wstr);
360
  return hm;
361
#else
362
0
  return LoadLibraryA(lpLibFileName);
363
0
#endif
364
0
}
365
366
HMODULE LoadLibraryExX(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
367
0
{
368
0
  if (!lpLibFileName)
369
0
    return NULL;
370
#if defined(_WIN32)
371
  HMODULE hm = NULL;
372
  WCHAR* wstr = ConvertUtf8ToWCharAlloc(lpLibFileName, NULL);
373
  if (wstr)
374
    hm = LoadLibraryExW(wstr, hFile, dwFlags);
375
  free(wstr);
376
  return hm;
377
#else
378
0
  return LoadLibraryExA(lpLibFileName, hFile, dwFlags);
379
0
#endif
380
0
}