shared_library_impl.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright 2015-2016 Antony Polukhin.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
  8. #define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
  9. #include <boost/config.hpp>
  10. #include <boost/dll/shared_library_load_mode.hpp>
  11. #include <boost/dll/detail/aggressive_ptr_cast.hpp>
  12. #include <boost/dll/detail/system_error.hpp>
  13. #include <boost/dll/detail/windows/path_from_handle.hpp>
  14. #include <boost/move/utility.hpp>
  15. #include <boost/swap.hpp>
  16. #include <boost/filesystem/path.hpp>
  17. #include <boost/filesystem/operations.hpp>
  18. #include <boost/winapi/dll.hpp>
  19. #ifdef BOOST_HAS_PRAGMA_ONCE
  20. # pragma once
  21. #endif
  22. namespace boost { namespace dll { namespace detail {
  23. class shared_library_impl {
  24. BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl)
  25. public:
  26. typedef boost::winapi::HMODULE_ native_handle_t;
  27. shared_library_impl() BOOST_NOEXCEPT
  28. : handle_(NULL)
  29. {}
  30. ~shared_library_impl() BOOST_NOEXCEPT {
  31. unload();
  32. }
  33. shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT
  34. : handle_(sl.handle_)
  35. {
  36. sl.handle_ = NULL;
  37. }
  38. shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT {
  39. swap(sl);
  40. return *this;
  41. }
  42. void load(boost::filesystem::path sl, load_mode::type mode, boost::system::error_code &ec) {
  43. typedef boost::winapi::DWORD_ native_mode_t;
  44. unload();
  45. if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
  46. boost::system::error_code current_path_ec;
  47. boost::filesystem::path prog_loc = boost::filesystem::current_path(current_path_ec);
  48. if (!current_path_ec) {
  49. prog_loc /= sl;
  50. sl.swap(prog_loc);
  51. }
  52. }
  53. mode &= ~load_mode::search_system_folders;
  54. // Trying to open with appended decorations
  55. if (!!(mode & load_mode::append_decorations)) {
  56. mode &= ~load_mode::append_decorations;
  57. handle_ = boost::winapi::LoadLibraryExW((sl.native() + L".dll").c_str(), 0, static_cast<native_mode_t>(mode));
  58. if (!handle_) {
  59. // MinGW loves 'lib' prefix and puts it even on Windows platform
  60. const boost::filesystem::path load_path = (sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native() + L".dll";
  61. handle_ = boost::winapi::LoadLibraryExW(
  62. load_path.c_str(),
  63. 0,
  64. static_cast<native_mode_t>(mode)
  65. );
  66. }
  67. if (handle_) {
  68. return;
  69. }
  70. }
  71. // From MSDN: If the string specifies a module name without a path and the
  72. // file name extension is omitted, the function appends the default library
  73. // extension .dll to the module name.
  74. //
  75. // From experiments: Default library extension appended to the module name even if
  76. // we have some path. So we do not check for path, only for extension. We can not be sure that
  77. // such behavior remain across all platforms, so we add L"." by hand.
  78. if (sl.has_extension()) {
  79. handle_ = boost::winapi::LoadLibraryExW(sl.c_str(), 0, static_cast<native_mode_t>(mode));
  80. } else {
  81. handle_ = boost::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, static_cast<native_mode_t>(mode));
  82. }
  83. // LoadLibraryExW method is capable of self loading from program_location() path. No special actions
  84. // must be taken to allow self loading.
  85. if (!handle_) {
  86. ec = boost::dll::detail::last_error_code();
  87. }
  88. }
  89. bool is_loaded() const BOOST_NOEXCEPT {
  90. return (handle_ != 0);
  91. }
  92. void unload() BOOST_NOEXCEPT {
  93. if (handle_) {
  94. boost::winapi::FreeLibrary(handle_);
  95. handle_ = 0;
  96. }
  97. }
  98. void swap(shared_library_impl& rhs) BOOST_NOEXCEPT {
  99. boost::swap(handle_, rhs.handle_);
  100. }
  101. boost::filesystem::path full_module_path(boost::system::error_code &ec) const {
  102. return boost::dll::detail::path_from_handle(handle_, ec);
  103. }
  104. static boost::filesystem::path suffix() {
  105. return L".dll";
  106. }
  107. void* symbol_addr(const char* sb, boost::system::error_code &ec) const BOOST_NOEXCEPT {
  108. if (is_resource()) {
  109. // `GetProcAddress` could not be called for libraries loaded with
  110. // `LOAD_LIBRARY_AS_DATAFILE`, `LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`
  111. // or `LOAD_LIBRARY_AS_IMAGE_RESOURCE`.
  112. ec = boost::system::error_code(
  113. boost::system::errc::operation_not_supported,
  114. boost::system::generic_category()
  115. );
  116. return NULL;
  117. }
  118. // Judging by the documentation of GetProcAddress
  119. // there is no version for UNICODE on desktop/server Windows, because
  120. // names of functions are stored in narrow characters.
  121. void* const symbol = boost::dll::detail::aggressive_ptr_cast<void*>(
  122. boost::winapi::get_proc_address(handle_, sb)
  123. );
  124. if (symbol == NULL) {
  125. ec = boost::dll::detail::last_error_code();
  126. }
  127. return symbol;
  128. }
  129. native_handle_t native() const BOOST_NOEXCEPT {
  130. return handle_;
  131. }
  132. private:
  133. bool is_resource() const BOOST_NOEXCEPT {
  134. return false; /*!!(
  135. reinterpret_cast<boost::winapi::ULONG_PTR_>(handle_) & static_cast<boost::winapi::ULONG_PTR_>(3)
  136. );*/
  137. }
  138. native_handle_t handle_;
  139. };
  140. }}} // boost::dll::detail
  141. #endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP