Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove libntdll.a from sources #146

Merged
merged 4 commits into from
Feb 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ readme = "README.md"
keywords = ["os", "os_type", "os_version", "os_info"]
categories = ["os"]
license = "MIT"
build = "build.rs"
edition = "2018"

[badges]
Expand Down
30 changes: 0 additions & 30 deletions build.rs

This file was deleted.

Binary file removed lib/i686/libntdll.a
Binary file not shown.
Binary file removed lib/x86_64/libntdll.a
Binary file not shown.
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ mod version;

pub use bitness::Bitness;
pub use info::Info;
#[cfg(not(windows))]
use matcher::Matcher;
pub use os_type::Type;
pub use version::{Version, VersionType};

Expand Down
2 changes: 1 addition & 1 deletion src/linux/file_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{fs::File, io::Read, path::Path};

use log::{trace, warn};

use crate::{Bitness, Info, Matcher, Type, Version};
use crate::{matcher::Matcher, Bitness, Info, Type, Version};

pub fn get() -> Option<Info> {
retrieve(&DISTRIBUTIONS)
Expand Down
2 changes: 1 addition & 1 deletion src/linux/lsb_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::process::Command;

use log::{trace, warn};

use crate::{Bitness, Info, Matcher, Type, Version};
use crate::{matcher::Matcher, Bitness, Info, Type, Version};

pub fn get() -> Option<Info> {
let release = retrieve()?;
Expand Down
2 changes: 1 addition & 1 deletion src/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::process::Command;

use log::trace;

use crate::{Bitness, Info, Matcher, Type, Version};
use crate::{matcher::Matcher, Bitness, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("macos::current_platform is called");
Expand Down
32 changes: 17 additions & 15 deletions src/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,29 @@ pub(crate) enum Matcher {
AllTrimmed,

/// After finding the `prefix` followed by one or more spaces, returns the following word.
#[cfg(not(target_os = "macos"))]
PrefixedWord { prefix: &'static str },

/// Similar to `PrefixedWord`, but only if the word is a valid version.
PrefixedVersion { prefix: &'static str },
}

impl Matcher {
/// Find the match on the input `string`.
pub(crate) fn find(&self, string: &str) -> Option<String> {
match *self {
Self::AllTrimmed => Some(string.trim().to_string()),
#[cfg(not(target_os = "macos"))]
Self::PrefixedWord { prefix } => {
find_prefixed_word(string, prefix).map(|v| v.to_owned())
}
Self::PrefixedVersion { prefix } => find_prefixed_word(string, prefix)
.filter(|&v| is_valid_version(v))
.map(|v| v.to_owned()),
}
}
}

fn find_prefixed_word<'a>(string: &'a str, prefix: &str) -> Option<&'a str> {
if let Some(prefix_start) = string.find(prefix) {
// Ignore prefix and leading whitespace
Expand All @@ -31,18 +48,3 @@ fn find_prefixed_word<'a>(string: &'a str, prefix: &str) -> Option<&'a str> {
fn is_valid_version(word: &str) -> bool {
!word.starts_with('.') && !word.ends_with('.')
}

impl Matcher {
/// Find the match on the input `string`.
pub(crate) fn find(&self, string: &str) -> Option<String> {
match *self {
Self::AllTrimmed => Some(string.trim().to_string()),
Self::PrefixedWord { prefix } => {
find_prefixed_word(string, prefix).map(|v| v.to_owned())
}
Self::PrefixedVersion { prefix } => find_prefixed_word(string, prefix)
.filter(|&v| is_valid_version(v))
.map(|v| v.to_owned()),
}
}
}
96 changes: 73 additions & 23 deletions src/windows/winapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
use std::mem;

use winapi::{
shared::{minwindef::DWORD, ntdef::NTSTATUS, ntstatus::STATUS_SUCCESS},
shared::{
minwindef::{DWORD, FARPROC},
ntdef::{LPCSTR, NTSTATUS},
ntstatus::STATUS_SUCCESS,
},
um::{
libloaderapi::{GetModuleHandleA, GetProcAddress},
sysinfoapi::{GetSystemInfo, SYSTEM_INFO},
winnt::{PROCESSOR_ARCHITECTURE_AMD64, VER_NT_WORKSTATION, VER_SUITE_WH_SERVER},
winuser::{GetSystemMetrics, SM_SERVERR2},
Expand All @@ -23,11 +28,6 @@ type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXA;
#[cfg(not(target_arch = "x86"))]
type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXW;

#[link(name = "ntdll")]
extern "system" {
pub fn RtlGetVersion(lpVersionInformation: &mut OSVERSIONINFOEX) -> NTSTATUS;
}

pub fn get() -> Info {
Info::new(Type::Windows, version(), bitness())
}
Expand Down Expand Up @@ -55,28 +55,18 @@ fn bitness() -> Bitness {
use winapi::{
shared::{
minwindef::{BOOL, FALSE, PBOOL},
ntdef::{HANDLE, LPCSTR},
},
um::{
libloaderapi::{GetModuleHandleA, GetProcAddress},
processthreadsapi::GetCurrentProcess,
ntdef::HANDLE,
},
um::processthreadsapi::GetCurrentProcess,
};

// IsWow64Process is not available on all supported versions of Windows. Use GetModuleHandle to
// get a handle to the DLL that contains the function and GetProcAddress to get a pointer to the
// function if available.
let kernel = unsafe { GetModuleHandleA(b"kernel32\0".as_ptr() as LPCSTR) };
if kernel.is_null() {
log::error!("GetModuleHandleA failed");
return Bitness::Unknown;
}

let is_wow_64 = unsafe { GetProcAddress(kernel, b"IsWow64Process\0".as_ptr() as LPCSTR) };
if is_wow_64.is_null() {
log::error!("GetProcAddress failed");
return Bitness::Unknown;
}
let is_wow_64 = match get_proc_address(b"kernel32\0", b"IsWow64Process\0") {
None => return Bitness::Unknown,
Some(val) => val,
};

type IsWow64 = unsafe extern "system" fn(HANDLE, PBOOL) -> BOOL;
let is_wow_64: IsWow64 = unsafe { mem::transmute(is_wow_64) };
Expand All @@ -97,10 +87,18 @@ fn bitness() -> Bitness {
// Calls the Win32 API function RtlGetVersion to get the OS version information:
// https://msdn.microsoft.com/en-us/library/mt723418(v=vs.85).aspx
fn version_info() -> Option<OSVERSIONINFOEX> {
let rtl_get_version = match get_proc_address(b"ntdll\0", b"RtlGetVersion\0") {
None => return None,
Some(val) => val,
};

type RtlGetVersion = unsafe extern "system" fn(&mut OSVERSIONINFOEX) -> NTSTATUS;
let rtl_get_version: RtlGetVersion = unsafe { mem::transmute(rtl_get_version) };

let mut info: OSVERSIONINFOEX = unsafe { mem::zeroed() };
info.dwOSVersionInfoSize = mem::size_of::<OSVERSIONINFOEX>() as DWORD;

if unsafe { RtlGetVersion(&mut info) } == STATUS_SUCCESS {
if unsafe { rtl_get_version(&mut info) } == STATUS_SUCCESS {
Some(info)
} else {
None
Expand Down Expand Up @@ -151,6 +149,28 @@ fn edition(version_info: &OSVERSIONINFOEX) -> Option<String> {
.map(str::to_string)
}

fn get_proc_address(module: &[u8], proc: &[u8]) -> Option<FARPROC> {
assert!(
*module.last().expect("Empty module name") == 0,
"Module name should be zero-terminated"
);
assert!(
*proc.last().expect("Empty procedure name") == 0,
"Procedure name should be zero-terminated"
);

let handle = unsafe { GetModuleHandleA(module.as_ptr() as LPCSTR) };
if handle.is_null() {
log::error!(
"GetModuleHandleA({}) failed",
String::from_utf8_lossy(module)
);
return None;
}

unsafe { Some(GetProcAddress(handle, proc.as_ptr() as LPCSTR)) }
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -206,4 +226,34 @@ mod tests {
let b = bitness();
assert_ne!(b, Bitness::Unknown);
}

#[test]
#[should_panic(expected = "Empty module name")]
fn empty_module_name() {
get_proc_address(b"", b"RtlGetVersion\0");
}

#[test]
#[should_panic(expected = "Module name should be zero-terminated")]
fn non_zero_terminated_module_name() {
get_proc_address(b"ntdll", b"RtlGetVersion\0");
}

#[test]
#[should_panic(expected = "Empty procedure name")]
fn empty_proc_name() {
get_proc_address(b"ntdll\0", b"");
}

#[test]
#[should_panic(expected = "Procedure name should be zero-terminated")]
fn non_zero_terminated_proc_name() {
get_proc_address(b"ntdll\0", b"RtlGetVersion");
}

#[test]
fn proc_address() {
let address = get_proc_address(b"ntdll\0", b"RtlGetVersion\0");
assert!(address.is_some());
}
}