summaryrefslogtreecommitdiffstats
path: root/vendor/sysinfo/src/windows/disk.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sysinfo/src/windows/disk.rs')
-rw-r--r--vendor/sysinfo/src/windows/disk.rs249
1 files changed, 249 insertions, 0 deletions
diff --git a/vendor/sysinfo/src/windows/disk.rs b/vendor/sysinfo/src/windows/disk.rs
new file mode 100644
index 000000000..ae393afb2
--- /dev/null
+++ b/vendor/sysinfo/src/windows/disk.rs
@@ -0,0 +1,249 @@
+// Take a look at the license at the top of the repository in the LICENSE file.
+
+use crate::{DiskExt, DiskType};
+
+use std::ffi::{OsStr, OsString};
+use std::mem::size_of;
+use std::path::Path;
+
+use winapi::ctypes::c_void;
+use winapi::shared::minwindef::{DWORD, MAX_PATH};
+use winapi::um::fileapi::{
+ CreateFileW, GetDiskFreeSpaceExW, GetDriveTypeW, GetLogicalDrives, GetVolumeInformationW,
+ OPEN_EXISTING,
+};
+use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
+use winapi::um::ioapiset::DeviceIoControl;
+use winapi::um::winbase::{DRIVE_FIXED, DRIVE_REMOVABLE};
+use winapi::um::winioctl::{
+ DEVICE_TRIM_DESCRIPTOR, IOCTL_STORAGE_QUERY_PROPERTY, STORAGE_PROPERTY_QUERY,
+};
+use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, HANDLE, ULARGE_INTEGER};
+
+#[doc = include_str!("../../md_doc/disk.md")]
+pub struct Disk {
+ type_: DiskType,
+ name: OsString,
+ file_system: Vec<u8>,
+ mount_point: Vec<u16>,
+ s_mount_point: String,
+ total_space: u64,
+ available_space: u64,
+ is_removable: bool,
+}
+
+impl DiskExt for Disk {
+ fn type_(&self) -> DiskType {
+ self.type_
+ }
+
+ fn name(&self) -> &OsStr {
+ &self.name
+ }
+
+ fn file_system(&self) -> &[u8] {
+ &self.file_system
+ }
+
+ fn mount_point(&self) -> &Path {
+ Path::new(&self.s_mount_point)
+ }
+
+ fn total_space(&self) -> u64 {
+ self.total_space
+ }
+
+ fn available_space(&self) -> u64 {
+ self.available_space
+ }
+
+ fn is_removable(&self) -> bool {
+ self.is_removable
+ }
+
+ fn refresh(&mut self) -> bool {
+ if self.total_space != 0 {
+ unsafe {
+ let mut tmp: ULARGE_INTEGER = std::mem::zeroed();
+ if GetDiskFreeSpaceExW(
+ self.mount_point.as_ptr(),
+ std::ptr::null_mut(),
+ std::ptr::null_mut(),
+ &mut tmp,
+ ) != 0
+ {
+ self.available_space = *tmp.QuadPart();
+ return true;
+ }
+ }
+ }
+ false
+ }
+}
+
+struct HandleWrapper(HANDLE);
+
+impl HandleWrapper {
+ unsafe fn new(drive_name: &[u16], open_rights: DWORD) -> Option<Self> {
+ let handle = CreateFileW(
+ drive_name.as_ptr(),
+ open_rights,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ std::ptr::null_mut(),
+ OPEN_EXISTING,
+ 0,
+ std::ptr::null_mut(),
+ );
+ if handle == INVALID_HANDLE_VALUE {
+ CloseHandle(handle);
+ None
+ } else {
+ Some(Self(handle))
+ }
+ }
+}
+
+impl Drop for HandleWrapper {
+ fn drop(&mut self) {
+ unsafe {
+ CloseHandle(self.0);
+ }
+ }
+}
+
+unsafe fn get_drive_size(mount_point: &[u16]) -> Option<(u64, u64)> {
+ let mut total_size: ULARGE_INTEGER = std::mem::zeroed();
+ let mut available_space: ULARGE_INTEGER = std::mem::zeroed();
+ if GetDiskFreeSpaceExW(
+ mount_point.as_ptr(),
+ std::ptr::null_mut(),
+ &mut total_size,
+ &mut available_space,
+ ) != 0
+ {
+ Some((
+ *total_size.QuadPart() as u64,
+ *available_space.QuadPart() as u64,
+ ))
+ } else {
+ None
+ }
+}
+
+pub(crate) unsafe fn get_disks() -> Vec<Disk> {
+ let drives = GetLogicalDrives();
+ if drives == 0 {
+ return Vec::new();
+ }
+
+ #[cfg(feature = "multithread")]
+ use rayon::iter::ParallelIterator;
+
+ crate::utils::into_iter(0..DWORD::BITS)
+ .filter_map(|x| {
+ if (drives >> x) & 1 == 0 {
+ return None;
+ }
+ let mount_point = [b'A' as u16 + x as u16, b':' as u16, b'\\' as u16, 0];
+
+ let drive_type = GetDriveTypeW(mount_point.as_ptr());
+
+ let is_removable = drive_type == DRIVE_REMOVABLE;
+
+ if drive_type != DRIVE_FIXED && drive_type != DRIVE_REMOVABLE {
+ return None;
+ }
+ let mut name = [0u16; MAX_PATH + 1];
+ let mut file_system = [0u16; 32];
+ if GetVolumeInformationW(
+ mount_point.as_ptr(),
+ name.as_mut_ptr(),
+ name.len() as DWORD,
+ std::ptr::null_mut(),
+ std::ptr::null_mut(),
+ std::ptr::null_mut(),
+ file_system.as_mut_ptr(),
+ file_system.len() as DWORD,
+ ) == 0
+ {
+ return None;
+ }
+ let mut pos = 0;
+ for x in name.iter() {
+ if *x == 0 {
+ break;
+ }
+ pos += 1;
+ }
+ let name = String::from_utf16_lossy(&name[..pos]);
+ let name = OsStr::new(&name);
+
+ pos = 0;
+ for x in file_system.iter() {
+ if *x == 0 {
+ break;
+ }
+ pos += 1;
+ }
+ let file_system: Vec<u8> = file_system[..pos].iter().map(|x| *x as u8).collect();
+
+ let drive_name = [
+ b'\\' as u16,
+ b'\\' as u16,
+ b'.' as u16,
+ b'\\' as u16,
+ b'A' as u16 + x as u16,
+ b':' as u16,
+ 0,
+ ];
+ let handle = HandleWrapper::new(&drive_name, 0)?;
+ let (total_space, available_space) = get_drive_size(&mount_point)?;
+ if total_space == 0 {
+ return None;
+ }
+ /*let mut spq_trim: STORAGE_PROPERTY_QUERY = std::mem::zeroed();
+ spq_trim.PropertyId = StorageDeviceTrimProperty;
+ spq_trim.QueryType = PropertyStandardQuery;
+ let mut dtd: DEVICE_TRIM_DESCRIPTOR = std::mem::zeroed();*/
+ let mut spq_trim = STORAGE_PROPERTY_QUERY {
+ PropertyId: 8,
+ QueryType: 0,
+ AdditionalParameters: [0],
+ };
+ let mut dtd: DEVICE_TRIM_DESCRIPTOR = std::mem::zeroed();
+
+ let mut dw_size = 0;
+ let type_ = if DeviceIoControl(
+ handle.0,
+ IOCTL_STORAGE_QUERY_PROPERTY,
+ &mut spq_trim as *mut STORAGE_PROPERTY_QUERY as *mut c_void,
+ size_of::<STORAGE_PROPERTY_QUERY>() as DWORD,
+ &mut dtd as *mut DEVICE_TRIM_DESCRIPTOR as *mut c_void,
+ size_of::<DEVICE_TRIM_DESCRIPTOR>() as DWORD,
+ &mut dw_size,
+ std::ptr::null_mut(),
+ ) == 0
+ || dw_size != size_of::<DEVICE_TRIM_DESCRIPTOR>() as DWORD
+ {
+ DiskType::Unknown(-1)
+ } else {
+ let is_ssd = dtd.TrimEnabled != 0;
+ if is_ssd {
+ DiskType::SSD
+ } else {
+ DiskType::HDD
+ }
+ };
+ Some(Disk {
+ type_,
+ name: name.to_owned(),
+ file_system: file_system.to_vec(),
+ mount_point: mount_point.to_vec(),
+ s_mount_point: String::from_utf16_lossy(&mount_point[..mount_point.len() - 1]),
+ total_space,
+ available_space,
+ is_removable,
+ })
+ })
+ .collect::<Vec<_>>()
+}