diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/misc/mptLibrary.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/misc/mptLibrary.cpp')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/misc/mptLibrary.cpp | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/misc/mptLibrary.cpp b/Src/external_dependencies/openmpt-trunk/misc/mptLibrary.cpp new file mode 100644 index 00000000..e924a90b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/misc/mptLibrary.cpp @@ -0,0 +1,553 @@ +/* + * mptLibrary.cpp + * -------------- + * Purpose: Shared library handling. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" +#include "mptLibrary.h" + +#include "mpt/osinfo/windows_version.hpp" + +#if MPT_OS_WINDOWS +#include <windows.h> +#elif MPT_OS_ANDROID +#include <dlfcn.h> +#elif defined(MPT_WITH_LTDL) +#include <ltdl.h> +#elif defined(MPT_WITH_DL) +#include <dlfcn.h> +#endif + + +OPENMPT_NAMESPACE_BEGIN + + +namespace mpt +{ + + +#if MPT_OS_WINDOWS + + +// KB2533623 / Win8 +#ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS +#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 +#endif +#ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR +#define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200 +#endif +#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32 +#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 +#endif +#ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR +#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100 +#endif + + +class LibraryHandle +{ + +private: + + HMODULE hModule; + +public: + + LibraryHandle(const mpt::LibraryPath &path) + : hModule(NULL) + { + +#if MPT_OS_WINDOWS_WINRT + +#if (_WIN32_WINNT < 0x0602) + (void)path; + hModule = NULL; // unsupported +#else + switch(path.GetSearchPath()) + { + case mpt::LibrarySearchPath::Default: + hModule = LoadPackagedLibrary(path.GetFileName().AsNative().c_str(), 0); + break; + case mpt::LibrarySearchPath::Application: + hModule = LoadPackagedLibrary(path.GetFileName().AsNative().c_str(), 0); + break; + case mpt::LibrarySearchPath::System: + hModule = NULL; // Only application packaged libraries can be loaded dynamically in WinRT + break; + case mpt::LibrarySearchPath::FullPath: + hModule = NULL; // Absolute path is not supported in WinRT + break; + case mpt::LibrarySearchPath::Invalid: + MPT_ASSERT_NOTREACHED(); + break; + } +#endif + +#else // !MPT_OS_WINDOWS_WINRT + +#if (_WIN32_WINNT >= 0x0602) + bool hasKB2533623 = true; +#else + // Check for KB2533623: + bool hasKB2533623 = false; + mpt::osinfo::windows::Version WindowsVersion = mpt::osinfo::windows::Version::Current(); + if(WindowsVersion.IsAtLeast(mpt::osinfo::windows::Version::Win8)) + { + hasKB2533623 = true; + } else if(WindowsVersion.IsAtLeast(mpt::osinfo::windows::Version::WinVista)) + { + HMODULE hKernel32DLL = LoadLibrary(TEXT("kernel32.dll")); + if(hKernel32DLL) + { + if(::GetProcAddress(hKernel32DLL, "SetDefaultDllDirectories") != nullptr) + { + hasKB2533623 = true; + } + FreeLibrary(hKernel32DLL); + hKernel32DLL = NULL; + } + } +#endif + + MPT_MAYBE_CONSTANT_IF(hasKB2533623) + { + switch(path.GetSearchPath()) + { + case mpt::LibrarySearchPath::Default: + hModule = LoadLibraryEx(path.GetFileName().AsNative().c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + break; + case mpt::LibrarySearchPath::System: + hModule = LoadLibraryEx(path.GetFileName().AsNative().c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + break; +#if defined(MODPLUG_TRACKER) + // Using restricted search paths applies to potential DLL dependencies + // recursively. + // This fails loading for e.g. Codec or Plugin DLLs in application + // directory if they depend on the MSVC C or C++ runtime (which is + // located in the system directory). + // Just rely on the default search path here. + case mpt::LibrarySearchPath::Application: + { + const mpt::PathString dllPath = mpt::GetExecutablePath(); + if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory()) + { + hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str()); + } + } + break; + case mpt::LibrarySearchPath::FullPath: + hModule = LoadLibrary(path.GetFileName().AsNative().c_str()); + break; +#else + // For libopenmpt, do the safe thing. + case mpt::LibrarySearchPath::Application: + hModule = LoadLibraryEx(path.GetFileName().AsNative().c_str(), NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR); + break; + case mpt::LibrarySearchPath::FullPath: + hModule = LoadLibraryEx(path.GetFileName().AsNative().c_str(), NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); + break; +#endif + case mpt::LibrarySearchPath::Invalid: + MPT_ASSERT_NOTREACHED(); + break; + } + } else + { + switch(path.GetSearchPath()) + { + case mpt::LibrarySearchPath::Default: + hModule = LoadLibrary(path.GetFileName().AsNative().c_str()); + break; + case mpt::LibrarySearchPath::Application: + { + const mpt::PathString dllPath = mpt::GetExecutablePath(); + if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory()) + { + hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str()); + } + } + break; + case mpt::LibrarySearchPath::System: + { + const mpt::PathString dllPath = mpt::GetSystemPath(); + if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory()) + { + hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str()); + } + } + break; + case mpt::LibrarySearchPath::FullPath: + hModule = LoadLibrary(path.GetFileName().AsNative().c_str()); + break; + case mpt::LibrarySearchPath::Invalid: + MPT_ASSERT_NOTREACHED(); + break; + } + } + +#endif // MPT_OS_WINDOWS_WINRT + + } + + LibraryHandle(const LibraryHandle &) = delete; + + LibraryHandle & operator=(const LibraryHandle &) = delete; + + ~LibraryHandle() + { + if(IsValid()) + { + FreeLibrary(hModule); + } + hModule = NULL; + } + +public: + + bool IsValid() const + { + return (hModule != NULL); + } + + FuncPtr GetProcAddress(const std::string &symbol) const + { + if(!IsValid()) + { + return nullptr; + } + return reinterpret_cast<FuncPtr>(::GetProcAddress(hModule, symbol.c_str())); + } + +}; + + +#elif MPT_OS_ANDROID + + +// Fake implementation. +// Load shared objects from the JAVA side of things. +class LibraryHandle +{ + +public: + + LibraryHandle(const mpt::LibraryPath &path) + { + return; + } + + LibraryHandle(const LibraryHandle &) = delete; + + LibraryHandle & operator=(const LibraryHandle &) = delete; + + ~LibraryHandle() + { + return; + } + +public: + + bool IsValid() const + { + return true; + } + + FuncPtr GetProcAddress(const std::string &symbol) const + { + if(!IsValid()) + { + return nullptr; + } + return reinterpret_cast<FuncPtr>(dlsym(0, symbol.c_str())); + } + +}; + + + +#elif defined(MPT_WITH_LTDL) + + +class LibraryHandle +{ + +private: + + bool inited; + lt_dlhandle handle; + +public: + + LibraryHandle(const mpt::LibraryPath &path) + : inited(false) + , handle(0) + { + if(lt_dlinit() != 0) + { + return; + } + inited = true; + handle = lt_dlopenext(path.GetFileName().AsNative().c_str()); + } + + LibraryHandle(const LibraryHandle &) = delete; + + LibraryHandle & operator=(const LibraryHandle &) = delete; + + ~LibraryHandle() + { + if(IsValid()) + { + lt_dlclose(handle); + } + handle = 0; + if(inited) + { + lt_dlexit(); + inited = false; + } + } + +public: + + bool IsValid() const + { + return handle != 0; + } + + FuncPtr GetProcAddress(const std::string &symbol) const + { + if(!IsValid()) + { + return nullptr; + } + return reinterpret_cast<FuncPtr>(lt_dlsym(handle, symbol.c_str())); + } + +}; + + +#elif defined(MPT_WITH_DL) + + +class LibraryHandle +{ + +private: + + void* handle; + +public: + + LibraryHandle(const mpt::LibraryPath &path) + : handle(NULL) + { + handle = dlopen(path.GetFileName().AsNative().c_str(), RTLD_NOW); + } + + LibraryHandle(const LibraryHandle &) = delete; + + LibraryHandle & operator=(const LibraryHandle &) = delete; + + ~LibraryHandle() + { + if(IsValid()) + { + dlclose(handle); + } + handle = NULL; + } + +public: + + bool IsValid() const + { + return handle != NULL; + } + + FuncPtr GetProcAddress(const std::string &symbol) const + { + if(!IsValid()) + { + return NULL; + } + return reinterpret_cast<FuncPtr>(dlsym(handle, symbol.c_str())); + } + +}; + + +#else // MPT_OS + + +// dummy implementation + +class LibraryHandle +{ +public: + + LibraryHandle(const mpt::LibraryPath &path) + { + MPT_UNREFERENCED_PARAMETER(path); + return; + } + + LibraryHandle(const LibraryHandle &) = delete; + + LibraryHandle & operator=(const LibraryHandle &) = delete; + + ~LibraryHandle() + { + return; + } + +public: + + bool IsValid() const + { + return false; + } + + FuncPtr GetProcAddress(const std::string &symbol) const + { + MPT_UNREFERENCED_PARAMETER(symbol); + if(!IsValid()) + { + return nullptr; + } + return nullptr; + } + +}; + + +#endif // MPT_OS + + +LibraryPath::LibraryPath(mpt::LibrarySearchPath searchPath, const mpt::PathString &fileName) + : searchPath(searchPath) + , fileName(fileName) +{ + return; +} + + +mpt::LibrarySearchPath LibraryPath::GetSearchPath() const +{ + return searchPath; +} + + +mpt::PathString LibraryPath::GetFileName() const +{ + return fileName; +} + + +mpt::PathString LibraryPath::GetDefaultPrefix() +{ + #if MPT_OS_WINDOWS + return P_(""); + #elif MPT_OS_ANDROID + return P_("lib"); + #elif defined(MPT_WITH_LTDL) + return P_("lib"); + #elif defined(MPT_WITH_DL) + return P_("lib"); + #else + return P_("lib"); + #endif +} + + +mpt::PathString LibraryPath::GetDefaultSuffix() +{ + #if MPT_OS_WINDOWS + return P_(".dll"); + #elif MPT_OS_ANDROID + return P_(".so"); + #elif defined(MPT_WITH_LTDL) + return P_(""); // handled by libltdl + #elif defined(MPT_WITH_DL) + return P_(".so"); + #else + return mpt::PathString(); + #endif +} + + +LibraryPath LibraryPath::App(const mpt::PathString &basename) +{ + return LibraryPath(mpt::LibrarySearchPath::Application, GetDefaultPrefix() + basename + GetDefaultSuffix()); +} + + +LibraryPath LibraryPath::AppFullName(const mpt::PathString &fullname) +{ + return LibraryPath(mpt::LibrarySearchPath::Application, fullname + GetDefaultSuffix()); +} + + +LibraryPath LibraryPath::System(const mpt::PathString &basename) +{ + return LibraryPath(mpt::LibrarySearchPath::System, GetDefaultPrefix() + basename + GetDefaultSuffix()); +} + + +LibraryPath LibraryPath::FullPath(const mpt::PathString &path) +{ + return LibraryPath(mpt::LibrarySearchPath::FullPath, path); +} + + +Library::Library() +{ + return; +} + + +Library::Library(const mpt::LibraryPath &path) +{ + if(path.GetSearchPath() == mpt::LibrarySearchPath::Invalid) + { + return; + } + if(path.GetFileName().empty()) + { + return; + } + m_Handle = std::make_shared<LibraryHandle>(path); +} + + +void Library::Unload() +{ + *this = mpt::Library(); +} + + +bool Library::IsValid() const +{ + return m_Handle && m_Handle->IsValid(); +} + + +FuncPtr Library::GetProcAddress(const std::string &symbol) const +{ + if(!IsValid()) + { + return nullptr; + } + return m_Handle->GetProcAddress(symbol); +} + + +} // namespace mpt + + +OPENMPT_NAMESPACE_END |