Mark ab/7061308 as merged in stage.

Bug: 180401296
Merged-In: I0e03e0a0af1d3267cca780e4b4fbb99140ed436b
Change-Id: I7645d7f8087063ab4a4a7258cf67caeca187044a
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index eb64010..69cdb18 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "c8b034167dae9e4b00c8c5e7dca651738f8bd421"
+    "sha1": "7fbd3a34336f7839bdd6d6aaf83a9a763c4fa1e5"
   }
 }
diff --git a/.github/workflows/libloading.yml b/.github/workflows/libloading.yml
index aa9b3f6..811681d 100644
--- a/.github/workflows/libloading.yml
+++ b/.github/workflows/libloading.yml
@@ -6,7 +6,7 @@
     - '*.mkd'
     - 'LICENSE'
   pull_request:
-    types: [opened, repoened, synchronize]
+    types: [opened, reopened, synchronize]
 
 jobs:
   native-test:
diff --git a/Android.bp b/Android.bp
index 65aa6bb..bbae702 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,22 @@
 // This file is generated by cargo2android.py --run --dependencies.
 
+package {
+    default_applicable_licenses: ["external_rust_crates_libloading_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "external_rust_crates_libloading_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-ISC",
+    ],
+    license_text: [
+        "LICENSE",
+    ],
+}
+
 rust_library_host {
     name: "liblibloading",
     crate_name: "libloading",
diff --git a/Cargo.toml b/Cargo.toml
index ea9984d..396a5c2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
 
 [package]
 name = "libloading"
-version = "0.6.6"
+version = "0.7.0"
 authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
 description = "A safer binding to platform’s dynamic library loading utilities"
 documentation = "https://docs.rs/libloading/"
@@ -33,4 +33,4 @@
 version = "1"
 [target."cfg(windows)".dependencies.winapi]
 version = "0.3"
-features = ["winerror", "errhandlingapi", "libloaderapi"]
+features = ["errhandlingapi", "libloaderapi"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 6e4696b..d946299 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -3,7 +3,7 @@
 # When bumping
 # * Don’t forget to add an entry to `src/changelog.rs`
 # * If bumping a incompatible version, adjust documentation in `src/lib.rs`
-version = "0.6.6"
+version = "0.7.0"
 authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
 license = "ISC"
 repository = "https://github.com/nagisa/rust_libloading/"
@@ -16,7 +16,6 @@
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
 features = [
-    "winerror",
     "errhandlingapi",
     "libloaderapi",
 ]
diff --git a/METADATA b/METADATA
index 814a83a..769af4a 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/libloading/libloading-0.6.6.crate"
+    value: "https://static.crates.io/crates/libloading/libloading-0.7.0.crate"
   }
-  version: "0.6.6"
+  version: "0.7.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2020
-    month: 12
-    day: 3
+    year: 2021
+    month: 2
+    day: 9
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 7bc6ed2..58584f2 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,9 +1,8 @@
-// Generated by cargo2android.py for tests in Android.bp
+// Generated by update_crate_tests.py for tests that depend on this crate.
 {
   "presubmit": [
     {
-      "host": true,
-      "name": "libsqlite3-sys_host_test_src_lib"
+      "name": "keystore2_test"
     },
     {
       "name": "libsqlite3-sys_device_test_src_lib"
diff --git a/src/changelog.rs b/src/changelog.rs
index 0ae7323..c927551 100644
--- a/src/changelog.rs
+++ b/src/changelog.rs
@@ -1,7 +1,117 @@
-//! Project changelog
+//! The change log.
 
-// 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.7.0 (2021-01-31)
+///
+/// ## Breaking changes
+///
+/// ### Loading functions are now `unsafe`
+///
+/// A number of associated methods involved in loading a library were changed to
+/// be `unsafe`. The affected functions are: [`Library::new`], [`os::unix::Library::new`],
+/// [`os::unix::Library::open`], [`os::windows::Library::new`],
+/// [`os::windows::Library::load_with_flags`]. This is the most prominent breaking change in this
+/// release and affects majority of the users of `libloading`.
+///
+/// In order to see why it was necessary, consider the following snippet of C++ code:
+///
+/// ```c++
+/// #include <vector>
+/// #include <iostream>
+///
+/// static std::vector<unsigned int> UNSHUU = { 1, 2, 3 };
+///
+/// int main() {
+///     std::cout << UNSHUU[0] << UNSHUU[1] << UNSHUU[2] << std::endl; // Prints 123
+///     return 0;
+/// }
+/// ```
+///
+/// The `std::vector` type, much like in Rust's `Vec`, stores its contents in a buffer allocated on
+/// the heap. In this example the vector object itself is stored and initialized as a static
+/// variable – a compile time construct. The heap, on the other hand, is a runtime construct. And
+/// yet the code works exactly as you'd expect – the vector contains numbers 1, 2 and 3 stored in
+/// a buffer on heap. So, _what_ makes it work out, exactly?
+///
+/// Various executable and shared library formats define conventions and machinery to execute
+/// arbitrary code when a program or a shared library is loaded. On systems using the PE format
+/// (e.g. Windows) this is available via the optional `DllMain` initializer. Various systems
+/// utilizing the ELF format take a sightly different approach of maintaining an array of function
+/// pointers in the `.init_array` section. A very similar mechanism exists on systems that utilize
+/// the Mach-O format.
+///
+/// For the C++ program above, the object stored in the `UNSHUU` global variable is constructed
+/// by code run as part of such an initializer routine. This initializer is run before the entry
+/// point (the `main` function) is executed, allowing for this magical behaviour to be possible.
+/// Were the C++ code built as a shared library instead, the initialization routines would run as
+/// the resulting shared library is loaded. In case of `libloading` – during the call to
+/// `Library::new` and other methods affected by this change.
+///
+/// These initialization (and very closely related termination) routines can be utilized outside of
+/// C++ too. Anybody can build a shared library in variety of different programming languages and
+/// set up the initializers to execute arbitrary code. Potentially code that does all sorts of
+/// wildly unsound stuff.
+///
+/// The routines are executed by components that are an integral part of the operating system.
+/// Changing or controlling the operation of these components is infeasible. With that in
+/// mind, the initializer and termination routines are something anybody loading a library must
+/// carefully evaluate the libraries loaded for soundness.
+///
+/// In practice, a vast majority of the libraries can be considered a good citizen and their
+/// initialization and termination routines, if they have any at all, can be trusted to be sound.
+///
+/// Also see: [issue #86].
+///
+/// ### Better & more consistent default behaviour on UNIX systems
+///
+/// On UNIX systems the [`Library::new`], [`os::unix::Library::new`] and
+/// [`os::unix::Library::this`] methods have been changed to use
+/// <code>[RTLD_LAZY] | [RTLD_LOCAL]</code> as the default set of loader options (previously:
+/// [`RTLD_NOW`]). This has a couple benefits. Namely:
+///
+/// * Lazy binding is generally quicker to execute when only a subset of symbols from a library are
+///   used and is typically the default when neither `RTLD_LAZY` nor `RTLD_NOW` are specified when
+///   calling the underlying `dlopen` API;
+/// * On most UNIX systems (macOS being a notable exception) `RTLD_LOCAL` is the default when
+///   neither `RTLD_LOCAL` nor [`RTLD_GLOBAL`] are specified. The explicit setting of the
+///   `RTLD_LOCAL` flag makes this behaviour consistent across platforms.
+///
+/// ### Dropped support for Windows XP/Vista
+///
+/// The (broken) support for Windows XP and Windows Vista environments was removed. This was
+/// prompted primarily by a similar policy change in the [Rust
+/// project](https://github.com/rust-lang/compiler-team/issues/378) but also as an acknowledgement
+/// to the fact that `libloading` never worked in these environments anyway.
+///
+/// ### More accurate error variant names
+///
+/// Finally, the `Error::LoadLibraryW` renamed to [`Error::LoadLibraryExW`] to more accurately
+/// represent the underlying API that's failing. No functional changes as part of this rename
+/// intended.
+///
+/// [issue #86]: https://github.com/nagisa/rust_libloading/issues/86
+/// [`Library::new`]: crate::Library::new
+/// [`Error::LoadLibraryExW`]: crate::Error::LoadLibraryExW
+/// [`os::unix::Library::this`]: crate::os::unix::Library::this
+/// [`os::unix::Library::new`]: crate::os::unix::Library::new
+/// [`os::unix::Library::open`]: crate::os::unix::Library::new
+/// [`os::windows::Library::new`]: crate::os::windows::Library::new
+/// [`os::windows::Library::load_with_flags`]: crate::os::windows::Library::load_with_flags
+/// [`RTLD_NOW`]: crate::os::unix::RTLD_NOW
+/// [RTLD_LAZY]: crate::os::unix::RTLD_LAZY
+/// [RTLD_LOCAL]: crate::os::unix::RTLD_LOCAL
+/// [`RTLD_GLOBAL`]: crate::os::unix::RTLD_GLOBAL
+pub mod r0_7_0 {}
+
+/// 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)
 ///
diff --git a/src/error.rs b/src/error.rs
index 6ba5367..bd70ec3 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -44,18 +44,18 @@
     /// The `dlclose` call failed and system did not report an error.
     DlCloseUnknown,
     /// The `LoadLibraryW` call failed.
-    LoadLibraryW {
+    LoadLibraryExW {
         /// The source error.
         source: WindowsError
     },
     /// The `LoadLibraryW` call failed and system did not report an error.
-    LoadLibraryWUnknown,
+    LoadLibraryExWUnknown,
     /// The `GetModuleHandleExW` call failed.
     GetModuleHandleExW {
         /// 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 {
@@ -91,7 +91,7 @@
         match *self {
             CreateCString { ref source } => Some(source),
             CreateCStringWithTrailing { ref source } => Some(source),
-            LoadLibraryW { ref source } => Some(&source.0),
+            LoadLibraryExW { ref source } => Some(&source.0),
             GetProcAddress { ref source } => Some(&source.0),
             FreeLibrary { ref source } => Some(&source.0),
             _ => None,
@@ -109,8 +109,8 @@
             DlSymUnknown => write!(f, "dlsym failed, but system did not report the error"),
             DlClose { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
             DlCloseUnknown => write!(f, "dlclose failed, but system did not report the error"),
-            LoadLibraryW { .. } => write!(f, "LoadLibraryExW failed"),
-            LoadLibraryWUnknown =>
+            LoadLibraryExW { .. } => write!(f, "LoadLibraryExW failed"),
+            LoadLibraryExWUnknown =>
                 write!(f, "LoadLibraryExW failed, but system did not report the error"),
             GetModuleHandleExW { .. } => write!(f, "GetModuleHandleExW failed"),
             GetModuleHandleExWUnknown =>
diff --git a/src/lib.rs b/src/lib.rs
index 21912b8..9a531f1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,15 +1,14 @@
 //! A memory-safer wrapper around system dynamic library loading primitives.
 //!
 //! Using this library allows loading [dynamic libraries](struct.Library.html) (also known as
-//! shared libraries) as well as use functions and static variables these libraries contain.
+//! shared libraries) and use functions & global variables contained within the libraries.
 //!
-//! While the library does expose a cross-platform interface to load a library and find stuff
-//! inside it, little is done to paper over the platform differences, especially where library
-//! loading is involved. The documentation for each function will attempt to document such
-//! differences on the best-effort basis.
+//! `libloading` crate exposes a cross-platform interface to load a library and utilize its
+//! contents, but little is done to paper over the differences in behaviour between different
+//! platforms. The API documentation strives to document such differences on the best-effort basis.
 //!
-//! Less safe, platform specific bindings are also available. See the
-//! [`os::platform`](os/index.html) module for details.
+//! Platform specific APIs are also available in the [`os`](crate::os) module. These APIs are more
+//! flexible but less safe.
 //!
 //! # Usage
 //!
@@ -17,25 +16,23 @@
 //!
 //! ```toml
 //! [dependencies]
-//! libloading = "0.6"
+//! libloading = "0.7"
 //! ```
 //!
-//! Then inside your project
+//! Then inside your code:
 //!
 //! ```no_run
-//! extern crate libloading as lib;
-//!
 //! fn call_dynamic() -> Result<u32, Box<dyn std::error::Error>> {
-//!     let lib = lib::Library::new("/path/to/liblibrary.so")?;
 //!     unsafe {
-//!         let func: lib::Symbol<unsafe extern fn() -> u32> = lib.get(b"my_func")?;
+//!         let lib = libloading::Library::new("/path/to/liblibrary.so")?;
+//!         let func: libloading::Symbol<unsafe extern fn() -> u32> = lib.get(b"my_func")?;
 //!         Ok(func())
 //!     }
 //! }
 //! ```
 //!
 //! The compiler will ensure that the loaded `function` will not outlive the `Library` it comes
-//! from, preventing a common cause of undefined behaviour and memory safety problems.
+//! from, preventing a common class of issues.
 #![deny(
     missing_docs,
     clippy::all,
@@ -74,20 +71,26 @@
     /// * Absolute path to the library;
     /// * Relative (to the current working directory) path to the library.
     ///
+    /// # Safety
+    ///
+    /// When a library is loaded initialization routines contained within the library are executed.
+    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
+    /// to be sound.
+    ///
+    /// Additionally, the callers of this function must also ensure that execution of the
+    /// termination routines contained within the library is safe as well. These routines may be
+    /// executed when the library is unloaded.
+    ///
     /// # Thread-safety
     ///
-    /// The implementation strives to be as MT-safe as sanely possible, however due to certain
-    /// error-handling related resources not always being safe, this library is not MT-safe either.
+    /// The implementation strives to be as MT-safe as sanely possible, however on certain
+    /// platforms the underlying error-handling related APIs not always MT-safe. This library
+    /// shares these limitations on those platforms. In particular, on certain UNIX targets
+    /// `dlerror` is not MT-safe, resulting in garbage error messages in certain MT-scenarios.
     ///
-    /// * On Windows Vista and earlier error handling falls back to [`SetErrorMode`], which is not
-    ///   MT-safe. MT-scenarios involving this function may cause a traditional data race;
-    /// * On some UNIX targets `dlerror` might not be MT-safe, resulting in garbage error messages
-    ///   in certain MT-scenarios.
-    ///
-    /// [`SetErrorMode`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
-    ///
-    /// Calling this function from multiple threads is not safe if used in conjunction with
-    /// relative filenames and the library search path is modified (`SetDllDirectory` function on
+    /// Calling this function from multiple threads is not MT-safe if used in conjunction with
+    /// library filenames and the library search path is modified (`SetDllDirectory` function on
     /// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
     ///
     /// # Platform-specific behaviour
@@ -97,15 +100,8 @@
     /// the platform specific [`os::unix::Library::new`] and [`os::windows::Library::new`] methods
     /// for further information on library lookup behaviour.
     ///
-    /// ## Windows
-    ///
     /// 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`.
-    ///
-    /// If the library contains thread local variables (MSVC’s `_declspec(thread)`, Rust’s
-    /// `#[thread_local]` attributes), loading the library will fail on versions prior to Windows
-    /// Vista.
+    /// `.dll` extension is implicitly added on Windows.
     ///
     /// # Tips
     ///
@@ -123,36 +119,37 @@
     /// ```no_run
     /// # use ::libloading::Library;
     /// // Any of the following are valid.
-    /// let _ = Library::new("/path/to/awesome.module").unwrap();
-    /// let _ = Library::new("../awesome.module").unwrap();
-    /// let _ = Library::new("libsomelib.so.1").unwrap();
+    /// unsafe {
+    ///     let _ = Library::new("/path/to/awesome.module").unwrap();
+    ///     let _ = Library::new("../awesome.module").unwrap();
+    ///     let _ = Library::new("libsomelib.so.1").unwrap();
+    /// }
     /// ```
-    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, Error> {
+    pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, Error> {
         imp::Library::new(filename).map(From::from)
     }
 
     /// Get a pointer to function or static variable by symbol name.
     ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
-    /// terminated `symbol` may avoid a string allocation in some cases.
+    /// The `symbol` may not contain any null bytes, with an exception of last byte. Providing a
+    /// null terminated `symbol` may help to avoid an allocation.
     ///
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
     /// most likely invalid.
     ///
     /// # Safety
     ///
-    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
-    /// undefined.
+    /// Users of this API must specify the correct type of the function or variable loaded. Using a
+    /// `Symbol` with a wrong type is undefined.
     ///
     /// # Platform-specific behaviour
     ///
-    /// Implementation of thread local variables is extremely platform specific and uses of these
-    /// variables that work on e.g. Linux may have unintended behaviour on other POSIX systems or
-    /// Windows.
+    /// Implementation of thread local variables is extremely platform specific and uses of such
+    /// variables that work on e.g. Linux may have unintended behaviour on other targets.
     ///
     /// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
-    /// as FreeBSD), this function will unconditionally return an error the underlying `dlsym` call
-    /// returns a null pointer. There are rare situations where `dlsym` returns a genuine null
+    /// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
+    /// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
     /// pointer without it being an error. If loading a null pointer is something you care about,
     /// consider using the [`os::unix::Library::get_singlethreaded`] call.
     ///
@@ -162,14 +159,18 @@
     ///
     /// ```no_run
     /// # use ::libloading::Library;
-    /// let lib = Library::new("/path/to/awesome.module").unwrap();
+    /// let lib = unsafe {
+    ///     Library::new("/path/to/awesome.module").unwrap()
+    /// };
     /// ```
     ///
     /// Loading and using a function looks like this:
     ///
     /// ```no_run
     /// # use ::libloading::{Library, Symbol};
-    /// # let lib = Library::new("/path/to/awesome.module").unwrap();
+    /// # let lib = unsafe {
+    /// #     Library::new("/path/to/awesome.module").unwrap()
+    /// # };
     /// unsafe {
     ///     let awesome_function: Symbol<unsafe extern fn(f64) -> f64> =
     ///         lib.get(b"awesome_function\0").unwrap();
@@ -181,7 +182,7 @@
     ///
     /// ```no_run
     /// # use ::libloading::{Library, Symbol};
-    /// # let lib = Library::new("/path/to/awesome.module").unwrap();
+    /// # let lib = unsafe { Library::new("/path/to/awesome.module").unwrap() };
     /// unsafe {
     ///     let awesome_variable: Symbol<*mut f64> = lib.get(b"awesome_variable\0").unwrap();
     ///     **awesome_variable = 42.0;
@@ -230,15 +231,12 @@
 /// Symbol from a library.
 ///
 /// This type is a safeguard against using dynamically loaded symbols after a `Library` is
-/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
+/// unloaded. Primary method to create an instance of a `Symbol` is via [`Library::get`].
 ///
-/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
-/// function or variable directly, without taking care to “extract” function or variable manually
-/// most of the time.
+/// The `Deref` trait implementation allows use of `Symbol` as if it was a function or variable
+/// itself, without taking care to “extract” function or variable manually most of the time.
 ///
-/// See [`Library::get`] for details.
-///
-/// [`Library::get`]: ./struct.Library.html#method.get
+/// [`Library::get`]: Library::get
 pub struct Symbol<'lib, T: 'lib> {
     inner: imp::Symbol<T>,
     pd: marker::PhantomData<&'lib T>
@@ -257,8 +255,8 @@
     ///
     /// ```no_run
     /// # use ::libloading::{Library, Symbol};
-    /// let lib = Library::new("/path/to/awesome.module").unwrap();
     /// unsafe {
+    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
     ///     let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
     ///     let symbol = symbol.into_raw();
     /// }
@@ -270,25 +268,25 @@
     /// Wrap the `os::platform::Symbol` into this safe wrapper.
     ///
     /// Note that, in order to create association between the symbol and the library this symbol
-    /// came from, this function requires reference to the library provided.
+    /// came from, this function requires a reference to the library.
     ///
     /// # Safety
     ///
-    /// It is invalid to provide a reference to any other value other than the library the `sym`
-    /// was loaded from. Doing so invalidates any lifetime guarantees.
+    /// The `library` reference must be exactly the library `sym` was loaded from.
     ///
     /// # Examples
     ///
     /// ```no_run
     /// # use ::libloading::{Library, Symbol};
-    /// let lib = Library::new("/path/to/awesome.module").unwrap();
     /// unsafe {
+    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
     ///     let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
     ///     let symbol = symbol.into_raw();
     ///     let symbol = Symbol::from_raw(symbol, &lib);
     /// }
     /// ```
-    pub unsafe fn from_raw<L>(sym: imp::Symbol<T>, _: &'lib L) -> Symbol<'lib, T> {
+    pub unsafe fn from_raw<L>(sym: imp::Symbol<T>, library: &'lib L) -> Symbol<'lib, T> {
+        let _ = library; // ignore here for documentation purposes.
         Symbol {
             inner: sym,
             pd: marker::PhantomData
@@ -303,8 +301,8 @@
     ///
     /// ```no_run
     /// # use ::libloading::{Library, Symbol};
-    /// let lib = Library::new("/path/to/awesome.module").unwrap();
     /// unsafe {
+    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
     ///     let symbol: Symbol<Option<*mut u32>> = lib.get(b"symbol\0").unwrap();
     ///     let symbol: Symbol<*mut u32> = symbol.lift_option().expect("static is not null");
     /// }
@@ -356,7 +354,9 @@
 /// use libloading::{Library, library_filename};
 /// // Will attempt to load `libLLVM.so` on Linux, `libLLVM.dylib` on macOS and `LLVM.dll` on
 /// // Windows.
-/// let library = Library::new(library_filename("LLVM"));
+/// let library = unsafe {
+///     Library::new(library_filename("LLVM"))
+/// };
 /// ```
 pub fn library_filename<S: AsRef<OsStr>>(name: S) -> OsString {
     let name = name.as_ref();
diff --git a/src/os/mod.rs b/src/os/mod.rs
index 40361c5..c03ebc1 100644
--- a/src/os/mod.rs
+++ b/src/os/mod.rs
@@ -1,4 +1,4 @@
-//! Unsafe, platform specific bindings to dynamic library loading facilities.
+//! Unsafe but flexible platform specific bindings to dynamic library loading facilities.
 //!
 //! These modules expose more extensive, powerful, less principled bindings to the dynamic
 //! library loading facilities. Use of these bindings come at the cost of less (in most cases,
diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs
index 83657a9..45e8230 100644
--- a/src/os/unix/mod.rs
+++ b/src/os/unix/mod.rs
@@ -103,15 +103,26 @@
     /// a file. Otherwise, platform-specific algorithms are employed to find a library with a
     /// matching file name.
     ///
-    /// This is equivalent to [`Library::open`]`(filename, RTLD_NOW)`.
+    /// This is equivalent to <code>[Library::open](filename, [RTLD_LAZY] | [RTLD_LOCAL])</code>.
     ///
     /// [path separator]: std::path::MAIN_SEPARATOR
+    ///
+    /// # Safety
+    ///
+    /// When a library is loaded initialization routines contained within the library are executed.
+    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
+    /// to be sound.
+    ///
+    /// Additionally, the callers of this function must also ensure that execution of the
+    /// termination routines contained within the library is safe as well. These routines may be
+    /// executed when the library is unloaded.
     #[inline]
-    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
-        Library::open(Some(filename), RTLD_NOW)
+    pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
+        Library::open(Some(filename), RTLD_LAZY | RTLD_LOCAL)
     }
 
-    /// Eagerly load the `Library` representing the current executable.
+    /// Load the `Library` representing the current executable.
     ///
     /// [`Library::get`] calls of the returned `Library` will look for symbols in following
     /// locations in order:
@@ -124,12 +135,16 @@
     /// Note that behaviour of `Library` loaded with this method is different from
     /// Libraries loaded with [`os::windows::Library::this`].
     ///
-    /// This is equivalent to [`Library::open`]`(None, RTLD_NOW)`.
+    /// This is equivalent to <code>[Library::open](None, [RTLD_LAZY] | [RTLD_LOCAL])</code>.
     ///
     /// [`os::windows::Library::this`]: crate::os::windows::Library::this
     #[inline]
     pub fn this() -> Library {
-        Library::open(None::<&OsStr>, RTLD_NOW).expect("this should never fail")
+        unsafe {
+            // SAFE: this does not load any new shared library images, no danger in it executing
+            // initializer routines.
+            Library::open(None::<&OsStr>, RTLD_LAZY | RTLD_LOCAL).expect("this should never fail")
+        }
     }
 
     /// Find and load an executable object file (shared library).
@@ -138,22 +153,30 @@
     /// when the `filename` is `None`. Otherwise see [`Library::new`].
     ///
     /// Corresponds to `dlopen(filename, flags)`.
-    pub fn open<P>(filename: Option<P>, flags: raw::c_int) -> Result<Library, crate::Error>
+    ///
+    /// # Safety
+    ///
+    /// When a library is loaded initialization routines contained within the library are executed.
+    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
+    /// to be sound.
+    ///
+    /// Additionally, the callers of this function must also ensure that execution of the
+    /// termination routines contained within the library is safe as well. These routines may be
+    /// executed when the library is unloaded.
+    pub unsafe fn open<P>(filename: Option<P>, flags: raw::c_int) -> Result<Library, crate::Error>
     where P: AsRef<OsStr> {
         let filename = match filename {
             None => None,
             Some(ref f) => Some(cstr_cow_from_bytes(f.as_ref().as_bytes())?),
         };
         with_dlerror(|desc| crate::Error::DlOpen { desc }, move || {
-            let result = unsafe {
-                let r = dlopen(match filename {
-                    None => ptr::null(),
-                    Some(ref f) => f.as_ptr()
-                }, flags);
-                // ensure filename lives until dlopen completes
-                drop(filename);
-                r
-            };
+            let result = dlopen(match filename {
+                None => ptr::null(),
+                Some(ref f) => f.as_ptr()
+            }, flags);
+            // ensure filename lives until dlopen completes
+            drop(filename);
             if result.is_null() {
                 None
             } else {
@@ -196,28 +219,27 @@
 
     /// Get a pointer to function or static variable by symbol name.
     ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
-    /// terminated `symbol` may avoid an allocation in some cases.
+    /// The `symbol` may not contain any null bytes, with an exception of last byte. Providing a
+    /// null terminated `symbol` may help to avoid an allocation.
     ///
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
     /// most likely invalid.
     ///
     /// # Safety
     ///
-    /// This function does not validate the type `T`. It is up to the user of this function to
-    /// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
-    /// defined behaviour.
+    /// Users of this API must specify the correct type of the function or variable loaded. Using a
+    /// `Symbol` with a wrong type is undefined.
     ///
     /// # Platform-specific behaviour
     ///
-    /// Implementation of thread local variables is extremely platform specific and uses of these
-    /// variables that work on e.g. Linux may have unintended behaviour on other POSIX systems.
+    /// Implementation of thread local variables is extremely platform specific and uses of such
+    /// variables that work on e.g. Linux may have unintended behaviour on other targets.
     ///
     /// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
     /// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
     /// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
-    /// pointer without it being an error. If loading a symbol at null address is something you
-    /// care about, consider using the [`Library::get_singlethreaded`] call.
+    /// pointer without it being an error. If loading a null pointer is something you care about,
+    /// consider using the [`Library::get_singlethreaded`] call.
     #[inline(always)]
     pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
         extern crate cfg_if;
@@ -243,17 +265,16 @@
 
     /// Get a pointer to function or static variable by symbol name.
     ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
-    /// terminated `symbol` may avoid a string allocation in some cases.
+    /// The `symbol` may not contain any null bytes, with an exception of last byte. Providing a
+    /// null terminated `symbol` may help to avoid an allocation.
     ///
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
     /// most likely invalid.
     ///
     /// # Safety
     ///
-    /// This function does not validate the type `T`. It is up to the user of this function to
-    /// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
-    /// defined behaviour.
+    /// Users of this API must specify the correct type of the function or variable loaded. Using a
+    /// `Symbol` with a wrong type is undefined.
     ///
     /// It is up to the user of this library to ensure that no other calls to an MT-unsafe
     /// implementation of `dlerror` occur during execution of this function. Failing that, the
@@ -261,8 +282,8 @@
     ///
     /// # Platform-specific behaviour
     ///
-    /// Implementation of thread local variables is extremely platform specific and uses of these
-    /// variables that work on e.g. Linux may have unintended behaviour on other POSIX systems.
+    /// Implementation of thread local variables is extremely platform specific and uses of such
+    /// variables that work on e.g. Linux may have unintended behaviour on other targets.
     #[inline(always)]
     pub unsafe fn get_singlethreaded<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
         self.get_impl(symbol, || Ok(Symbol {
@@ -300,7 +321,8 @@
     /// what library was opened or other platform specifics.
     ///
     /// You only need to call this if you are interested in handling any errors that may arise when
-    /// library is unloaded. Otherwise this will be done when `Library` is dropped.
+    /// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
+    /// library and ignore the errors were they arise.
     ///
     /// The underlying data structures may still get leaked if an error does occur.
     pub fn close(self) -> Result<(), crate::Error> {
@@ -312,7 +334,7 @@
             }
         }).map_err(|e| e.unwrap_or(crate::Error::DlCloseUnknown));
         // While the library is not free'd yet in case of an error, there is no reason to try
-        // dropping it again, because all that will do is try calling `FreeLibrary` again. only
+        // dropping it again, because all that will do is try calling `dlclose` again. only
         // this time it would ignore the return result, which we already seen failing…
         std::mem::forget(self);
         result
diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs
index da1b5c9..7e28527 100644
--- a/src/os/windows/mod.rs
+++ b/src/os/windows/mod.rs
@@ -28,7 +28,6 @@
     extern crate winapi;
     pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
     pub(super) use self::winapi::shared::ntdef::WCHAR;
-    pub(super) use self::winapi::shared::winerror;
     pub(super) use self::winapi::um::{errhandlingapi, libloaderapi};
     pub(super) use std::os::windows::ffi::{OsStrExt, OsStringExt};
     pub(super) const SEM_FAILCE: DWORD = 1;
@@ -55,7 +54,6 @@
 use util::{ensure_compatible_types, cstr_cow_from_bytes};
 use std::ffi::{OsStr, OsString};
 use std::{fmt, io, marker, mem, ptr};
-use std::sync::atomic::{AtomicBool, Ordering};
 
 /// A platform-specific counterpart of the cross-platform [`Library`](crate::Library).
 pub struct Library(HMODULE);
@@ -88,15 +86,26 @@
     /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
     /// trailing `.` to the `filename`.
     ///
-    /// This is equivalent to [`Library::load_with_flags`]`(filename, 0)`.
+    /// This is equivalent to <code>[Library::load_with_flags](filename, 0)</code>.
     ///
     /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw#remarks
+    ///
+    /// # Safety
+    ///
+    /// When a library is loaded initialization routines contained within the library are executed.
+    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
+    /// to be sound.
+    ///
+    /// Additionally, the callers of this function must also ensure that execution of the
+    /// termination routines contained within the library is safe as well. These routines may be
+    /// executed when the library is unloaded.
     #[inline]
-    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
+    pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
         Library::load_with_flags(filename, 0)
     }
 
-    /// Load the `Library` representing the original program executable.
+    /// Get the `Library` representing the original program executable.
     ///
     /// Note that behaviour of `Library` loaded with this method is different from
     /// Libraries loaded with [`os::unix::Library::this`]. For more information refer to [MSDN].
@@ -119,6 +128,45 @@
         }
     }
 
+    /// Get 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
@@ -127,22 +175,32 @@
     /// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags)`.
     ///
     /// [flags]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters
-    pub fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
+    ///
+    /// # Safety
+    ///
+    /// When a library is loaded initialization routines contained within the library are executed.
+    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
+    /// to be sound.
+    ///
+    /// Additionally, the callers of this function must also ensure that execution of the
+    /// termination routines contained within the library is safe as well. These routines may be
+    /// executed when the library is unloaded.
+    pub unsafe fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
         let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
         let _guard = ErrorModeGuard::new();
 
-        let ret = with_get_last_error(|source| crate::Error::LoadLibraryW { source }, || {
+        let ret = with_get_last_error(|source| crate::Error::LoadLibraryExW { 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 handle = unsafe {
-                libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags)
-            };
+            let handle =
+                libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags);
             if handle.is_null()  {
                 None
             } else {
                 Some(Library(handle))
             }
-        }).map_err(|e| e.unwrap_or(crate::Error::LoadLibraryWUnknown));
+        }).map_err(|e| e.unwrap_or(crate::Error::LoadLibraryExWUnknown));
         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
@@ -158,9 +216,8 @@
     ///
     /// # Safety
     ///
-    /// This function does not validate the type `T`. It is up to the user of this function to
-    /// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
-    /// definied behaviour.
+    /// Users of this API must specify the correct type of the function or variable loaded. Using a
+    /// `Symbol` with a wrong type is undefined.
     pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
         ensure_compatible_types::<T, FARPROC>()?;
         let symbol = cstr_cow_from_bytes(symbol)?;
@@ -181,8 +238,8 @@
     ///
     /// # Safety
     ///
-    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
-    /// undefined.
+    /// Users of this API must specify the correct type of the function or variable loaded. Using a
+    /// `Symbol` with a wrong type is undefined.
     pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
         ensure_compatible_types::<T, FARPROC>()?;
         with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
@@ -210,8 +267,9 @@
     ///
     /// # Safety
     ///
-    /// The handle shall be a result of a successful call of `LoadLibraryW` or a
-    /// handle previously returned by the `Library::into_raw` call.
+    /// The handle shall be a result of a successful call of `LoadLibraryA`, `LoadLibraryW`,
+    /// `LoadLibraryExW`, `LoadLibraryExA` or a handle previously returned by the
+    /// `Library::into_raw` call.
     pub unsafe fn from_raw(handle: HMODULE) -> Library {
         Library(handle)
     }
@@ -322,49 +380,23 @@
     }
 }
 
-static USE_ERRORMODE: AtomicBool = AtomicBool::new(false);
 struct ErrorModeGuard(DWORD);
 
 impl ErrorModeGuard {
     #[allow(clippy::if_same_then_else)]
     fn new() -> Option<ErrorModeGuard> {
         unsafe {
-            if !USE_ERRORMODE.load(Ordering::Acquire) {
-                let mut previous_mode = 0;
-                let success = errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) != 0;
-                if !success && errhandlingapi::GetLastError() == winerror::ERROR_CALL_NOT_IMPLEMENTED {
-                    USE_ERRORMODE.store(true, Ordering::Release);
-                } else if !success {
-                    // SetThreadErrorMode failed with some other error? How in the world is it
-                    // possible for what is essentially a simple variable swap to fail?
-                    // For now we just ignore the error -- the worst that can happen here is
-                    // the previous mode staying on and user seeing a dialog error on older Windows
-                    // machines.
-                    return None;
-                } else if previous_mode == SEM_FAILCE {
-                    return None;
-                } else {
-                    return Some(ErrorModeGuard(previous_mode));
-                }
-            }
-            match errhandlingapi::SetErrorMode(SEM_FAILCE) {
-                SEM_FAILCE => {
-                    // This is important to reduce racy-ness when this library is used on multiple
-                    // threads. In particular this helps with following race condition:
-                    //
-                    // T1: SetErrorMode(SEM_FAILCE)
-                    // T2: SetErrorMode(SEM_FAILCE)
-                    // T1: SetErrorMode(old_mode) # not SEM_FAILCE
-                    // T2: SetErrorMode(SEM_FAILCE) # restores to SEM_FAILCE on drop
-                    //
-                    // This is still somewhat racy in a sense that T1 might restore the error
-                    // mode before T2 finishes loading the library, but that is less of a
-                    // concern – it will only end up in end user seeing a dialog.
-                    //
-                    // Also, SetErrorMode itself is probably not an atomic operation.
-                    None
-                }
-                a => Some(ErrorModeGuard(a))
+            let mut previous_mode = 0;
+            if errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) == 0 {
+                // How in the world is it possible for what is essentially a simple variable swap
+                // to fail?  For now we just ignore the error -- the worst that can happen here is
+                // the previous mode staying on and user seeing a dialog error on older Windows
+                // machines.
+                None
+            } else if previous_mode == SEM_FAILCE {
+                None
+            } else {
+                Some(ErrorModeGuard(previous_mode))
             }
         }
     }
@@ -373,11 +405,7 @@
 impl Drop for ErrorModeGuard {
     fn drop(&mut self) {
         unsafe {
-            if !USE_ERRORMODE.load(Ordering::Relaxed) {
-                errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
-            } else {
-                errhandlingapi::SetErrorMode(self.0);
-            }
+            errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
         }
     }
 }
diff --git a/tests/functions.rs b/tests/functions.rs
index e899344..eef41e6 100644
--- a/tests/functions.rs
+++ b/tests/functions.rs
@@ -31,8 +31,8 @@
 #[test]
 fn test_id_u32() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         let f: Symbol<unsafe extern fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap();
         assert_eq!(42, f(42));
     }
@@ -50,8 +50,8 @@
 #[test]
 fn test_id_struct() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
         assert_eq!(S { a: 1, b: 2, c: 3, d: 4 }, f(S { a: 1, b: 2, c: 3, d: 4 }));
     }
@@ -60,8 +60,8 @@
 #[test]
 fn test_0_no_0() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
         let f2: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
         assert_eq!(*f, *f2);
@@ -70,14 +70,16 @@
 
 #[test]
 fn wrong_name_fails() {
-    Library::new("target/this_location_is_definitely_non existent:^~").err().unwrap();
+    unsafe {
+        Library::new("target/this_location_is_definitely_non existent:^~").err().unwrap();
+    }
 }
 
 #[test]
 fn missing_symbol_fails() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap();
         lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap();
     }
@@ -86,8 +88,8 @@
 #[test]
 fn interior_null_fails() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
         lib.get::<*mut ()>(b"test\0_does_not_exist\0").err().unwrap();
     }
@@ -96,8 +98,8 @@
 #[test]
 fn test_incompatible_type() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         assert!(match lib.get::<()>(b"test_identity_u32\0") {
            Err(libloading::Error::IncompatibleSize) => true,
            _ => false,
@@ -111,8 +113,8 @@
     unsafe fn get<'a, T>(l: &'a Library, _: T) -> Result<Symbol<'a, T>, libloading::Error> {
         l.get::<T>(b"test_identity_u32\0")
     }
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         assert!(match get(&lib, test_incompatible_type_named_fn) {
            Err(libloading::Error::IncompatibleSize) => true,
            _ => false,
@@ -123,8 +125,8 @@
 #[test]
 fn test_static_u32() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
         **var = 42;
         let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_static_u32\0").unwrap();
@@ -135,8 +137,8 @@
 #[test]
 fn test_static_ptr() {
     make_helpers();
-    let lib = Library::new(LIBPATH).unwrap();
     unsafe {
+        let lib = Library::new(LIBPATH).unwrap();
         let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
         **var = *var as *mut _;
         let works: Symbol<unsafe extern fn() -> bool> =
@@ -174,13 +176,12 @@
 fn library_this_get() {
     use libloading::os::unix::Library;
     make_helpers();
-    let _lib = Library::new(LIBPATH).unwrap();
-    let this = Library::this();
     // SAFE: functions are never called
     unsafe {
+        let _lib = Library::new(LIBPATH).unwrap();
+        let this = Library::this();
         // Library we loaded in `_lib` (should be RTLD_LOCAL).
-        // FIXME: inconsistent behaviour between macos and other posix systems
-        // assert!(this.get::<unsafe extern "C" fn()>(b"test_identity_u32").is_err());
+        assert!(this.get::<unsafe extern "C" fn()>(b"test_identity_u32").is_err());
         // Something obscure from libc...
         assert!(this.get::<unsafe extern "C" fn()>(b"freopen").is_ok());
     }
@@ -191,10 +192,11 @@
 fn library_this() {
     use libloading::os::windows::Library;
     make_helpers();
-    let _lib = Library::new(LIBPATH).unwrap();
-    let this = Library::this().expect("this library");
-    // SAFE: functions are never called
     unsafe {
+        // SAFE: well-known library without initializers is loaded.
+        let _lib = Library::new(LIBPATH).unwrap();
+        let this = Library::this().expect("this library");
+        // SAFE: functions are never called.
         // Library we loaded in `_lib`.
         assert!(this.get::<unsafe extern "C" fn()>(b"test_identity_u32").is_err());
         // Something "obscure" from kernel32...
@@ -209,11 +211,9 @@
     use winapi::shared::minwindef::DWORD;
     use libloading::os::windows::{Library, Symbol};
 
-    let lib = Library::new("kernel32.dll").unwrap();
-    let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
-        lib.get(b"GetLastError").unwrap()
-    };
     unsafe {
+        let lib = Library::new("kernel32.dll").unwrap();
+        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError").unwrap();
         errhandlingapi::SetLastError(42);
         assert_eq!(errhandlingapi::GetLastError(), gle())
     }
@@ -226,12 +226,31 @@
     use winapi::shared::minwindef::DWORD;
     use libloading::os::windows::{Library, Symbol};
 
-    let lib = Library::new("kernel32.dll").unwrap();
-    let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
-        lib.get(b"GetLastError\0").unwrap()
-    };
     unsafe {
+        let lib = Library::new("kernel32.dll").unwrap();
+        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError\0").unwrap();
         errhandlingapi::SetLastError(42);
         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,
+    });
+
+    unsafe {
+        let _lib = Library::new(LIBPATH).unwrap();
+        // Loaded now.
+        assert!(Library::open_already_loaded(LIBPATH).is_ok());
+    }
+}
diff --git a/tests/windows.rs b/tests/windows.rs
index 343aaa1..b4aad4a 100644
--- a/tests/windows.rs
+++ b/tests/windows.rs
@@ -15,12 +15,16 @@
 
 #[cfg(target_arch="x86")]
 fn load_ordinal_lib() -> Library {
-    Library::new("tests/nagisa32.dll").expect("nagisa32.dll")
+    unsafe {
+        Library::new("tests/nagisa32.dll").expect("nagisa32.dll")
+    }
 }
 
 #[cfg(target_arch="x86_64")]
 fn load_ordinal_lib() -> Library {
-    Library::new("tests/nagisa64.dll").expect("nagisa64.dll")
+    unsafe {
+        Library::new("tests/nagisa64.dll").expect("nagisa64.dll")
+    }
 }
 
 #[cfg(any(target_arch="x86", target_arch="x86_64"))]
@@ -47,10 +51,14 @@
 
 #[test]
 fn test_new_kernel23() {
-    Library::new("kernel23").err().unwrap();
+    unsafe {
+        Library::new("kernel23").err().unwrap();
+    }
 }
 
 #[test]
 fn test_new_kernel32_no_ext() {
-    Library::new("kernel32").unwrap();
+    unsafe {
+        Library::new("kernel32").unwrap();
+    }
 }