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 found = false;
121 let mut i = 0;
122 while i + 1 < table.len() {
123 if table[i] == number {
124 found = true;
125 break;
126 }
127 i += table[i + 1] as usize;
128 while i < table.len() {
130 if table[i] == 0 && table[i + 1] == 0 {
131 i += 2;
132 break;
133 }
134 i += 1;
135 }
136 }
137
138 if !found {
139 return None;
140 }
141
142 let data = table.get(i..)?;
143 if data.len() < std::mem::size_of::<T>() {
144 return None;
145 }
146
147 let info: T = unsafe { std::ptr::read_unaligned(data.as_ptr() as *const _) };
150
151 let values = table.get((i + info.length() as usize)..)
154 .unwrap_or_default()
155 .split(|&b| b == 0)
156 .filter_map(|s| std::str::from_utf8(s).ok())
157 .take_while(|s| !s.is_empty())
158 .collect();
159
160 Some((info, values))
161 }
162 }
163}