Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:43

0001 // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
0002 // Copyright Antony Polukhin, 2015-2023.
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE_1_0.txt
0006 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
0009 #define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
0010 
0011 #include <boost/dll/config.hpp>
0012 #include <boost/dll/shared_library_load_mode.hpp>
0013 #include <boost/dll/detail/aggressive_ptr_cast.hpp>
0014 #include <boost/dll/detail/system_error.hpp>
0015 #include <boost/dll/detail/windows/path_from_handle.hpp>
0016 
0017 #include <boost/move/utility.hpp>
0018 #include <boost/core/invoke_swap.hpp>
0019 
0020 #include <boost/winapi/dll.hpp>
0021 
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 # pragma once
0024 #endif
0025 
0026 namespace boost { namespace dll { namespace detail {
0027 
0028 class shared_library_impl {
0029     BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl)
0030 
0031 public:
0032     typedef boost::winapi::HMODULE_ native_handle_t;
0033 
0034     shared_library_impl() BOOST_NOEXCEPT
0035         : handle_(NULL)
0036     {}
0037 
0038     ~shared_library_impl() BOOST_NOEXCEPT {
0039         unload();
0040     }
0041 
0042     shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT
0043         : handle_(sl.handle_)
0044     {
0045         sl.handle_ = NULL;
0046     }
0047 
0048     shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT {
0049         swap(sl);
0050         return *this;
0051     }
0052 
0053     static boost::dll::fs::path decorate(const boost::dll::fs::path& sl) {
0054         boost::dll::fs::path actual_path = sl;
0055         actual_path += suffix();
0056         return actual_path;
0057     }
0058 
0059     void load(boost::dll::fs::path sl, load_mode::type portable_mode, boost::dll::fs::error_code &ec) {
0060         typedef boost::winapi::DWORD_ native_mode_t;
0061         native_mode_t native_mode = static_cast<native_mode_t>(portable_mode);
0062         unload();
0063 
0064         if (!sl.is_absolute() && !(native_mode & load_mode::search_system_folders)) {
0065             boost::dll::fs::error_code current_path_ec;
0066             boost::dll::fs::path prog_loc = boost::dll::fs::current_path(current_path_ec);
0067 
0068             if (!current_path_ec) {
0069                 prog_loc /= sl;
0070                 sl.swap(prog_loc);
0071             }
0072         }
0073         native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::search_system_folders);
0074 
0075         // Trying to open with appended decorations
0076         if (!!(native_mode & load_mode::append_decorations)) {
0077             native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::append_decorations);
0078 
0079             if (load_impl(decorate(sl), native_mode, ec)) {
0080                 return;
0081             }
0082 
0083             // MinGW loves 'lib' prefix and puts it even on Windows platform.
0084             const boost::dll::fs::path mingw_load_path = (
0085                 sl.has_parent_path()
0086                 ? sl.parent_path() / L"lib"
0087                 : L"lib"
0088             ).native() + sl.filename().native() + suffix().native();
0089             if (load_impl(mingw_load_path, native_mode, ec)) {
0090                 return;
0091             }
0092         }
0093 
0094         // From MSDN: If the string specifies a module name without a path and the
0095         // file name extension is omitted, the function appends the default library
0096         // extension .dll to the module name.
0097         //
0098         // From experiments: Default library extension appended to the module name even if
0099         // we have some path. So we do not check for path, only for extension. We can not be sure that
0100         // such behavior remain across all platforms, so we add L"." by hand.
0101         if (sl.has_extension()) {
0102             handle_ = boost::winapi::LoadLibraryExW(sl.c_str(), 0, native_mode);
0103         } else {
0104             handle_ = boost::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, native_mode);
0105         }
0106 
0107         // LoadLibraryExW method is capable of self loading from program_location() path. No special actions
0108         // must be taken to allow self loading.
0109         if (!handle_) {
0110             ec = boost::dll::detail::last_error_code();
0111         }
0112     }
0113 
0114     bool is_loaded() const BOOST_NOEXCEPT {
0115         return (handle_ != 0);
0116     }
0117 
0118     void unload() BOOST_NOEXCEPT {
0119         if (handle_) {
0120             boost::winapi::FreeLibrary(handle_);
0121             handle_ = 0;
0122         }
0123     }
0124 
0125     void swap(shared_library_impl& rhs) BOOST_NOEXCEPT {
0126         boost::core::invoke_swap(handle_, rhs.handle_);
0127     }
0128 
0129     boost::dll::fs::path full_module_path(boost::dll::fs::error_code &ec) const {
0130         return boost::dll::detail::path_from_handle(handle_, ec);
0131     }
0132 
0133     static boost::dll::fs::path suffix() {
0134         return L".dll";
0135     }
0136 
0137     void* symbol_addr(const char* sb, boost::dll::fs::error_code &ec) const BOOST_NOEXCEPT {
0138         if (is_resource()) {
0139             // `GetProcAddress` could not be called for libraries loaded with
0140             // `LOAD_LIBRARY_AS_DATAFILE`, `LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`
0141             // or `LOAD_LIBRARY_AS_IMAGE_RESOURCE`.
0142             ec = boost::dll::fs::make_error_code(
0143                 boost::dll::fs::errc::operation_not_supported
0144             );
0145 
0146             return NULL;
0147         }
0148 
0149         // Judging by the documentation of GetProcAddress
0150         // there is no version for UNICODE on desktop/server Windows, because
0151         // names of functions are stored in narrow characters.
0152         void* const symbol = boost::dll::detail::aggressive_ptr_cast<void*>(
0153             boost::winapi::get_proc_address(handle_, sb)
0154         );
0155         if (symbol == NULL) {
0156             ec = boost::dll::detail::last_error_code();
0157         }
0158 
0159         return symbol;
0160     }
0161 
0162     native_handle_t native() const BOOST_NOEXCEPT {
0163         return handle_;
0164     }
0165 
0166 private:
0167     // Returns true if this load attempt should be the last one.
0168     bool load_impl(const boost::dll::fs::path &load_path, boost::winapi::DWORD_ mode, boost::dll::fs::error_code &ec) {
0169         handle_ = boost::winapi::LoadLibraryExW(load_path.c_str(), 0, mode);
0170         if (handle_) {
0171             return true;
0172         }
0173 
0174         ec = boost::dll::detail::last_error_code();
0175         if (boost::dll::fs::exists(load_path)) {
0176             // decorated path exists : current error is not a bad file descriptor
0177             return true;
0178         }
0179 
0180         ec.clear();
0181         return false;
0182     }
0183 
0184     bool is_resource() const BOOST_NOEXCEPT {
0185         return false; /*!!(
0186             reinterpret_cast<boost::winapi::ULONG_PTR_>(handle_) & static_cast<boost::winapi::ULONG_PTR_>(3)
0187         );*/
0188     }
0189 
0190     native_handle_t handle_;
0191 };
0192 
0193 }}} // boost::dll::detail
0194 
0195 #endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP