blob: 5f76cc5e28d1223ca04ba9a2d20df026545d766c [file] [log] [blame]
// Windows/DLL.cpp
#include "StdAfx.h"
#ifdef __APPLE_CC__
#include <mach-o/dyld.h>
#elif ENV_BEOS
#include <kernel/image.h>
#include <Path.h>
#else
#define UINT64 DLL_UINT64 // HP-UX , dlfcn.h defines UINT64 but p7zip also defines UINT64
#include <dlfcn.h> // dlopen ...
#undef UINT64
#endif
#include "DLL.h"
#include "Defs.h"
#ifdef _UNICODE
#include "../Common/StringConvert.h"
#endif
#define NEED_NAME_WINDOWS_TO_UNIX
#include "myPrivate.h"
// #define TRACEN(u) u;
#define TRACEN(u) /* */
namespace NWindows {
namespace NDLL {
CLibrary::~CLibrary()
{
Free();
}
bool CLibrary::Free()
{
TRACEN((printf("CLibrary::Free(%p)\n",(void *)_module)))
if (_module == 0)
return true;
#ifdef __APPLE_CC__
int ret = NSUnLinkModule ((NSModule)_module, 0);
#elif ENV_BEOS
int ret = unload_add_on((image_id)_module);
#else
int ret = dlclose(_module);
#endif
TRACEN((printf("CLibrary::Free dlclose(%p)=%d\n",(void *)_module,ret)))
if (ret != 0) return false;
_module = 0;
return true;
}
static FARPROC local_GetProcAddress(HMODULE module,LPCSTR lpProcName)
{
void *ptr = 0;
TRACEN((printf("local_GetProcAddress(%p,%s)\n",(void *)module,lpProcName)))
if (module) {
#ifdef __APPLE_CC__
char name[MAX_PATHNAME_LEN];
snprintf(name,sizeof(name),"_%s",lpProcName);
name[sizeof(name)-1] = 0;
TRACEN((printf("NSLookupSymbolInModule(%p,%s)\n",(void *)module,name)))
NSSymbol sym;
sym = NSLookupSymbolInModule((NSModule)module, name);
if (sym) {
ptr = NSAddressOfSymbol(sym);
} else {
ptr = 0;
}
#elif ENV_BEOS
if (get_image_symbol((image_id)module, lpProcName, B_SYMBOL_TYPE_TEXT, &ptr) != B_OK)
ptr = 0;
#else
ptr = dlsym (module, lpProcName);
#endif
TRACEN((printf("CLibrary::GetProc : dlsym(%p,%s)=%p\n",(void *)module,lpProcName,ptr)))
}
return (FARPROC)ptr;
}
FARPROC CLibrary::GetProc(LPCSTR lpProcName) const
{
TRACEN((printf("CLibrary::GetProc(%p,%s)\n",(void *)_module,lpProcName)))
return local_GetProcAddress(_module,lpProcName);
}
bool CLibrary::LoadOperations(HMODULE newModule)
{
if (newModule == NULL)
return false;
if(!Free())
return false;
_module = newModule;
return true;
}
bool CLibrary::Load(LPCTSTR lpLibFileName)
{
void *handler = 0;
char name[MAX_PATHNAME_LEN+1];
#ifdef _UNICODE
AString name2 = UnicodeStringToMultiByte(lpLibFileName);
strcpy(name,nameWindowToUnix((const char *)name2));
#else
strcpy(name,nameWindowToUnix(lpLibFileName));
#endif
// replace ".dll" with ".so"
size_t len = strlen(name);
if ((len >=4) && (strcmp(name+len-4,".dll") == 0)) {
strcpy(name+len-4,".so");
}
TRACEN((printf("CLibrary::Load(%ls) => %s\n",lpLibFileName,name)))
#ifdef __APPLE_CC__
NSObjectFileImage image;
NSObjectFileImageReturnCode nsret;
nsret = NSCreateObjectFileImageFromFile (name, &image);
if (nsret == NSObjectFileImageSuccess) {
TRACEN((printf("NSCreateObjectFileImageFromFile(%s) : OK\n",name)))
handler = (HMODULE)NSLinkModule(image,name,NSLINKMODULE_OPTION_RETURN_ON_ERROR
| NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW);
} else {
TRACEN((printf("NSCreateObjectFileImageFromFile(%s) : ERROR\n",name)))
}
#elif ENV_BEOS
// normalize path (remove things like "./", "..", etc..), otherwise it won't work
BPath p(name, NULL, true);
status_t err = B_OK;
image_id image = load_add_on(p.Path());
TRACEN((printf("load_add_on(%s)=%d\n",p.Path(),(int)image)))
if (image < 0) {
err = (image_id)handler;
handler = 0;
} else {
err = 0;
handler = (HMODULE)image;
}
#else
int options_dlopen = 0;
#ifdef RTLD_LOCAL
options_dlopen |= RTLD_LOCAL;
#endif
#ifdef RTLD_NOW
options_dlopen |= RTLD_NOW;
#endif
#ifdef RTLD_GROUP
#if ! (defined(hpux) || defined(__hpux))
options_dlopen |= RTLD_GROUP; // mainly for solaris but not for HPUX
#endif
#endif
TRACEN((printf("CLibrary::Load - dlopen(%s,0x%d)\n",name,options_dlopen)))
handler = dlopen(name,options_dlopen);
#endif // __APPLE_CC__
TRACEN((printf("CLibrary::Load(%s) => %p\n",name,handler)))
if (handler) {
// Call DllMain() like in Windows : useless now
// Propagate the value of global_use_utf16_conversion into the plugins
int *tmp = (int *)local_GetProcAddress(handler,"global_use_utf16_conversion");
if (tmp) *tmp = global_use_utf16_conversion;
tmp = (int *)local_GetProcAddress(handler,"global_use_lstat");
if (tmp) *tmp = global_use_lstat;
// test construtors calls
void (*fctTest)(void) = (void (*)(void))local_GetProcAddress(handler,"sync_TestConstructor");
if (fctTest) fctTest();
} else {
#ifdef __APPLE_CC__
NSLinkEditErrors c;
int num_err;
const char *file,*err;
NSLinkEditError(&c,&num_err,&file,&err);
printf("Can't load '%ls' (%s)\n", lpLibFileName,err);
#elif ENV_BEOS
printf("Can't load '%ls' (%s)\n", lpLibFileName,strerror(err));
#else
printf("Can't load '%ls' (%s)\n", lpLibFileName,dlerror());
#endif
}
return LoadOperations(handler);
}
}}