1 // A hack for docs.rs to build documentation that has both windows and linux documentation in the
2 // same rustdoc build visible.
3 #[cfg(all(docsrs, not(windows)))]
4 mod windows_imports {
5 pub(super) enum WORD {}
6 pub(super) struct DWORD;
7 pub(super) enum HMODULE {}
8 pub(super) enum FARPROC {}
9
10 pub(super) mod consts {
11 use super::DWORD;
12 pub(crate) const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = DWORD;
13 pub(crate) const LOAD_LIBRARY_AS_DATAFILE: DWORD = DWORD;
14 pub(crate) const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = DWORD;
15 pub(crate) const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = DWORD;
16 pub(crate) const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = DWORD;
17 pub(crate) const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = DWORD;
18 pub(crate) const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = DWORD;
19 pub(crate) const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = DWORD;
20 pub(crate) const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = DWORD;
21 pub(crate) const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = DWORD;
22 pub(crate) const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = DWORD;
23 pub(crate) const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = DWORD;
24 }
25 }
26 #[cfg(any(not(docsrs), windows))]
27 mod windows_imports {
28 extern crate winapi;
29 pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
30 pub(super) use self::winapi::shared::ntdef::WCHAR;
31 pub(super) use self::winapi::shared::winerror;
32 pub(super) use self::winapi::um::{errhandlingapi, libloaderapi};
33 pub(super) use std::os::windows::ffi::{OsStrExt, OsStringExt};
34 pub(super) const SEM_FAILCE: DWORD = 1;
35
36 pub(super) mod consts {
37 pub(crate) use super::winapi::um::libloaderapi::{
38 LOAD_IGNORE_CODE_AUTHZ_LEVEL,
39 LOAD_LIBRARY_AS_DATAFILE,
40 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE,
41 LOAD_LIBRARY_AS_IMAGE_RESOURCE,
42 LOAD_LIBRARY_SEARCH_APPLICATION_DIR,
43 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
44 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR,
45 LOAD_LIBRARY_SEARCH_SYSTEM32,
46 LOAD_LIBRARY_SEARCH_USER_DIRS,
47 LOAD_WITH_ALTERED_SEARCH_PATH,
48 LOAD_LIBRARY_REQUIRE_SIGNED_TARGET,
49 LOAD_LIBRARY_SAFE_CURRENT_DIRS,
50 };
51 }
52 }
53
54 use self::windows_imports::*;
55 use util::{ensure_compatible_types, cstr_cow_from_bytes};
56 use std::ffi::{OsStr, OsString};
57 use std::{fmt, io, marker, mem, ptr};
58 use std::sync::atomic::{AtomicBool, Ordering};
59
60 /// A platform-specific counterpart of the cross-platform [`Library`](crate::Library).
61 pub struct Library(HMODULE);
62
63 unsafe impl Send for Library {}
64 // Now, this is sort-of-tricky. MSDN documentation does not really make any claims as to safety of
65 // the Win32 APIs. Sadly, whomever I asked, even current and former Microsoft employees, couldn’t
66 // say for sure, whether the Win32 APIs used to implement `Library` are thread-safe or not.
67 //
68 // My investigation ended up with a question about thread-safety properties of the API involved
69 // being sent to an internal (to MS) general question mailing-list. The conclusion of the mail is
70 // as such:
71 //
72 // * Nobody inside MS (at least out of all the people who have seen the question) knows for
73 // sure either;
74 // * However, the general consensus between MS developers is that one can rely on the API being
75 // thread-safe. In case it is not thread-safe it should be considered a bug on the Windows
76 // part. (NB: bugs filled at https://connect.microsoft.com/ against Windows Server)
77 unsafe impl Sync for Library {}
78
79 impl Library {
80 /// Find and load a module.
81 ///
82 /// If the `filename` specifies a full path, the function only searches that path for the
83 /// module. Otherwise, if the `filename` specifies a relative path or a module name without a
84 /// path, the function uses a windows-specific search strategy to find the module; for more
85 /// information, see the [Remarks on MSDN][msdn].
86 ///
87 /// If the `filename` specifies a library filename without path and with extension omitted,
88 /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
89 /// trailing `.` to the `filename`.
90 ///
91 /// This is equivalent to [`Library::load_with_flags`]`(filename, 0)`.
92 ///
93 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw#remarks
94 #[inline]
new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error>95 pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
96 Library::load_with_flags(filename, 0)
97 }
98
99 /// Load the `Library` representing the original program executable.
100 ///
101 /// Note that behaviour of `Library` loaded with this method is different from
102 /// Libraries loaded with [`os::unix::Library::this`]. For more information refer to [MSDN].
103 ///
104 /// Corresponds to `GetModuleHandleExW(0, NULL, _)`.
105 ///
106 /// [`os::unix::Library::this`]: crate::os::unix::Library::this
107 /// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
this() -> Result<Library, crate::Error>108 pub fn this() -> Result<Library, crate::Error> {
109 unsafe {
110 let mut handle: HMODULE = std::ptr::null_mut();
111 with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
112 let result = libloaderapi::GetModuleHandleExW(0, std::ptr::null_mut(), &mut handle);
113 if result == 0 {
114 None
115 } else {
116 Some(Library(handle))
117 }
118 }).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown))
119 }
120 }
121
122 /// Load a module that is already loaded by the program.
123 ///
124 /// This function returns a `Library` corresponding to a module with the given name that is
125 /// already mapped into the address space of the process. If the module isn't found an error is
126 /// returned.
127 ///
128 /// If the `filename` does not include a full path and there are multiple different loaded
129 /// modules corresponding to the `filename`, it is impossible to predict which module handle
130 /// will be returned. For more information refer to [MSDN].
131 ///
132 /// If the `filename` specifies a library filename without path and with extension omitted,
133 /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
134 /// trailing `.` to the `filename`.
135 ///
136 /// This is equivalent to `GetModuleHandleExW(0, filename, _)`.
137 ///
138 /// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
open_already_loaded<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error>139 pub fn open_already_loaded<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
140 let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
141
142 let ret = unsafe {
143 let mut handle: HMODULE = std::ptr::null_mut();
144 with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
145 // Make sure no winapi calls as a result of drop happen inside this closure, because
146 // otherwise that might change the return value of the GetLastError.
147 let result = libloaderapi::GetModuleHandleExW(0, wide_filename.as_ptr(), &mut handle);
148 if result == 0 {
149 None
150 } else {
151 Some(Library(handle))
152 }
153 }).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown))
154 };
155
156 drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
157 // inside the closure by mistake. See comment inside the closure.
158 ret
159 }
160
161 /// Find and load a module, additionally adjusting behaviour with flags.
162 ///
163 /// See [`Library::new`] for documentation on handling of the `filename` argument. See the
164 /// [flag table on MSDN][flags] for information on applicable values for the `flags` argument.
165 ///
166 /// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags)`.
167 ///
168 /// [flags]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters
load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error>169 pub fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
170 let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
171 let _guard = ErrorModeGuard::new();
172
173 let ret = with_get_last_error(|source| crate::Error::LoadLibraryW { source }, || {
174 // Make sure no winapi calls as a result of drop happen inside this closure, because
175 // otherwise that might change the return value of the GetLastError.
176 let handle = unsafe {
177 libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags)
178 };
179 if handle.is_null() {
180 None
181 } else {
182 Some(Library(handle))
183 }
184 }).map_err(|e| e.unwrap_or(crate::Error::LoadLibraryWUnknown));
185 drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
186 // inside the closure by mistake. See comment inside the closure.
187 ret
188 }
189
190 /// Get a pointer to function or static variable by symbol name.
191 ///
192 /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
193 /// terminated `symbol` may avoid a string allocation in some cases.
194 ///
195 /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
196 /// most likely invalid.
197 ///
198 /// # Safety
199 ///
200 /// This function does not validate the type `T`. It is up to the user of this function to
201 /// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
202 /// definied behaviour.
get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error>203 pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
204 ensure_compatible_types::<T, FARPROC>()?;
205 let symbol = cstr_cow_from_bytes(symbol)?;
206 with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
207 let symbol = libloaderapi::GetProcAddress(self.0, symbol.as_ptr());
208 if symbol.is_null() {
209 None
210 } else {
211 Some(Symbol {
212 pointer: symbol,
213 pd: marker::PhantomData
214 })
215 }
216 }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
217 }
218
219 /// Get a pointer to function or static variable by ordinal number.
220 ///
221 /// # Safety
222 ///
223 /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
224 /// undefined.
get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error>225 pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
226 ensure_compatible_types::<T, FARPROC>()?;
227 with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
228 let ordinal = ordinal as usize as *mut _;
229 let symbol = libloaderapi::GetProcAddress(self.0, ordinal);
230 if symbol.is_null() {
231 None
232 } else {
233 Some(Symbol {
234 pointer: symbol,
235 pd: marker::PhantomData
236 })
237 }
238 }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
239 }
240
241 /// Convert the `Library` to a raw handle.
into_raw(self) -> HMODULE242 pub fn into_raw(self) -> HMODULE {
243 let handle = self.0;
244 mem::forget(self);
245 handle
246 }
247
248 /// Convert a raw handle to a `Library`.
249 ///
250 /// # Safety
251 ///
252 /// The handle shall be a result of a successful call of `LoadLibraryW` or a
253 /// handle previously returned by the `Library::into_raw` call.
from_raw(handle: HMODULE) -> Library254 pub unsafe fn from_raw(handle: HMODULE) -> Library {
255 Library(handle)
256 }
257
258 /// Unload the library.
259 ///
260 /// You only need to call this if you are interested in handling any errors that may arise when
261 /// library is unloaded. Otherwise this will be done when `Library` is dropped.
262 ///
263 /// The underlying data structures may still get leaked if an error does occur.
close(self) -> Result<(), crate::Error>264 pub fn close(self) -> Result<(), crate::Error> {
265 let result = with_get_last_error(|source| crate::Error::FreeLibrary { source }, || {
266 if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
267 None
268 } else {
269 Some(())
270 }
271 }).map_err(|e| e.unwrap_or(crate::Error::FreeLibraryUnknown));
272 // While the library is not free'd yet in case of an error, there is no reason to try
273 // dropping it again, because all that will do is try calling `FreeLibrary` again. only
274 // this time it would ignore the return result, which we already seen failing…
275 std::mem::forget(self);
276 result
277 }
278 }
279
280 impl Drop for Library {
drop(&mut self)281 fn drop(&mut self) {
282 unsafe { libloaderapi::FreeLibrary(self.0); }
283 }
284 }
285
286 impl fmt::Debug for Library {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result287 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288 unsafe {
289 // FIXME: use Maybeuninit::uninit_array when stable
290 let mut buf =
291 mem::MaybeUninit::<[mem::MaybeUninit::<WCHAR>; 1024]>::uninit().assume_init();
292 let len = libloaderapi::GetModuleFileNameW(self.0,
293 (&mut buf[..]).as_mut_ptr().cast(), 1024) as usize;
294 if len == 0 {
295 f.write_str(&format!("Library@{:p}", self.0))
296 } else {
297 let string: OsString = OsString::from_wide(
298 // FIXME: use Maybeuninit::slice_get_ref when stable
299 &*(&buf[..len] as *const [_] as *const [WCHAR])
300 );
301 f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
302 }
303 }
304 }
305 }
306
307 /// Symbol from a library.
308 ///
309 /// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
310 /// `Symbol` does not outlive `Library` it comes from.
311 pub struct Symbol<T> {
312 pointer: FARPROC,
313 pd: marker::PhantomData<T>
314 }
315
316 impl<T> Symbol<T> {
317 /// Convert the loaded Symbol into a handle.
into_raw(self) -> FARPROC318 pub fn into_raw(self) -> FARPROC {
319 let pointer = self.pointer;
320 mem::forget(self);
321 pointer
322 }
323 }
324
325 impl<T> Symbol<Option<T>> {
326 /// Lift Option out of the symbol.
lift_option(self) -> Option<Symbol<T>>327 pub fn lift_option(self) -> Option<Symbol<T>> {
328 if self.pointer.is_null() {
329 None
330 } else {
331 Some(Symbol {
332 pointer: self.pointer,
333 pd: marker::PhantomData,
334 })
335 }
336 }
337 }
338
339 unsafe impl<T: Send> Send for Symbol<T> {}
340 unsafe impl<T: Sync> Sync for Symbol<T> {}
341
342 impl<T> Clone for Symbol<T> {
clone(&self) -> Symbol<T>343 fn clone(&self) -> Symbol<T> {
344 Symbol { ..*self }
345 }
346 }
347
348 impl<T> ::std::ops::Deref for Symbol<T> {
349 type Target = T;
deref(&self) -> &T350 fn deref(&self) -> &T {
351 unsafe {
352 // Additional reference level for a dereference on `deref` return value.
353 &*(&self.pointer as *const *mut _ as *const T)
354 }
355 }
356 }
357
358 impl<T> fmt::Debug for Symbol<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result359 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
360 f.write_str(&format!("Symbol@{:p}", self.pointer))
361 }
362 }
363
364 static USE_ERRORMODE: AtomicBool = AtomicBool::new(false);
365 struct ErrorModeGuard(DWORD);
366
367 impl ErrorModeGuard {
368 #[allow(clippy::if_same_then_else)]
new() -> Option<ErrorModeGuard>369 fn new() -> Option<ErrorModeGuard> {
370 unsafe {
371 if !USE_ERRORMODE.load(Ordering::Acquire) {
372 let mut previous_mode = 0;
373 let success = errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) != 0;
374 if !success && errhandlingapi::GetLastError() == winerror::ERROR_CALL_NOT_IMPLEMENTED {
375 USE_ERRORMODE.store(true, Ordering::Release);
376 } else if !success {
377 // SetThreadErrorMode failed with some other error? How in the world is it
378 // possible for what is essentially a simple variable swap to fail?
379 // For now we just ignore the error -- the worst that can happen here is
380 // the previous mode staying on and user seeing a dialog error on older Windows
381 // machines.
382 return None;
383 } else if previous_mode == SEM_FAILCE {
384 return None;
385 } else {
386 return Some(ErrorModeGuard(previous_mode));
387 }
388 }
389 match errhandlingapi::SetErrorMode(SEM_FAILCE) {
390 SEM_FAILCE => {
391 // This is important to reduce racy-ness when this library is used on multiple
392 // threads. In particular this helps with following race condition:
393 //
394 // T1: SetErrorMode(SEM_FAILCE)
395 // T2: SetErrorMode(SEM_FAILCE)
396 // T1: SetErrorMode(old_mode) # not SEM_FAILCE
397 // T2: SetErrorMode(SEM_FAILCE) # restores to SEM_FAILCE on drop
398 //
399 // This is still somewhat racy in a sense that T1 might restore the error
400 // mode before T2 finishes loading the library, but that is less of a
401 // concern – it will only end up in end user seeing a dialog.
402 //
403 // Also, SetErrorMode itself is probably not an atomic operation.
404 None
405 }
406 a => Some(ErrorModeGuard(a))
407 }
408 }
409 }
410 }
411
412 impl Drop for ErrorModeGuard {
drop(&mut self)413 fn drop(&mut self) {
414 unsafe {
415 if !USE_ERRORMODE.load(Ordering::Relaxed) {
416 errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
417 } else {
418 errhandlingapi::SetErrorMode(self.0);
419 }
420 }
421 }
422 }
423
with_get_last_error<T, F>(wrap: fn(crate::error::WindowsError) -> crate::Error, closure: F) -> Result<T, Option<crate::Error>> where F: FnOnce() -> Option<T>424 fn with_get_last_error<T, F>(wrap: fn(crate::error::WindowsError) -> crate::Error, closure: F)
425 -> Result<T, Option<crate::Error>>
426 where F: FnOnce() -> Option<T> {
427 closure().ok_or_else(|| {
428 let error = unsafe { errhandlingapi::GetLastError() };
429 if error == 0 {
430 None
431 } else {
432 Some(wrap(crate::error::WindowsError(io::Error::from_raw_os_error(error as i32))))
433 }
434 })
435 }
436
437 /// Do not check AppLocker rules or apply Software Restriction Policies for the DLL.
438 ///
439 /// This action applies only to the DLL being loaded and not to its dependencies. This value is
440 /// recommended for use in setup programs that must run extracted DLLs during installation.
441 ///
442 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
443 pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = consts::LOAD_IGNORE_CODE_AUTHZ_LEVEL;
444
445 /// Map the file into the calling process’ virtual address space as if it were a data file.
446 ///
447 /// Nothing is done to execute or prepare to execute the mapped file. Therefore, you cannot call
448 /// functions like [`Library::get`] with this DLL. Using this value causes writes to read-only
449 /// memory to raise an access violation. Use this flag when you want to load a DLL only to extract
450 /// messages or resources from it.
451 ///
452 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
453 pub const LOAD_LIBRARY_AS_DATAFILE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE;
454
455 /// Map the file into the calling process’ virtual address space as if it were a data file.
456 ///
457 /// Similar to [`LOAD_LIBRARY_AS_DATAFILE`], except that the DLL file is opened with exclusive
458 /// write access for the calling process. Other processes cannot open the DLL file for write access
459 /// while it is in use. However, the DLL can still be opened by other processes.
460 ///
461 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
462 pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE;
463
464 /// Map the file into the process’ virtual address space as an image file.
465 ///
466 /// The loader does not load the static imports or perform the other usual initialization steps.
467 /// Use this flag when you want to load a DLL only to extract messages or resources from it.
468 ///
469 /// Unless the application depends on the file having the in-memory layout of an image, this value
470 /// should be used with either [`LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`] or
471 /// [`LOAD_LIBRARY_AS_DATAFILE`].
472 ///
473 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
474 pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = consts::LOAD_LIBRARY_AS_IMAGE_RESOURCE;
475
476 /// Search application's installation directory for the DLL and its dependencies.
477 ///
478 /// Directories in the standard search path are not searched. This value cannot be combined with
479 /// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
480 ///
481 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
482 pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
483
484 /// Search default directories when looking for the DLL and its dependencies.
485 ///
486 /// This value is a combination of [`LOAD_LIBRARY_SEARCH_APPLICATION_DIR`],
487 /// [`LOAD_LIBRARY_SEARCH_SYSTEM32`], and [`LOAD_LIBRARY_SEARCH_USER_DIRS`]. Directories in the
488 /// standard search path are not searched. This value cannot be combined with
489 /// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
490 ///
491 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
492 pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
493
494 /// Directory that contains the DLL is temporarily added to the beginning of the list of
495 /// directories that are searched for the DLL’s dependencies.
496 ///
497 /// Directories in the standard search path are not searched.
498 ///
499 /// The `filename` parameter must specify a fully qualified path. This value cannot be combined
500 /// with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
501 ///
502 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
503 pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
504
505 /// Search `%windows%\system32` for the DLL and its dependencies.
506 ///
507 /// Directories in the standard search path are not searched. This value cannot be combined with
508 /// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
509 ///
510 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
511 pub const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = consts::LOAD_LIBRARY_SEARCH_SYSTEM32;
512
513 /// Directories added using the `AddDllDirectory` or the `SetDllDirectory` function are searched
514 /// for the DLL and its dependencies.
515 ///
516 /// If more than one directory has been added, the order in which the directories are searched is
517 /// unspecified. Directories in the standard search path are not searched. This value cannot be
518 /// combined with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
519 ///
520 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
521 pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_USER_DIRS;
522
523 /// If `filename specifies an absolute path, the system uses the alternate file search strategy
524 /// discussed in the [Remarks section] to find associated executable modules that the specified
525 /// module causes to be loaded.
526 ///
527 /// If this value is used and `filename` specifies a relative path, the behavior is undefined.
528 ///
529 /// If this value is not used, or if `filename` does not specify a path, the system uses the
530 /// standard search strategy discussed in the [Remarks section] to find associated executable
531 /// modules that the specified module causes to be loaded.
532 ///
533 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
534 ///
535 /// [Remarks]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#remarks
536 pub const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = consts::LOAD_WITH_ALTERED_SEARCH_PATH;
537
538 /// Specifies that the digital signature of the binary image must be checked at load time.
539 ///
540 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
541 pub const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = consts::LOAD_LIBRARY_REQUIRE_SIGNED_TARGET;
542
543 /// Allow loading a DLL for execution from the current directory only if it is under a directory in
544 /// the Safe load list.
545 ///
546 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
547 pub const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = consts::LOAD_LIBRARY_SAFE_CURRENT_DIRS;
548