winx: do not link directly to ntdll.dll. (#1739)
The documentation for RtlNtStatusToDosError explicitly tells to call it via GetProcAddress. The documentation for NtQueryInformationFile does not, but similar considerations apply because there is normally no import library for ntdll. The main reason to use GetProcAddress though is because MinGW does include an import library for ntdll, this import library contains a definition of setjmp, and because of the way rustc orders linker arguments, this definition of setjmp conflicts with and gets picked over the one in msvcrt. Using setjmp from ntdll is undesirable as it is an undocumented API and it is missing from wine, making it harder to develop wasmtime using a cross-compiler. Fixes #1738.
This commit is contained in:
@@ -6,7 +6,9 @@
|
|||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::os::raw::c_ulong;
|
use std::os::raw::c_ulong;
|
||||||
use std::os::windows::prelude::RawHandle;
|
use std::os::windows::prelude::RawHandle;
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use winapi::shared::ntdef::NTSTATUS;
|
use winapi::shared::ntdef::NTSTATUS;
|
||||||
|
use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
|
||||||
use winapi::um::winnt::ACCESS_MASK;
|
use winapi::um::winnt::ACCESS_MASK;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -49,17 +51,40 @@ impl Default for IO_STATUS_BLOCK {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link(name = "ntdll")]
|
macro_rules! ntdll_import {
|
||||||
extern "C" {
|
{ fn $name:ident($($arg:ident: $argty:ty),*) -> $retty:ty; $($tail:tt)* } => {
|
||||||
|
pub(crate) unsafe fn $name($($arg: $argty),*) -> $retty {
|
||||||
|
static ADDRESS: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
let address = match ADDRESS.load(Ordering::Relaxed) {
|
||||||
|
0 => {
|
||||||
|
let ntdll = GetModuleHandleA("ntdll\0".as_ptr() as *const i8);
|
||||||
|
let address = GetProcAddress(
|
||||||
|
ntdll,
|
||||||
|
concat!(stringify!($name), "\0").as_ptr() as *const i8,
|
||||||
|
) as usize;
|
||||||
|
assert!(address != 0);
|
||||||
|
ADDRESS.store(address, Ordering::Relaxed);
|
||||||
|
address
|
||||||
|
}
|
||||||
|
address => address
|
||||||
|
};
|
||||||
|
let func: unsafe fn($($argty),*) -> $retty = std::mem::transmute(address);
|
||||||
|
func($($arg),*)
|
||||||
|
}
|
||||||
|
ntdll_import! { $($tail)* }
|
||||||
|
};
|
||||||
|
{} => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ntdll_import! {
|
||||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntqueryinformationfile
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntqueryinformationfile
|
||||||
pub(crate) fn NtQueryInformationFile(
|
fn NtQueryInformationFile(
|
||||||
FileHandle: RawHandle,
|
FileHandle: RawHandle,
|
||||||
IoStatusBlock: *mut IO_STATUS_BLOCK,
|
IoStatusBlock: *mut IO_STATUS_BLOCK,
|
||||||
FileInformation: *mut c_void,
|
FileInformation: *mut c_void,
|
||||||
Length: c_ulong,
|
Length: c_ulong,
|
||||||
FileInformationClass: FILE_INFORMATION_CLASS,
|
FileInformationClass: FILE_INFORMATION_CLASS
|
||||||
) -> NTSTATUS;
|
) -> NTSTATUS;
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-rtlntstatustodoserror
|
// https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-rtlntstatustodoserror
|
||||||
pub(crate) fn RtlNtStatusToDosError(status: NTSTATUS) -> c_ulong;
|
fn RtlNtStatusToDosError(status: NTSTATUS) -> c_ulong;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user