| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* GATE PROJECT LICENSE: | ||
| 2 | +----------------------------------------------------------------------------+ | ||
| 3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
| 4 | | All rights reserved. | | ||
| 5 | | | | ||
| 6 | | Redistribution and use in source and binary forms, with or without | | ||
| 7 | | modification, are permitted provided that the following conditions are met:| | ||
| 8 | | | | ||
| 9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
| 10 | | this list of conditions and the following disclaimer. | | ||
| 11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
| 12 | | notice, this list of conditions and the following disclaimer in the | | ||
| 13 | | documentation and/or other materials provided with the distribution. | | ||
| 14 | | | | ||
| 15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
| 16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
| 17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
| 18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
| 19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
| 20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
| 21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
| 22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
| 23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
| 24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
| 25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
| 26 | +----------------------------------------------------------------------------+ | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include "gate/libraries.h" | ||
| 30 | #include "gate/results.h" | ||
| 31 | #include "gate/platforms.h" | ||
| 32 | |||
| 33 | #if defined(GATE_SYS_WIN) | ||
| 34 | # define GATE_CORE_LIBRARIES_USE_WINAPI 1 | ||
| 35 | #elif defined(GATE_SYS_POSIX) | ||
| 36 | # define GATE_CORE_LIBRARIES_USE_POSIX 1 | ||
| 37 | #else | ||
| 38 | # define GATE_CORE_LIBRARIES_NO_IMPL 1 | ||
| 39 | #endif | ||
| 40 | |||
| 41 | |||
| 42 | ✗ | gate_result_t gate_library_get_function_name(gate_library_t lib, char const* funcname, void* ptrfunc) | |
| 43 | { | ||
| 44 | gate_library_function_t func; | ||
| 45 | gate_string_t name; | ||
| 46 | gate_result_t res; | ||
| 47 | ✗ | gate_string_create_static(&name, funcname); | |
| 48 | ✗ | res = gate_library_get_function(lib, &name, &func); | |
| 49 | ✗ | if (GATE_SUCCEEDED(res)) | |
| 50 | { | ||
| 51 | ✗ | *((gate_library_function_t*)ptrfunc) = func; | |
| 52 | } | ||
| 53 | else | ||
| 54 | { | ||
| 55 | ✗ | *((gate_library_function_t*)ptrfunc) = NULL; | |
| 56 | } | ||
| 57 | ✗ | return res; | |
| 58 | } | ||
| 59 | |||
| 60 | 24 | gate_result_t gate_library_get_data_name(gate_library_t lib, char const* entryname, void* ptr_data) | |
| 61 | { | ||
| 62 | void* data; | ||
| 63 | gate_string_t name; | ||
| 64 | gate_result_t res; | ||
| 65 | 24 | gate_string_create_static(&name, entryname); | |
| 66 | 24 | res = gate_library_get_data(lib, &name, &data); | |
| 67 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | if (GATE_SUCCEEDED(res)) |
| 68 | { | ||
| 69 | 24 | *((void**)ptr_data) = data; | |
| 70 | } | ||
| 71 | else | ||
| 72 | { | ||
| 73 | ✗ | *((void**)ptr_data) = NULL; | |
| 74 | } | ||
| 75 | 24 | return res; | |
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | |||
| 80 | #if defined(GATE_CORE_LIBRARIES_USE_WINAPI) | ||
| 81 | |||
| 82 | #ifndef DONT_RESOLVE_DLL_REFERENCES | ||
| 83 | #define DONT_RESOLVE_DLL_REFERENCES 0x00000001 | ||
| 84 | #endif | ||
| 85 | |||
| 86 | static gate_bool_t is_hmodule_valid(HMODULE hmod) | ||
| 87 | { | ||
| 88 | #if defined(GATE_SYS_WIN16) | ||
| 89 | return (hmod > HINSTANCE_ERROR); | ||
| 90 | #else | ||
| 91 | return (hmod != NULL); | ||
| 92 | #endif | ||
| 93 | } | ||
| 94 | |||
| 95 | gate_bool_t gate_library_support() | ||
| 96 | { | ||
| 97 | return true; | ||
| 98 | } | ||
| 99 | |||
| 100 | gate_result_t gate_library_open(gate_string_t const* path, gate_library_t* lib, gate_enumint_t flags) | ||
| 101 | { | ||
| 102 | gate_result_t ret; | ||
| 103 | TCHAR libpath[GATE_MAX_FILEPATH_LENGTH]; | ||
| 104 | HMODULE hmod; | ||
| 105 | DWORD dwflags = 0; | ||
| 106 | gate_size_t libpathlen = gate_win32_utf8_2_winstr(path->str, path->length, libpath, sizeof(libpath) / sizeof(libpath[0])); | ||
| 107 | if (libpathlen == 0) | ||
| 108 | { | ||
| 109 | return GATE_RESULT_INVALIDDATA; | ||
| 110 | } | ||
| 111 | if (GATE_FLAG_ENABLED(flags, GATE_LIBRARY_FLAG_DATA)) | ||
| 112 | { | ||
| 113 | dwflags |= DONT_RESOLVE_DLL_REFERENCES; | ||
| 114 | } | ||
| 115 | hmod = gate_win32_load_library(libpath, dwflags); | ||
| 116 | if (is_hmodule_valid(hmod)) | ||
| 117 | { | ||
| 118 | *lib = (gate_library_t)hmod; | ||
| 119 | ret = GATE_RESULT_OK; | ||
| 120 | } | ||
| 121 | else | ||
| 122 | { | ||
| 123 | gate_win32_print_lasterror(&ret, NULL, 0); | ||
| 124 | } | ||
| 125 | return ret; | ||
| 126 | } | ||
| 127 | gate_result_t gate_library_close(gate_library_t lib) | ||
| 128 | { | ||
| 129 | gate_result_t ret; | ||
| 130 | HMODULE hmod = (HMODULE)lib; | ||
| 131 | BOOL succeeded = true; | ||
| 132 | #if !defined(GATE_SYS_WIN16) | ||
| 133 | succeeded = | ||
| 134 | #endif | ||
| 135 | FreeLibrary(hmod); | ||
| 136 | if (succeeded) | ||
| 137 | { | ||
| 138 | ret = GATE_RESULT_OK; | ||
| 139 | } | ||
| 140 | else | ||
| 141 | { | ||
| 142 | gate_win32_print_lasterror(&ret, NULL, 0); | ||
| 143 | } | ||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | gate_result_t gate_library_get_function(gate_library_t lib, gate_string_t const* entryname, gate_library_function_t* func) | ||
| 147 | { | ||
| 148 | gate_result_t ret; | ||
| 149 | HMODULE hmod = (HMODULE)lib; | ||
| 150 | gate_size_t procnamelen; | ||
| 151 | FARPROC proc; | ||
| 152 | #if defined(GATE_SYS_WINCE) | ||
| 153 | TCHAR procname[GATE_MAX_FILENAME_LENGTH]; | ||
| 154 | procnamelen = gate_win32_utf8_2_winstr(entryname->str, entryname->length, procname, sizeof(procname) / sizeof(procname[0])); | ||
| 155 | #else | ||
| 156 | char procname[GATE_MAX_FILENAME_LENGTH]; | ||
| 157 | procnamelen = gate_str_print_text(procname, sizeof(procname) / sizeof(procname[0]), entryname->str, entryname->length); | ||
| 158 | #endif | ||
| 159 | if (procnamelen == 0) | ||
| 160 | { | ||
| 161 | return GATE_RESULT_INVALIDDATA; | ||
| 162 | } | ||
| 163 | proc = GetProcAddress(hmod, procname); | ||
| 164 | if (proc == NULL) | ||
| 165 | { | ||
| 166 | gate_win32_print_lasterror(&ret, NULL, 0); | ||
| 167 | } | ||
| 168 | else | ||
| 169 | { | ||
| 170 | *func = (gate_library_function_t)proc; | ||
| 171 | ret = GATE_RESULT_OK; | ||
| 172 | } | ||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | gate_result_t gate_library_get_data(gate_library_t lib, gate_string_t const* entryname, void** data) | ||
| 176 | { | ||
| 177 | gate_library_function_t ptr; | ||
| 178 | gate_result_t ret = gate_library_get_function(lib, entryname, &ptr); | ||
| 179 | if (GATE_SUCCEEDED(ret)) | ||
| 180 | { | ||
| 181 | *data = (void*)ptr; | ||
| 182 | } | ||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | |||
| 186 | #endif /* GATE_CORE_LIBRARIES_USE_WINAPI */ | ||
| 187 | |||
| 188 | |||
| 189 | |||
| 190 | #if defined(GATE_CORE_LIBRARIES_USE_POSIX) | ||
| 191 | |||
| 192 | # include "dlfcn.h" | ||
| 193 | |||
| 194 | 1 | gate_bool_t gate_library_support() | |
| 195 | { | ||
| 196 | static gate_bool_t volatile test_completed = false; | ||
| 197 | static gate_bool_t volatile test_result = false; | ||
| 198 | |||
| 199 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!test_completed) |
| 200 | { | ||
| 201 | 1 | void* proc_handle = gate_posix_dlopen(NULL, RTLD_LAZY); | |
| 202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (NULL == proc_handle) |
| 203 | { | ||
| 204 | /* dlopen not supported (e.g. in a static binary) */ | ||
| 205 | ✗ | test_result = false; | |
| 206 | } | ||
| 207 | else | ||
| 208 | { | ||
| 209 | 1 | test_result = true; | |
| 210 | 1 | gate_posix_dlclose(proc_handle); | |
| 211 | } | ||
| 212 | 1 | test_completed = true; | |
| 213 | } | ||
| 214 | 1 | return test_result; | |
| 215 | } | ||
| 216 | |||
| 217 | 6 | gate_result_t gate_library_open(gate_string_t const* path, gate_library_t* lib, gate_enumint_t flags) | |
| 218 | { | ||
| 219 | gate_result_t ret; | ||
| 220 | |||
| 221 | do | ||
| 222 | { | ||
| 223 | void* handle; | ||
| 224 | 6 | int dlflags = 0; | |
| 225 | char libpath[GATE_MAX_FILEPATH_LENGTH]; | ||
| 226 | 6 | gate_size_t libpathlen = gate_str_print_text(libpath, sizeof(libpath) / sizeof(libpath[0]), path->str, path->length); | |
| 227 | |||
| 228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (libpathlen == 0) |
| 229 | { | ||
| 230 | ✗ | ret = GATE_RESULT_INVALIDARG; | |
| 231 | 3 | break; | |
| 232 | } | ||
| 233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (GATE_FLAG_ENABLED(flags, GATE_LIBRARY_FLAG_DATA)) |
| 234 | { | ||
| 235 | ✗ | dlflags |= RTLD_LAZY; | |
| 236 | } | ||
| 237 | else | ||
| 238 | { | ||
| 239 | 6 | dlflags |= RTLD_NOW; | |
| 240 | } | ||
| 241 | |||
| 242 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (GATE_FLAG_ENABLED(flags, GATE_LIBRARY_FLAG_LOCAL)) |
| 243 | { | ||
| 244 | ✗ | dlflags |= RTLD_LOCAL; | |
| 245 | } | ||
| 246 | else | ||
| 247 | { | ||
| 248 | 6 | dlflags |= RTLD_GLOBAL; | |
| 249 | } | ||
| 250 | |||
| 251 | 6 | handle = gate_posix_dlopen(libpath, dlflags); | |
| 252 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (handle == NULL) |
| 253 | { | ||
| 254 | 3 | ret = GATE_RESULT_FAILED; | |
| 255 | 3 | break; | |
| 256 | } | ||
| 257 | |||
| 258 | /* success: */ | ||
| 259 | 3 | *lib = (gate_library_t)handle; | |
| 260 | 3 | ret = GATE_RESULT_OK; | |
| 261 | |||
| 262 | } while (0); | ||
| 263 | |||
| 264 | 6 | return ret; | |
| 265 | } | ||
| 266 | 3 | gate_result_t gate_library_close(gate_library_t lib) | |
| 267 | { | ||
| 268 | 3 | void* handle = (void*)lib; | |
| 269 | 3 | int errcode = gate_posix_dlclose(handle); | |
| 270 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | return ((errcode == 0) ? GATE_RESULT_OK : GATE_RESULT_FAILED); |
| 271 | } | ||
| 272 | 4 | gate_result_t gate_library_get_function(gate_library_t lib, gate_string_t const* entryname, gate_library_function_t* func) | |
| 273 | { | ||
| 274 | gate_result_t ret; | ||
| 275 | void* dataptr; | ||
| 276 | 4 | ret = gate_library_get_data(lib, entryname, &dataptr); | |
| 277 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | if (GATE_SUCCEEDED(ret) && (func != NULL)) |
| 278 | { | ||
| 279 | 2 | *func = (gate_library_function_t)dataptr; | |
| 280 | } | ||
| 281 | 4 | return ret; | |
| 282 | } | ||
| 283 | 30 | gate_result_t gate_library_get_data(gate_library_t lib, gate_string_t const* entryname, void** data) | |
| 284 | { | ||
| 285 | gate_result_t ret; | ||
| 286 | 30 | void* handle = (void*)lib; | |
| 287 | void* dataptr; | ||
| 288 | char name[GATE_MAX_FILENAME_LENGTH]; | ||
| 289 | 30 | gate_size_t entrylen = gate_str_print_text(name, sizeof(name) / sizeof(name[0]), entryname->str, entryname->length); | |
| 290 | do | ||
| 291 | { | ||
| 292 |
2/4✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
|
30 | if ((handle == NULL) || (entrylen == 0)) |
| 293 | { | ||
| 294 | ✗ | ret = GATE_RESULT_INVALIDARG; | |
| 295 | ✗ | break; | |
| 296 | } | ||
| 297 | |||
| 298 | 30 | dataptr = gate_posix_dlsym(handle, name); | |
| 299 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 26 times.
|
30 | if (dataptr == NULL) |
| 300 | { | ||
| 301 | 4 | ret = GATE_RESULT_FAILED; | |
| 302 | 4 | break; | |
| 303 | } | ||
| 304 | |||
| 305 | /*success case*/ | ||
| 306 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | if (data != NULL) |
| 307 | { | ||
| 308 | 26 | *data = dataptr; | |
| 309 | } | ||
| 310 | 26 | ret = GATE_RESULT_OK; | |
| 311 | |||
| 312 | } while (0); | ||
| 313 | |||
| 314 | 30 | return ret; | |
| 315 | } | ||
| 316 | |||
| 317 | #endif /* GATE_SYS_POSIX */ | ||
| 318 | |||
| 319 | |||
| 320 | |||
| 321 | #if defined(GATE_CORE_LIBRARIES_NO_IMPL) | ||
| 322 | |||
| 323 | gate_bool_t gate_library_support() | ||
| 324 | { | ||
| 325 | return false; | ||
| 326 | } | ||
| 327 | |||
| 328 | gate_result_t gate_library_open(gate_string_t const* path, gate_library_t* lib, gate_enumint_t flags) | ||
| 329 | { | ||
| 330 | (void)path; | ||
| 331 | (void)lib; | ||
| 332 | (void)flags; | ||
| 333 | return GATE_RESULT_NOTSUPPORTED; | ||
| 334 | } | ||
| 335 | gate_result_t gate_library_close(gate_library_t lib) | ||
| 336 | { | ||
| 337 | (void)lib; | ||
| 338 | return GATE_RESULT_NOTSUPPORTED; | ||
| 339 | } | ||
| 340 | gate_result_t gate_library_get_function(gate_library_t lib, gate_string_t const* entryname, gate_library_function_t* ptr_func) | ||
| 341 | { | ||
| 342 | (void)lib; | ||
| 343 | (void)entryname; | ||
| 344 | (void)ptr_func; | ||
| 345 | return GATE_RESULT_NOTSUPPORTED; | ||
| 346 | } | ||
| 347 | gate_result_t gate_library_get_data(gate_library_t lib, gate_string_t const* entryname, void** ptr_data) | ||
| 348 | { | ||
| 349 | (void)lib; | ||
| 350 | (void)entryname; | ||
| 351 | (void)ptr_data; | ||
| 352 | return GATE_RESULT_NOTSUPPORTED; | ||
| 353 | } | ||
| 354 | |||
| 355 | #endif /* GATE_CORE_LIBRARIES_NO_IMPL */ | ||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 |