mirror of
https://github.com/openharmony/third_party_rust_libloading.git
synced 2026-08-26 16:31:22 -04:00
Add os::windows::Library::open_already_loaded()
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -235,3 +235,23 @@ fn works_getlasterror0() {
|
||||
assert_eq!(errhandlingapi::GetLastError(), gle())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn library_open_already_loaded() {
|
||||
use libloading::os::windows::Library;
|
||||
|
||||
// Present on Windows systems and NOT used by any other tests to prevent races.
|
||||
const LIBPATH: &str = "Msftedit.dll";
|
||||
|
||||
// Not loaded yet.
|
||||
assert!(match Library::open_already_loaded(LIBPATH) {
|
||||
Err(libloading::Error::GetModuleHandleExW { .. }) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let _lib = Library::new(LIBPATH).unwrap();
|
||||
|
||||
// Loaded now.
|
||||
assert!(Library::open_already_loaded(LIBPATH).is_ok());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user