efl/legacy/evil/src/lib/dlfcn/dlfcn.c

220 lines
4.3 KiB
C
Raw Normal View History

#include <stdlib.h>
#if defined(__CEGCC__) || defined(__MINGW32CE__)
# include <limits.h>
#endif /* __MINGW32CE__ */
#include "../Evil.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include "dlfcn.h"
#if HAVE___ATTRIBUTE__
# define __UNUSED__ __attribute__((unused))
#else
# define __UNUSED__
#endif /* HAVE___ATTRIBUTE__ */
static char *dl_err = NULL;
static int dl_err_viewed = 0;
static void
get_last_error(char *desc)
{
TCHAR *str;
char *str2;
int l1;
int l2;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&str, 0, NULL);
#if defined(__CEGCC__) || defined(__MINGW32CE__)
str2 = evil_wchar_to_char(str);
LocalFree(str);
#else
str2 = str;
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
l1 = strlen(desc);
l2 = strlen(str2);
if (dl_err)
free(dl_err);
dl_err = (char *)malloc(sizeof(char) * (l1 + l2 + 1));
if (!dl_err)
dl_err = strdup("not enough resource");
else
{
memcpy(dl_err, desc, l1);
memcpy(dl_err + l1, str2, l2);
dl_err[l1 + l2] = '\0';
}
LocalFree(str2);
dl_err_viewed = 0;
}
void *
dlopen(const char* path, int mode __UNUSED__)
{
HMODULE module = NULL;
if (!path)
{
module = GetModuleHandle(NULL);
if (!module)
get_last_error("GetModuleHandle returned: ");
}
else
{
char *new_path;
int l;
int i;
/* according to MSDN, we must change the slash to backslash */
l = strlen(path);
new_path = (char *)malloc(sizeof(char) * (l + 1));
if (!new_path)
{
if (dl_err)
free(dl_err);
dl_err = strdup("not enough resource");
dl_err_viewed = 0;
return NULL;
}
for (i = 0; i <= l; i++)
{
if (path[i] == '/')
new_path[i] = '\\';
else
new_path[i] = path[i];
}
#if defined(__CEGCC__) || defined(__MINGW32CE__)
{
wchar_t *wpath;
wpath = evil_char_to_wchar(new_path);
module = LoadLibrary(wpath);
free(wpath);
}
#else
module = LoadLibraryEx(new_path, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
if (!module)
get_last_error("LoadLibraryEx returned: ");
free(new_path);
}
return module;
}
int
dlclose(void* handle)
{
if (FreeLibrary(handle))
return 0;
else
{
get_last_error("FreeLibrary returned: ");
return -1;
}
}
void *
dlsym(void *handle, const char *symbol)
{
FARPROC fp;
#if defined(__CEGCC__) || defined(__MINGW32CE__)
{
wchar_t *wsymbol;
wsymbol = evil_char_to_wchar(symbol);
fp = GetProcAddress(handle, wsymbol);
free(wsymbol);
}
#else
fp = GetProcAddress(handle, symbol);
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
if (!fp)
get_last_error("GetProcAddress returned: ");
return fp;
}
int
dladdr (void *addr __UNUSED__, Dl_info *info)
{
TCHAR tpath[PATH_MAX];
char *path;
char *tmp;
int length;
int ret = 0;
if (!info)
return 0;
ret = GetModuleFileName(GetModuleHandle(NULL), (LPTSTR)&tpath, PATH_MAX);
if (!ret)
return 0;
#if defined(__CEGCC__) || defined(__MINGW32CE__)
path = evil_wchar_to_char(tpath);
#else
path = tpath;
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
length = strlen (path);
if (length >= PATH_MAX)
{
length = PATH_MAX - 1;
path[PATH_MAX - 1] = '\0';
}
/* replace '\' by '/' */
tmp = path;
while (*tmp)
{
if (*tmp == '\\') *tmp = '/';
tmp++;
}
memcpy (info->dli_fname, path, length + 1);
info->dli_fbase = NULL;
info->dli_sname = NULL;
info->dli_saddr = NULL;
#if defined(__CEGCC__) || defined(__MINGW32CE__)
free (path);
#endif /* __CEGCC__ || __MINGW32CE__ */
return 1;
}
char *
dlerror (void)
{
if (!dl_err_viewed)
{
dl_err_viewed = 1;
return dl_err;
}
else
{
if (dl_err)
free(dl_err);
return NULL;
}
}