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