From adb118290b238d6454f495797b944de99a5738e8 Mon Sep 17 00:00:00 2001 From: chuck- Date: Fri, 12 Jun 2020 10:41:48 +0200 Subject: [PATCH] osdep/io: provide dlopen, etc. abstraction wrappers for windows --- osdep/io.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ osdep/io.h | 9 +++++++ 2 files changed, 79 insertions(+) diff --git a/osdep/io.c b/osdep/io.c index 8cd6dede85..790caf6ec6 100644 --- a/osdep/io.c +++ b/osdep/io.c @@ -699,6 +699,76 @@ off_t mp_lseek(int fd, off_t offset, int whence) return _lseeki64(fd, offset, whence); } +_Thread_local +static struct { + DWORD errcode; + char *errstring; +} mp_dl_result = { + .errcode = 0, + .errstring = NULL +}; + +static void mp_dl_free(void) +{ + if (mp_dl_result.errstring != NULL) { + talloc_free(mp_dl_result.errstring); + } +} + +static void mp_dl_init(void) +{ + atexit(mp_dl_free); +} + +void *mp_dlopen(const char *filename, int flag) +{ + wchar_t *wfilename = mp_from_utf8(NULL, filename); + HMODULE lib = LoadLibraryW(wfilename); + talloc_free(wfilename); + mp_dl_result.errcode = GetLastError(); + return (void *)lib; +} + +void *mp_dlsym(void *handle, const char *symbol) +{ + FARPROC addr = GetProcAddress((HMODULE)handle, symbol); + mp_dl_result.errcode = GetLastError(); + return (void *)addr; +} + +char *mp_dlerror(void) +{ + static pthread_once_t once_init_dlerror = PTHREAD_ONCE_INIT; + pthread_once(&once_init_dlerror, mp_dl_init); + mp_dl_free(); + + if (mp_dl_result.errcode == 0) + return NULL; + + // convert error code to a string message + LPWSTR werrstring = NULL; + FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + mp_dl_result.errcode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), + (LPWSTR) &werrstring, + 0, + NULL); + mp_dl_result.errcode = 0; + + if (werrstring) { + mp_dl_result.errstring = mp_to_utf8(NULL, werrstring); + LocalFree(werrstring); + } + + return mp_dl_result.errstring == NULL + ? "unknown error" + : mp_dl_result.errstring; +} + #if HAVE_UWP void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { diff --git a/osdep/io.h b/osdep/io.h index 905558c284..6f398c7f95 100644 --- a/osdep/io.h +++ b/osdep/io.h @@ -113,6 +113,9 @@ char *mp_getenv(const char *name); char ***mp_penviron(void); off_t mp_lseek(int fd, off_t offset, int whence); +void *mp_dlopen(const char *filename, int flag); +void *mp_dlsym(void *handle, const char *symbol); +char *mp_dlerror(void); // mp_stat types. MSVCRT's dev_t and ino_t are way too short to be unique. typedef uint64_t mp_dev_t_; @@ -172,6 +175,12 @@ void mp_globfree(mp_glob_t *pglob); #undef lseek #define lseek(...) mp_lseek(__VA_ARGS__) +#define RTLD_NOW 0 +#define RTLD_LOCAL 0 +#define dlopen(fn,fg) mp_dlopen((fn), (fg)) +#define dlsym(h,s) mp_dlsym((h), (s)) +#define dlerror mp_dlerror + // Affects both "stat()" and "struct stat". #undef stat #define stat mp_stat