path_from_handle.hpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright Antony Polukhin, 2015-2024.
  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. // If `handle` parameter is NULL, GetModuleFileName retrieves the path of the
  28. // executable file of the current process.
  29. boost::winapi::WCHAR_ path_hldr[DEFAULT_PATH_SIZE_];
  30. const boost::winapi::DWORD_ ret = boost::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_);
  31. if (ret) {
  32. // On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually.
  33. ec.clear();
  34. return boost::dll::fs::path(path_hldr);
  35. }
  36. ec = boost::dll::detail::last_error_code();
  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. if (size) {
  41. // On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually.
  42. ec.clear();
  43. p.resize(size);
  44. return boost::dll::fs::path(p);
  45. }
  46. ec = boost::dll::detail::last_error_code();
  47. }
  48. // Error other than ERROR_INSUFFICIENT_BUFFER_ occurred or failed to allocate buffer big enough.
  49. return boost::dll::fs::path();
  50. }
  51. }}} // namespace boost::dll::detail
  52. #endif // BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP