use std::{
convert::TryInto,
io::{Error, ErrorKind},
};
use crate::SMBiosData;
use super::WinSMBiosData;
mod ffi {
#[link(name = "kernel32")]
extern "system" {
pub fn GetSystemFirmwareTable(
firmware_table_provider_signature: u32,
firmware_table_id: u32,
firmware_table_buffer_ptr: *mut u8,
buffer_size: u32,
) -> u32;
}
}
pub fn load_windows_smbios_data() -> Result<WinSMBiosData, Error> {
match raw_smbios_from_device() {
Ok(raw) => WinSMBiosData::new(raw),
Err(e) => Err(e),
}
}
pub fn table_load_from_device() -> Result<SMBiosData, Error> {
Ok(load_windows_smbios_data()?.smbios_data)
}
pub fn raw_smbios_from_device() -> Result<Vec<u8>, Error> {
use std::ptr;
unsafe {
const MEMORY_ERROR_MESSAGE: &'static str = "Memory error";
const RAW_SMBIOS_SIGNATURE: u32 = 1381190978u32; let max_i32: u32 = i32::MAX.try_into().unwrap();
let firmware_table_buffer_ptr: *mut u8 = ptr::null_mut();
let buffer_size =
ffi::GetSystemFirmwareTable(RAW_SMBIOS_SIGNATURE, 0, firmware_table_buffer_ptr, 0);
if buffer_size == 0 || buffer_size > max_i32 {
return Err(Error::new(ErrorKind::Other, MEMORY_ERROR_MESSAGE));
}
let mut firmware_table_buffer = Vec::with_capacity(buffer_size as usize);
let firmware_table_buffer_ptr = firmware_table_buffer.as_mut_ptr();
let buffer_size = ffi::GetSystemFirmwareTable(
RAW_SMBIOS_SIGNATURE,
0,
firmware_table_buffer_ptr,
buffer_size,
);
if buffer_size == 0 {
Err(Error::last_os_error())
}
else if buffer_size > max_i32 {
Err(Error::new(ErrorKind::Other, MEMORY_ERROR_MESSAGE))
} else {
firmware_table_buffer.set_len(buffer_size as usize);
Ok(firmware_table_buffer)
}
}
}