path_from_handle.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright 2015-2019 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_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
  8. #define BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
  9. #include <boost/dll/config.hpp>
  10. #include <boost/dll/detail/system_error.hpp>
  11. #include <boost/winapi/dll.hpp>
  12. #include <boost/winapi/get_last_error.hpp>
  13. #ifdef BOOST_HAS_PRAGMA_ONCE
  14. # pragma once
  15. #endif
  16. namespace boost { namespace dll { namespace detail {
  17. inline boost::dll::fs::error_code last_error_code() BOOST_NOEXCEPT {
  18. boost::winapi::DWORD_ err = boost::winapi::GetLastError();
  19. return boost::dll::fs::error_code(
  20. static_cast<int>(err),
  21. boost::dll::fs::system_category()
  22. );
  23. }
  24. inline boost::dll::fs::path path_from_handle(boost::winapi::HMODULE_ handle, boost::dll::fs::error_code &ec) {
  25. BOOST_STATIC_CONSTANT(boost::winapi::DWORD_, ERROR_INSUFFICIENT_BUFFER_ = 0x7A);
  26. BOOST_STATIC_CONSTANT(boost::winapi::DWORD_, DEFAULT_PATH_SIZE_ = 260);
  27. // On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually.
  28. boost::winapi::GetLastError();
  29. // If `handle` parameter is NULL, GetModuleFileName retrieves the path of the
  30. // executable file of the current process.
  31. boost::winapi::WCHAR_ path_hldr[DEFAULT_PATH_SIZE_];
  32. boost::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_);
  33. ec = boost::dll::detail::last_error_code();
  34. if (!ec) {
  35. return boost::dll::fs::path(path_hldr);
  36. }
  37. for (unsigned i = 2; i < 1025 && static_cast<boost::winapi::DWORD_>(ec.value()) == ERROR_INSUFFICIENT_BUFFER_; i *= 2) {
  38. std::wstring p(DEFAULT_PATH_SIZE_ * i, L'\0');
  39. const std::size_t size = boost::winapi::GetModuleFileNameW(handle, &p[0], DEFAULT_PATH_SIZE_ * i);
  40. ec = boost::dll::detail::last_error_code();
  41. if (!ec) {
  42. p.resize(size);
  43. return boost::dll::fs::path(p);
  44. }
  45. }
  46. // Error other than ERROR_INSUFFICIENT_BUFFER_ occurred or failed to allocate buffer big enough.
  47. return boost::dll::fs::path();
  48. }
  49. }}} // namespace boost::dll::detail
  50. #endif // BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP