aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/changelog.rs11
-rw-r--r--src/error.rs2
-rw-r--r--src/os/windows/mod.rs39
3 files changed, 51 insertions, 1 deletions
diff --git a/src/changelog.rs b/src/changelog.rs
index 0ae7323..67f9cb0 100644
--- a/src/changelog.rs
+++ b/src/changelog.rs
@@ -3,6 +3,17 @@
// TODO: for the next breaking release rename `Error::LoadLibraryW` to `Error::LoadLibraryExW`.
// TODO: for the next breaking release use `RTLD_LAZY | RTLD_LOCAL` by default on unix.
+/// Release 0.6.7 (2021-01-14)
+///
+/// * Added a [`os::windows::Library::open_already_loaded`] to obtain a handle to a library that
+/// must already be loaded. There is no portable equivalent for all UNIX targets. Users who do not
+/// care about portability across UNIX platforms may use [`os::unix::Library::open`] with
+/// `libc::RTLD_NOLOAD`;
+///
+/// [`os::windows::Library::open_already_loaded`]: crate::os::windows::Library::open_already_loaded
+/// [`os::unix::Library::open`]: crate::os::unix::Library::open
+pub mod r0_6_7 {}
+
/// Release 0.6.6 (2020-12-03)
///
/// * Fix a double-release of resources when [`Library::close`] or [`os::windows::Library::close`]
diff --git a/src/error.rs b/src/error.rs
index 6ba5367..e1c465e 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -55,7 +55,7 @@ pub enum Error {
/// The source error.
source: WindowsError
},
- /// The `LoadLibraryW` call failed and system did not report an error.
+ /// The `GetModuleHandleExW` call failed and system did not report an error.
GetModuleHandleExWUnknown,
/// The `GetProcAddress` call failed.
GetProcAddress {
diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs
index da1b5c9..f1298f6 100644
--- a/src/os/windows/mod.rs
+++ b/src/os/windows/mod.rs
@@ -119,6 +119,45 @@ impl Library {
}
}
+ /// Load a module that is already loaded by the program.
+ ///
+ /// This function returns a `Library` corresponding to a module with the given name that is
+ /// already mapped into the address space of the process. If the module isn't found an error is
+ /// returned.
+ ///
+ /// If the `filename` does not include a full path and there are multiple different loaded
+ /// modules corresponding to the `filename`, it is impossible to predict which module handle
+ /// will be returned. For more information refer to [MSDN].
+ ///
+ /// If the `filename` specifies a library filename without path and with extension omitted,
+ /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
+ /// trailing `.` to the `filename`.
+ ///
+ /// This is equivalent to `GetModuleHandleExW(0, filename, _)`.
+ ///
+ /// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
+ pub fn open_already_loaded<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
+ let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
+
+ let ret = unsafe {
+ let mut handle: HMODULE = std::ptr::null_mut();
+ with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
+ // Make sure no winapi calls as a result of drop happen inside this closure, because
+ // otherwise that might change the return value of the GetLastError.
+ let result = libloaderapi::GetModuleHandleExW(0, wide_filename.as_ptr(), &mut handle);
+ if result == 0 {
+ None
+ } else {
+ Some(Library(handle))
+ }
+ }).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown))
+ };
+
+ drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
+ // inside the closure by mistake. See comment inside the closure.
+ ret
+ }
+
/// Find and load a module, additionally adjusting behaviour with flags.
///
/// See [`Library::new`] for documentation on handling of the `filename` argument. See the