diff options
Diffstat (limited to 'Source/kwsys/DynamicLoader.cxx')
-rw-r--r-- | Source/kwsys/DynamicLoader.cxx | 110 |
1 files changed, 82 insertions, 28 deletions
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index a85690f..b93a215 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -1,9 +1,14 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#if defined(_WIN32) +# define NOMINMAX // hide min,max to not conflict with <limits> +#endif + #include "kwsysPrivate.h" #include KWSYS_HEADER(DynamicLoader.hxx) #include KWSYS_HEADER(Configure.hxx) +#include KWSYS_HEADER(Encoding.hxx) // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. @@ -25,6 +30,28 @@ // Each part of the ifdef contains a complete implementation for // the static methods of DynamicLoader. +#define CHECK_OPEN_FLAGS(var, supported, ret) \ + do { \ + /* Check for unknown flags. */ \ + if ((var & AllOpenFlags) != var) { \ + return ret; \ + } \ + \ + /* Check for unsupported flags. */ \ + if ((var & (supported)) != var) { \ + return ret; \ + } \ + } while (0) + +namespace KWSYS_NAMESPACE { + +DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( + const std::string& libname) +{ + return DynamicLoader::OpenLibrary(libname, 0); +} +} + #if !KWSYS_SUPPORTS_SHARED_LIBS // Implementation for environments without dynamic libs # include <string.h> // for strerror() @@ -32,7 +59,7 @@ namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { return 0; } @@ -67,8 +94,10 @@ const char* DynamicLoader::LastError() namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { + CHECK_OPEN_FLAGS(flags, 0, 0); + return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L); } @@ -130,8 +159,10 @@ const char* DynamicLoader::LastError() namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { + CHECK_OPEN_FLAGS(flags, 0, 0); + NSObjectFileImageReturnCode rc; NSObjectFileImage image = 0; @@ -185,19 +216,22 @@ const char* DynamicLoader::LastError() // Implementation for Windows win32 code but not cygwin # include <windows.h> +# include <stdio.h> + namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { - DynamicLoader::LibraryHandle lh; - int length = MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, NULL, 0); - wchar_t* wchars = new wchar_t[length + 1]; - wchars[0] = '\0'; - MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, wchars, length); - lh = LoadLibraryW(wchars); - delete[] wchars; - return lh; + CHECK_OPEN_FLAGS(flags, SearchBesideLibrary, NULL); + + DWORD llFlags = 0; + if (flags & SearchBesideLibrary) { + llFlags |= LOAD_WITH_ALTERED_SEARCH_PATH; + } + + return LoadLibraryExW(Encoding::ToWindowsExtendedPath(libname).c_str(), NULL, + llFlags); } int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) @@ -247,24 +281,38 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( # endif } +# define DYNLOAD_ERROR_BUFFER_SIZE 1024 + const char* DynamicLoader::LastError() { - LPVOID lpMsgBuf = NULL; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR)&lpMsgBuf, 0, NULL); + wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1]; + + DWORD error = GetLastError(); + DWORD length = FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + lpMsgBuf, DYNLOAD_ERROR_BUFFER_SIZE, NULL); + + static char str[DYNLOAD_ERROR_BUFFER_SIZE + 1]; + + if (length < 1) { + /* FormatMessage failed. Use a default message. */ + _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE, + "DynamicLoader encountered error 0x%X. " + "FormatMessage failed with error 0x%X", + error, GetLastError()); + return str; + } - if (!lpMsgBuf) { - return NULL; + if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str, + DYNLOAD_ERROR_BUFFER_SIZE, NULL, NULL)) { + /* WideCharToMultiByte failed. Use a default message. */ + _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE, + "DynamicLoader encountered error 0x%X. " + "WideCharToMultiByte failed with error 0x%X", + error, GetLastError()); } - static char* str = 0; - delete[] str; - str = strcpy(new char[strlen((char*)lpMsgBuf) + 1], (char*)lpMsgBuf); - // Free the buffer. - LocalFree(lpMsgBuf); return str; } @@ -282,8 +330,10 @@ namespace KWSYS_NAMESPACE { static image_id last_dynamic_err = B_OK; DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { + CHECK_OPEN_FLAGS(flags, 0, 0); + // image_id's are integers, errors are negative. Add one just in case we // get a valid image_id of zero (is that even possible?). image_id rc = load_add_on(libname.c_str()); @@ -360,8 +410,10 @@ const char* DynamicLoader::LastError() namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { + CHECK_OPEN_FLAGS(flags, 0, NULL); + char* name = (char*)calloc(1, libname.size() + 1); dld_init(program_invocation_name); strncpy(name, libname.c_str(), libname.size()); @@ -404,8 +456,10 @@ const char* DynamicLoader::LastError() namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( - const std::string& libname) + const std::string& libname, int flags) { + CHECK_OPEN_FLAGS(flags, 0, NULL); + return dlopen(libname.c_str(), RTLD_LAZY); } |