Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:30:35

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