jaulib v1.3.0
Jau Support Library (C++, Java, ..)
windows_dyn_linker.cpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#if defined(_WIN32)
25 #include <cstdlib>
26
27 #include <cassert>
28
29 #include "jau/os/dyn_linker.hpp"
30
31 #include <windows.h>
32 /* This typedef is apparently needed for compilers before VC8,
33 and for the embedded ARM compilers we're using */
34 #if !defined(__MINGW64__) && ( (_MSC_VER < 1400) || defined(UNDER_CE) )
35 typedef int intptr_t;
36 #endif
37 /* GetProcAddress doesn't exist in A/W variants under desktop Windows */
38 #ifndef UNDER_CE
39 #define GetProcAddressA GetProcAddress
40 #endif
41
42 namespace jau::os::impl {
43
44 using namespace jau::os;
45
46 class WindowsDynamicLinker : public DynamicLinker {
47 private:
48 constexpr static const int symbolArgAlignment=4; // 4 byte alignment of each argument
49 constexpr static const int symbolMaxArguments=12; // experience ..
50
51 protected:
52 libhandle_t openLibraryGlobalImpl(const std::string& pathname) noexcept override {
53 HANDLE res = LoadLibraryW((LPCWSTR) pathname.c_str());
54 return reinterpret_cast<libhandle_t>( res ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
55
56 }
57 libhandle_t openLibraryLocalImpl(const std::string& pathname) noexcept override {
58 // How does that work under Windows ?
59 // Don't know .. so it's an alias to global, for the time being
60 HANDLE res = LoadLibraryW((LPCWSTR) pathname.c_str());
61 return reinterpret_cast<libhandle_t>( res ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
62 }
63
64 const char* lookupLibraryPathnameImpl(libhandle_t handle, const std::string& symbolName) noexcept override {
65 // symbolName is not required
66 return 0 != handle ? GetModuleFileNameA( reinterpret_cast<HANDLE>(handle) ) : nullptr; // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
67 }
68
69 symhandle_t lookupSymbolLocalImpl(libhandle_t handle, const std::string& symbolName) noexcept override {
70 std::string altSymbolName = symbolName;
71 symhandle_t addr = GetProcAddressA(reinterpret_cast<HANDLE>(handle), altSymbolName.c_str()); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
72 if( 0 == addr ) {
73 // __stdcall hack: try some @nn decorations,
74 // the leading '_' must not be added (same with cdecl)
75 for(int arg=0; 0==addr && arg<=symbolMaxArguments; arg++) {
76 altSymbolName = symbolName+"@"+std::to_string(arg*symbolArgAlignment);
77 addr = GetProcAddressA(reinterpret_cast<HANDLE>(handle), altSymbolName.c_str()); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
78 }
79 }
80 return addr;
81 }
82
83 symhandle_t lookupSymbolGlobalImpl(const std::string& symbolName) noexcept override {
84 if(DEBUG_LOOKUP) {
85 WARN_PRINT("lookupSymbolGlobal: Not supported on Windows");
86 }
87 // allow DynamicLibraryBundle to continue w/ local libs
88 return 0;
89 }
90
91 void closeLibraryImpl(libhandle_t handle) noexcept override {
92 FreeLibrary( reinterpret_cast<HANDLE>(handle) ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
93 }
94
95 std::string getLastErrorImpl() noexcept override {
96 const int err = GetLastError();
97 return "Last error: "+jau::to_hexstring(err)+" ("+std::to_string(err)+")";
98 }
99 };
100
101 } // namespace jau::os::impl
102
103 jau::os::DynamicLinker* jau::os::DynamicLinker::create() {
104 return new jau::os::impl::WindowsDynamicLinker();
105 }
106
107#endif // _WIN32
Low level secure dynamic linker access.
Definition: dyn_linker.hpp:45
#define WARN_PRINT(...)
Use for unconditional warning messages, prefix '[elapsed_time] Warning @ FILE:LINE FUNC: '.
Definition: debug.hpp:123
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
Definition: dyn_linker.hpp:37