From 809110f0f01786a0b74856dc9bd2443e3b5beabc Mon Sep 17 00:00:00 2001 From: Stefan Vigerske Date: Mon, 22 Apr 2024 11:41:19 +0200 Subject: [PATCH] change loadLibrary on Windows to LoadLibraryA + LoadLibraryExA again - try LoadLibraryA first in any case - try LoadLibraryExA if that failed - print error from both, unless second failed with invalid parameter error --- ChangeLog.md | 2 +- src/Common/IpLibraryLoader.cpp | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0d1f22302..baefd8a6b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,7 +10,7 @@ More detailed information about incremental changes can be found in the ### 3.14.16 (2024-04-22) - Fixed load of linear solver libraries at runtime on Windows, which got - broken for relative paths (the default) in 3.14.15 [#759]. + broken for relative paths (the default) in 3.14.15 [#759, #760]. ### 3.14.15 (2024-04-10) diff --git a/src/Common/IpLibraryLoader.cpp b/src/Common/IpLibraryLoader.cpp index 0ae8a142c..1ba80c5be 100644 --- a/src/Common/IpLibraryLoader.cpp +++ b/src/Common/IpLibraryLoader.cpp @@ -50,23 +50,34 @@ void LibraryLoader::loadLibrary() } #ifdef HAVE_WINDOWS_H - /* if absolute path, then use LoadLibraryExA with LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR to find - * dependencies of library in same directory - * otherwise, use standard search paths (which includes PATH) + libhandle = (void*)LoadLibraryA(libname.c_str()); + + if( libhandle != NULL ) + return; + + std::stringstream s; + s << "Error " << GetLastError() << " while loading DLL " << libname << " via LoadLibraryA: "; + addLastError(s); + + /* try again with LoadLibraryExA + * due to the use of LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR, this will always fail with an invalid parameter error (87) if libname is a relative path */ - if( libname.length() > 2 && libname[1] == ':' ) - libhandle = (void*)LoadLibraryExA(libname.c_str(), NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); - else - libhandle = (void*)LoadLibraryA(libname.c_str()); + libhandle = (void*)LoadLibraryExA(libname.c_str(), NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - if( libhandle == NULL ) + if( libhandle != NULL ) + return; + + /* skip message if LoadLibraryExA failed with invalid parameter error + * do not confuse user just because we were too lazy to check what kind of path libname is + */ + if( GetLastError() != 87 ) { - std::stringstream s; - s << "Error " << GetLastError() << " while loading DLL " << libname << ": "; + s << "Error " << GetLastError() << " while loading DLL " << libname << " via LoadLibraryExA: "; addLastError(s); - THROW_EXCEPTION(DYNAMIC_LIBRARY_FAILURE, s.str()); } + THROW_EXCEPTION(DYNAMIC_LIBRARY_FAILURE, s.str()); + #elif defined(HAVE_DLFCN_H) // ToDo switch to RTLD_LAZY for performance? libhandle = dlopen(libname.c_str(), RTLD_NOW);