efl/src/lib/evil/dlfcn.c

274 lines
5.4 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#if defined(__MINGW32CE__) || defined(_MSC_VER)
# include <limits.h>
#endif /* __MINGW32CE__ || _MSC_VER */
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#ifdef _WIN32_WCE
# include <tlhelp32.h> /* CreateToolhelp32Snapshot */
#else
# include <psapi.h> /* EnumProcessModules(Ex) */
#endif
#include "Evil.h"
#include "evil_private.h"
#include "dlfcn.h"
static char *dl_err = NULL;
static int dl_err_viewed = 0;
static void
get_last_error(char *desc)
{
char *str;
size_t l1;
size_t l2;
str = evil_last_error_get();
l1 = strlen(desc);
l2 = strlen(str);
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, str, l2);
dl_err[l1 + l2] = '\0';
}
free(str);
dl_err_viewed = 0;
}
void *
dlopen(const char* path, int mode EVIL_UNUSED)
{
HMODULE module = NULL;
if (!path)
{
module = GetModuleHandle(NULL);
if (!module)
get_last_error("GetModuleHandle returned: ");
}
else
{
char *new_path;
size_t l;
unsigned 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];
}
#ifdef UNICODE
{
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 /* ! UNICODE */
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 = NULL;
LPCTSTR new_symbol;
if (!symbol || !*symbol) return NULL;
#ifdef UNICODE
new_symbol = evil_char_to_wchar(symbol);
#else
new_symbol = symbol;
#endif /* UNICODE */
if (handle == RTLD_DEFAULT)
{
#ifdef _WIN32_WCE
HANDLE snapshot;
MODULEENTRY32 module;
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS |
TH32CS_SNAPMODULE |
TH32CS_GETALLMODS,
0);
if (!snapshot)
return NULL;
module.dwSize = sizeof(module);
if (Module32First(snapshot, &module))
do {
fp = GetProcAddress(module.hModule, new_symbol);
if (fp) break;
} while (Module32Next(snapshot, &module));
CloseToolhelp32Snapshot(snapshot);
#else
HMODULE modules[1024];
DWORD needed;
DWORD i;
/* TODO: use EnumProcessModulesEx() on Windows >= Vista */
if (!EnumProcessModules(GetCurrentProcess(),
modules, sizeof(modules), &needed))
return NULL;
for (i = 0; i < (needed / sizeof(HMODULE)); i++)
{
fp = GetProcAddress(modules[i], new_symbol);
if (fp) break;
}
#endif
}
else
fp = GetProcAddress(handle, new_symbol);
#ifdef UNICODE
free((void *)new_symbol);
#endif /* UNICODE */
if (!fp)
get_last_error("GetProcAddress returned: ");
return fp;
}
int
dladdr (const void *addr EVIL_UNUSED, Dl_info *info)
{
TCHAR tpath[PATH_MAX];
MEMORY_BASIC_INFORMATION mbi;
char *path;
char *tmp;
size_t length;
int ret = 0;
if (!info)
return 0;
#ifdef _WIN32_WINNT
length = VirtualQuery(addr, &mbi, sizeof(mbi));
if (!length)
return 0;
if (mbi.State != MEM_COMMIT)
return 0;
if (!mbi.AllocationBase)
return 0;
ret = GetModuleFileName((HMODULE)mbi.AllocationBase, (LPTSTR)&tpath, PATH_MAX);
if (!ret)
return 0;
#else
ret = GetModuleFileName(NULL, (LPTSTR)&tpath, PATH_MAX);
if (!ret)
return 0;
#endif
#ifdef UNICODE
path = evil_wchar_to_char(tpath);
#else
path = tpath;
#endif /* ! UNICODE */
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;
#ifdef UNICODE
free (path);
#endif /* ! UNICODE */
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;
}
}