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