1#[cfg(feature = "disk")]
4use windows::Win32::Storage::FileSystem::{
5 CreateFileW, FILE_ACCESS_RIGHTS, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
6};
7
8#[cfg(any(feature = "user", feature = "system"))]
9pub(crate) unsafe fn to_utf8_str(p: windows::core::PWSTR) -> String {
10 if p.is_null() {
11 return String::new();
12 }
13
14 unsafe {
15 p.to_string().unwrap_or_else(|_e| {
16 sysinfo_debug!("Failed to convert to UTF-16 string: {}", _e);
17 String::new()
18 })
19 }
20}
21
22cfg_if! {
23 if #[cfg(any(feature = "disk", feature = "system"))] {
24 use windows::Win32::Foundation::{CloseHandle, HANDLE};
25 use std::ops::Deref;
26
27 pub(crate) struct HandleWrapper(pub(crate) HANDLE);
28
29 impl HandleWrapper {
30 #[cfg(feature = "system")]
31 pub(crate) fn new(handle: HANDLE) -> Option<Self> {
32 if handle.is_invalid() {
33 None
34 } else {
35 Some(Self(handle))
36 }
37 }
38
39 #[cfg(feature = "disk")]
40 pub(crate) unsafe fn new_from_file(
41 drive_name: &[u16],
42 open_rights: FILE_ACCESS_RIGHTS,
43 ) -> Option<Self> {
44 let lpfilename = windows::core::PCWSTR::from_raw(drive_name.as_ptr());
45 let handle = unsafe { CreateFileW(
46 lpfilename,
47 open_rights.0,
48 FILE_SHARE_READ | FILE_SHARE_WRITE,
49 None,
50 OPEN_EXISTING,
51 Default::default(),
52 Some(HANDLE::default()),
53 ) }
54 .ok()?;
55 if handle.is_invalid() {
56 sysinfo_debug!(
57 "Expected handle to {:?} to be valid",
58 String::from_utf16_lossy(drive_name)
59 );
60 None
61 } else {
62 Some(Self(handle))
63 }
64 }
65 }
66
67 impl Deref for HandleWrapper {
68 type Target = HANDLE;
69
70 fn deref(&self) -> &Self::Target {
71 &self.0
72 }
73 }
74
75 impl Drop for HandleWrapper {
76 fn drop(&mut self) {
77 let _err = unsafe { CloseHandle(self.0) };
78 }
79 }
80 }
81}
82
83cfg_if! {
84 if #[cfg(feature = "system")] {
85 use windows::Win32::System::SystemInformation::{FIRMWARE_TABLE_PROVIDER, GetSystemFirmwareTable};
86 use super::ffi::SMBIOSType;
87
88 pub(crate) fn get_smbios_table() -> Option<Vec<u8>> {
90 const PROVIDER: FIRMWARE_TABLE_PROVIDER = FIRMWARE_TABLE_PROVIDER(u32::from_be_bytes(*b"RSMB"));
91
92 let size = unsafe { GetSystemFirmwareTable(PROVIDER, 0, None) };
93 if size == 0 {
94 return None;
95 }
96
97 let mut buffer = vec![0u8; size as usize];
98
99 let res = unsafe { GetSystemFirmwareTable(PROVIDER, 0, Some(&mut buffer)) };
100 if res == 0 {
101 return None;
102 }
103
104 Some(buffer)
105 }
106
107 pub(crate) fn parse_smbios<T: SMBIOSType>(table: &[u8], number: u8) -> Option<(T, Vec<&str>)> {
112 let mut i = 0;
121 while i + 1 < table.len() {
122 if table[i] == number {
123 break;
124 }
125 i += table[i + 1] as usize;
126 while i < table.len() {
128 if table[i] == 0 && table[i + 1] == 0 {
129 i += 2;
130 break;
131 }
132 i += 1;
133 }
134 }
135
136 let info: T = unsafe { std::ptr::read_unaligned(table[i..].as_ptr() as *const _) };
137
138 let values = table[(i + info.length() as usize)..]
141 .split(|&b| b == 0)
142 .filter_map(|s| std::str::from_utf8(s).ok())
143 .take_while(|s| !s.is_empty())
144 .collect();
145
146 Some((info, values))
147 }
148 }
149}