| // 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); |
| } |
| |
| }} |
| |