mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-25 06:40:03 +00:00
Remove dep windows-dll and replace it with manual loading (#1658)
Fixed #1629 Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
48039ed739
commit
fe2a4d8b0c
3 changed files with 100 additions and 171 deletions
|
@ -10,9 +10,15 @@ edition = "2021"
|
|||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.35.0", features = ["rt", "process", "sync"], default-features = false }
|
||||
tokio = { version = "1.35.0", features = [
|
||||
"rt",
|
||||
"process",
|
||||
"sync",
|
||||
], default-features = false }
|
||||
tracing = { version = "0.1.39", optional = true }
|
||||
tracing-subscriber = { version = "0.3.17", features = ["fmt"], default-features = false, optional = true }
|
||||
tracing-subscriber = { version = "0.3.17", features = [
|
||||
"fmt",
|
||||
], default-features = false, optional = true }
|
||||
cfg-if = "1.0.0"
|
||||
guess_host_triple = "0.1.3"
|
||||
|
||||
|
@ -21,8 +27,12 @@ tracing = ["dep:tracing"]
|
|||
cli-logging = ["tracing", "dep:tracing-subscriber"]
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
windows-sys = { version = "0.52.0", features = ["Win32_System_Threading", "Win32_System_SystemInformation", "Win32_Foundation"] }
|
||||
windows-dll = { version = "0.4.1", features = ["windows"], default-features = false }
|
||||
windows-sys = { version = "0.52.0", features = [
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_SystemInformation",
|
||||
"Win32_Foundation",
|
||||
"Win32_System_LibraryLoader",
|
||||
] }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.35.0", features = ["macros"], default-features = false }
|
||||
|
|
|
@ -1,44 +1,72 @@
|
|||
use std::mem;
|
||||
use windows_dll::dll;
|
||||
use windows_sys::{
|
||||
core::HRESULT,
|
||||
Win32::System::{
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{FreeLibrary, HMODULE, S_OK},
|
||||
System::{
|
||||
LibraryLoader::{GetProcAddress, LoadLibraryA},
|
||||
SystemInformation::{
|
||||
IMAGE_FILE_MACHINE, IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_ARM,
|
||||
IMAGE_FILE_MACHINE_ARM64, IMAGE_FILE_MACHINE_I386,
|
||||
},
|
||||
Threading::{UserEnabled, Wow64Container, MACHINE_ATTRIBUTES},
|
||||
Threading::{GetMachineTypeAttributes, UserEnabled, Wow64Container, MACHINE_ATTRIBUTES},
|
||||
},
|
||||
};
|
||||
|
||||
#[dll("Kernel32")]
|
||||
extern "system" {
|
||||
#[allow(non_snake_case)]
|
||||
#[fallible]
|
||||
fn GetMachineTypeAttributes(
|
||||
machine: IMAGE_FILE_MACHINE,
|
||||
machine_attributes: *mut MACHINE_ATTRIBUTES,
|
||||
) -> HRESULT;
|
||||
struct LibraryHandle(HMODULE);
|
||||
|
||||
impl LibraryHandle {
|
||||
fn new(name: &[u8]) -> Option<Self> {
|
||||
let handle = unsafe { LoadLibraryA(name.as_ptr() as _) };
|
||||
(handle != 0).then(|| Self(handle))
|
||||
}
|
||||
|
||||
/// Get a function pointer to a function in the library.
|
||||
/// # SAFETY
|
||||
///
|
||||
/// The caller must ensure that the function signature matches the actual function.
|
||||
/// The easiest way to do this is to add an entry to windows_sys_no_link.list and use the
|
||||
/// generated function for `func_signature`.
|
||||
///
|
||||
/// The function returned cannot be used after the handle is dropped.
|
||||
unsafe fn get_proc_address<F>(&self, name: &[u8]) -> Option<F> {
|
||||
let symbol = unsafe { GetProcAddress(self.0, name.as_ptr() as _) };
|
||||
symbol.map(|symbol| unsafe { mem::transmute_copy(&symbol) })
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LibraryHandle {
|
||||
fn drop(&mut self) {
|
||||
unsafe { FreeLibrary(self.0) };
|
||||
}
|
||||
}
|
||||
|
||||
type GetMachineTypeAttributesFuncType =
|
||||
unsafe extern "system" fn(u16, *mut MACHINE_ATTRIBUTES) -> i32;
|
||||
const _: () = {
|
||||
// Ensure that our hand-written signature matches the actual function signature.
|
||||
// We can't use `GetMachineTypeAttributes` outside of a const scope otherwise we'll end up statically linking to
|
||||
// it, which will fail to load on older versions of Windows.
|
||||
let _: GetMachineTypeAttributesFuncType = GetMachineTypeAttributes;
|
||||
};
|
||||
|
||||
fn is_arch_supported_inner(arch: IMAGE_FILE_MACHINE) -> Option<bool> {
|
||||
// GetMachineTypeAttributes is only available on Win11 22000+, so dynamically load it.
|
||||
let kernel32 = LibraryHandle::new(b"kernel32.dll\0")?;
|
||||
// SAFETY: GetMachineTypeAttributesFuncType is checked to match the real function signature.
|
||||
let get_machine_type_attributes = unsafe {
|
||||
kernel32.get_proc_address::<GetMachineTypeAttributesFuncType>(b"GetMachineTypeAttributes\0")
|
||||
}?;
|
||||
|
||||
let mut machine_attributes = mem::MaybeUninit::uninit();
|
||||
if unsafe { get_machine_type_attributes(arch, machine_attributes.as_mut_ptr()) } == S_OK {
|
||||
let machine_attributes = unsafe { machine_attributes.assume_init() };
|
||||
Some((machine_attributes & (Wow64Container | UserEnabled)) != 0)
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_arch_supported(arch: IMAGE_FILE_MACHINE) -> bool {
|
||||
let mut machine_attributes = mem::MaybeUninit::uninit();
|
||||
|
||||
// SAFETY: GetMachineTypeAttributes takes type IMAGE_FILE_MACHINE
|
||||
// plus it takes a pointer to machine_attributes which is only
|
||||
// written to.
|
||||
match unsafe { GetMachineTypeAttributes(arch, machine_attributes.as_mut_ptr()) } {
|
||||
Ok(0) => {
|
||||
// SAFETY: Symbol GetMachineTypeAttributes exists and calls to it
|
||||
// succceeds.
|
||||
//
|
||||
// Thus, machine_attributes is initialized.
|
||||
let machine_attributes = unsafe { machine_attributes.assume_init() };
|
||||
|
||||
(machine_attributes & (Wow64Container | UserEnabled)) != 0
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
is_arch_supported_inner(arch).unwrap_or(false)
|
||||
}
|
||||
|
||||
pub(super) fn detect_alternative_targets(target: &str) -> impl Iterator<Item = String> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue