@@ -104,6 +104,15 @@ namespace boost { namespace dll { namespace detail {
104104#if BOOST_OS_QNX
105105// QNX's copy of <elf.h> and <link.h> reside in sys folder
106106# include < sys/link.h>
107+ #elif BOOST_OS_CYGWIN
108+ // Cygwin returns the opaque pointer-sized handle of type `HMODULE` on the invoke of `dlopen`,
109+ // which cannot be interpreted. As GCC on Cygwin always links to KERNEL32.DLL, we can use the
110+ // standard Win32 API `GetModuleFileNameW` to implement `path_from_handle`
111+ //
112+ // Introduce the Win32 API `GetModuleFileNameW` here
113+ extern " C" void GetModuleFileNameW (void *, wchar_t *, unsigned long long );
114+ // Introduce the Win32 API `GetLastError` here
115+ extern " C" unsigned long long GetLastError ();
107116#else
108117# include < link.h> // struct link_map
109118#endif
@@ -129,9 +138,29 @@ namespace boost { namespace dll { namespace detail {
129138 // Unfortunately we can not use `dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0`
130139 // because it is not supported on MacOS X 10.3, NetBSD 3.0, OpenBSD 3.8, AIX 5.1,
131140 // HP-UX 11, IRIX 6.5, OSF/1 5.1, Cygwin, mingw, Interix 3.5, BeOS.
132- // Fortunately investigating the sources of open source projects brought the understanding, that
141+ // Fortunately, investigating the sources of open source projects brought the understanding, that
133142 // `handle` is just a `struct link_map*` that contains full library name.
134143
144+ #if BOOST_OS_CYGWIN
145+ // Cygwin doesn't have <link.h> header
146+ unsigned long long buffer_size = 4096 ;
147+ std::vector<wchar_t > buffer;
148+ do
149+ {
150+ buffer.resize (buffer_size);
151+ GetModuleFileNameW (handle, buffer.data (), buffer.size ());
152+ buffer_size *= 2 ;
153+ } while (GetLastError () == 122 /* ERROR_INSUFFICIENT_BUFFER */ );
154+ if (GetLastError () == 0 )
155+ {
156+ return boost::filesystem::path (buffer.data ());
157+ } else
158+ {
159+ boost::dll::detail::reset_dlerror ();
160+ ec = std::make_error_code (std::errc::bad_file_descriptor);
161+ return boost::filesystem::path ();
162+ }
163+ #else
135164 const struct link_map * link_map = 0 ;
136165#if BOOST_OS_BSD_FREE
137166 // FreeBSD has it's own logic http://code.metager.de/source/xref/freebsd/libexec/rtld-elf/rtld.c
@@ -156,6 +185,7 @@ namespace boost { namespace dll { namespace detail {
156185 }
157186
158187 return boost::dll::fs::path (link_map->l_name );
188+ #endif
159189 }
160190
161191}}} // namespace boost::dll::detail
0 commit comments