path_from_handle.hpp 2.4 KB

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