Added dlerror() and fixed issue with dlopen() handling UTF-8 filenames
dlerror() is supposed to return a char *, but currently returns a DWORD. Reimplement it using the Win32 FormatMessage function. Correctly handle UTF-8 filenames in the Win32 implementation of dlopen()
This commit is contained in:
parent
959cbe3265
commit
3449eb2152
|
@ -2,10 +2,10 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#define RTLD_NOW 0
|
#define RTLD_NOW 0
|
||||||
|
|
||||||
#define dlerror() GetLastError()
|
|
||||||
|
|
||||||
HMODULE dlopen(const char *filename, int flags);
|
HMODULE dlopen(const char *filename, int flags);
|
||||||
|
|
||||||
int dlclose(HMODULE handle);
|
int dlclose(HMODULE handle);
|
||||||
|
|
||||||
FARPROC dlsym(HMODULE handle, const char *symbol);
|
FARPROC dlsym(HMODULE handle, const char *symbol);
|
||||||
|
|
||||||
|
char * dlerror();
|
||||||
|
|
|
@ -221,10 +221,23 @@ explicit_bzero(void *b, size_t len)
|
||||||
SecureZeroMemory(b, len);
|
SecureZeroMemory(b, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD last_dlerror = ERROR_SUCCESS;
|
||||||
|
|
||||||
HMODULE
|
HMODULE
|
||||||
dlopen(const char *filename, int flags)
|
dlopen(const char *filename, int flags)
|
||||||
{
|
{
|
||||||
return LoadLibraryA(filename);
|
wchar_t *wfilename = utf8_to_utf16(filename);
|
||||||
|
if (wfilename == NULL) {
|
||||||
|
last_dlerror = ERROR_INVALID_PARAMETER;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE module = LoadLibraryW(wfilename);
|
||||||
|
if (module == NULL)
|
||||||
|
last_dlerror = GetLastError();
|
||||||
|
|
||||||
|
free(wfilename);
|
||||||
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -237,9 +250,48 @@ dlclose(HMODULE handle)
|
||||||
FARPROC
|
FARPROC
|
||||||
dlsym(HMODULE handle, const char *symbol)
|
dlsym(HMODULE handle, const char *symbol)
|
||||||
{
|
{
|
||||||
return GetProcAddress(handle, symbol);
|
void *ptr = GetProcAddress(handle, symbol);
|
||||||
|
if (ptr == NULL)
|
||||||
|
last_dlerror = GetLastError();
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
dlerror()
|
||||||
|
{
|
||||||
|
static char *message = NULL;
|
||||||
|
if (message != NULL) {
|
||||||
|
free(message);
|
||||||
|
message = NULL;
|
||||||
|
}
|
||||||
|
if (last_dlerror == ERROR_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wchar_t *wmessage = NULL;
|
||||||
|
DWORD length = FormatMessageW(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, last_dlerror, 0, (wchar_t *) &wmessage, 0, NULL);
|
||||||
|
last_dlerror = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (wmessage[length - 1] == L'\n')
|
||||||
|
wmessage[length - 1] = L'\0';
|
||||||
|
if (length > 1 && wmessage[length - 2] == L'\r')
|
||||||
|
wmessage[length - 2] = L'\0';
|
||||||
|
|
||||||
|
message = utf16_to_utf8(wmessage);
|
||||||
|
LocalFree(wmessage);
|
||||||
|
|
||||||
|
if (message == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return "Failed to format error message";
|
||||||
|
}
|
||||||
|
|
||||||
/*fopen on Windows to mimic https://linux.die.net/man/3/fopen
|
/*fopen on Windows to mimic https://linux.die.net/man/3/fopen
|
||||||
* only r, w, a are supported for now
|
* only r, w, a are supported for now
|
||||||
|
|
Loading…
Reference in New Issue