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:
whitequark
2020-05-21 18:56:20 +00:00
committed by GitHub
parent 68f0d2f6d0
commit e5635f4bc9

View File

@@ -6,7 +6,9 @@
use std::ffi::c_void;
use std::os::raw::c_ulong;
use std::os::windows::prelude::RawHandle;
use std::sync::atomic::{AtomicUsize, Ordering};
use winapi::shared::ntdef::NTSTATUS;
use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
use winapi::um::winnt::ACCESS_MASK;
#[repr(C)]
@@ -49,17 +51,40 @@ impl Default for IO_STATUS_BLOCK {
}
}
#[link(name = "ntdll")]
extern "C" {
macro_rules! ntdll_import {
{ 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
pub(crate) fn NtQueryInformationFile(
fn NtQueryInformationFile(
FileHandle: RawHandle,
IoStatusBlock: *mut IO_STATUS_BLOCK,
FileInformation: *mut c_void,
Length: c_ulong,
FileInformationClass: FILE_INFORMATION_CLASS,
FileInformationClass: FILE_INFORMATION_CLASS
) -> NTSTATUS;
// 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;
}