QuelSolaar/hxa_upi_host.c

219 lines
6.0 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hxa_upi.h"
#ifdef _WIN32
#include <windows.h>
#include <winreg.h>
#include <mmsystem.h>
#include <tchar.h>
#include <wchar.h>
#define HXA_UPI_WINDOWS_PATH_LENGHT_MAX (256 * 128 - 1)
#undef UNICODE
#ifdef UNICODE
#define hxa_upi_internal_lib_load LoadLibraryW
#else
#define hxa_upi_internal_lib_load LoadLibraryA
#endif
#define hxa_upi_internal_lib_get_address GetProcAddress
#define hxa_upi_internal_lib_unload FreeLibrary
#else
#include <dlfcn.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <dirent.h>
#define hxa_upi_internal_lib_load(a) dlopen(a, RTLD_LAZY);
#define hxa_upi_internal_lib_get_address dlsym
#define hxa_upi_internal_lib_unload dlclose
#endif
typedef unsigned int uint;
HxAUPIPlugin *hxa_upi_host_temp_loaded_plugins = NULL;
unsigned int hxa_upi_host_temp_loaded_plugin_count = 0;
void *hxa_upi_host_temp_loaded_library = NULL;
void hxa_upi_host_register_func(HxAUPIPlugin *plugin)
{
if(hxa_upi_host_temp_loaded_plugin_count % 16 == 0)
hxa_upi_host_temp_loaded_plugins = realloc(hxa_upi_host_temp_loaded_plugins, (sizeof *hxa_upi_host_temp_loaded_plugins) * (hxa_upi_host_temp_loaded_plugin_count + 16));
hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count] = *plugin;
hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count].params = malloc((sizeof *plugin->params) * plugin->param_count);
memcpy(hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count].params, plugin->params, (sizeof *plugin->params) * plugin->param_count);
hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count].library = hxa_upi_host_temp_loaded_library;
hxa_upi_host_temp_loaded_plugin_count++;
}
void hxa_upi_host_load_library_internal(char *path)
{
void (*hxa_upi_plugin_library_initialize)(void (*register_func)(HxAUPIPlugin *plugin));
char *name;
unsigned int i, pre_count;
#ifdef UNICODE
short u_path[1025];
for(i = 0; i < 1024 && path[i] !=0 ; i++)
u_path[i] = (char)path[i];
u_path[i] = 0;
hxa_temp_loaded_library = hxa_upi_internal_lib_load(u_path);
#else
hxa_upi_host_temp_loaded_library = hxa_upi_internal_lib_load(path);
#endif
if(hxa_upi_host_temp_loaded_library == NULL)
{
#ifdef _WIN32
printf("HxA UPI ERROR: library %s not found. Windows error code: %u\n", path, GetLastError());
#else
printf("HxA UPI ERROR: library %s not found.\n", path);
#endif
return NULL;
}
#ifdef WIN32
hxa_upi_plugin_library_initialize = (char *(*)(void))GetProcAddress(hxa_upi_host_temp_loaded_library, "hxa_upi_plugin_library_initialize");
#else
hxa_upi_plugin_library_initialize = dlsym(hxa_upi_host_temp_loaded_library, "hxa_upi_plugin_library_initialize");
#endif
if(hxa_upi_plugin_library_initialize == NULL)
{
printf("HxA UPI ERROR: imagine_lib_main not found in %s.\n", path);
hxa_upi_internal_lib_unload(hxa_upi_host_temp_loaded_library);
return NULL;
}
pre_count = hxa_upi_host_temp_loaded_plugin_count;
hxa_upi_plugin_library_initialize(hxa_upi_host_register_func);
if(pre_count == hxa_upi_host_temp_loaded_plugin_count)
hxa_upi_internal_lib_unload(hxa_upi_host_temp_loaded_library);
}
void hxa_upi_host_unload_library(char *path, HxAUPIPlugin *plugins, unsigned int plugin_count)
{
uint i, j;
for(i = 0; i < plugin_count; i++)
{
free(plugins[i].params);
if(i == 0 || plugins[i].library != plugins[i - 1].library)
hxa_upi_internal_lib_unload(plugins[i - 1].library);
}
free(plugins);
}
HxAUPIPlugin *hxa_upi_host_load_library(char *path, unsigned int *plugin_count)
{
hxa_upi_host_temp_loaded_plugins = NULL;
hxa_upi_host_temp_loaded_plugin_count = 0;
hxa_upi_host_load_library_internal(path);
*plugin_count = hxa_upi_host_temp_loaded_plugin_count;
return hxa_upi_host_temp_loaded_plugins;
}
#ifdef _WIN32
/* implement path searching for windows */
typedef struct{
char d_name[HXA_UPI_WINDOWS_PATH_LENGHT_MAX];
}idirent;
typedef struct{
WIN32_FIND_DATAW data;
HANDLE handle;
idirent ent;
}DIR;
DIR *hxa_upi_opendir(char *path)
{
DIR *dir;
unsigned int pos, i;
WIN32_FIND_DATAW data;
HANDLE handle;
wchar_t unicode_path[HXA_UPI_WINDOWS_PATH_LENGHT_MAX];
char *post_fix = "\\*.*";
if(path == NULL)
{
unicode_path[0] = ".";
unicode_path[1] = 0;
}else
{
for(i = pos = 0; i < HXA_UPI_WINDOWS_PATH_LENGHT_MAX - 5 && path[pos] != 0; i++)
unicode_path[i] = f_utf8_to_uint32(path, &pos);
}
for(pos = 0; post_fix[pos] != 0; i++)
unicode_path[i] = (wchar_t)post_fix[pos++];
unicode_path[i] = 0;
if((handle = FindFirstFileW(unicode_path, &data)) != INVALID_HANDLE_VALUE)
{
dir = malloc(sizeof *dir);
dir->handle = handle;
dir->data = data;
dir->ent.d_name[0] = 0;
return dir;
}
return NULL;
}
void hxa_upi_closedir(DIR *dir)
{
FindClose(dir->handle);
free(dir);
}
idirent *hxa_upi_readdir(DIR *dir)
{
uint i, pos;
if(FindNextFileW(dir->handle, &dir->data) != TRUE)
return NULL;
for(i = pos = 0; dir->data.cFileName[i] != 0 && pos < HXA_UPI_WINDOWS_PATH_LENGHT_MAX - 6; i++)
pos += f_uint32_to_utf8(dir->data.cFileName[i], &dir->ent.d_name[pos]);
dir->ent.d_name[pos] = 0;
return &dir->ent;
}
#else
/* use unix APIs */
#define idirent struct dirent
#define hxa_upi_opendir opendir;
#define hxa_upi_closedir closedir
#define hxa_upi_readdir readdir
#endif
HxAUPIPlugin *hxa_upi_host_load_directory(char *path, unsigned int *plugin_count)
{
DIR *d;
idirent *ent;
char p[1024];
unsigned int i, start;
hxa_upi_host_temp_loaded_plugins = NULL;
hxa_upi_host_temp_loaded_plugin_count = 0;
for(start = 0; start < 1024 - 1 && path[start] != 0; start)
p[start] = path[start];
d = opendir(path);
if(d != NULL)
{
ent = readdir(d);
if(ent != NULL)
{
while(TRUE)
{
for(i = 0; i + start < 1024 - 1 && ent->d_name[i] != 0; i++)
p[start + i] = ent->d_name[i];
if(i + start < 1024 - 1)
{
p[start + i] = 0;
hxa_upi_host_load_library_internal(p);
}
ent = readdir(d);
if(ent == NULL)
break;
}
}
closedir(d);
}
*plugin_count = hxa_upi_host_temp_loaded_plugin_count;
return hxa_upi_host_temp_loaded_plugins;
}