diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs index 41c8f0a..9b753e9 100644 --- a/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs @@ -10,6 +10,8 @@ using System.Management; namespace LibreHardwareMonitor.Hardware.Storage; +#pragma warning disable CA1416 // Validate platform compatibility + internal class StorageGroup : IGroup { private readonly List _hardware = new(); @@ -19,99 +21,138 @@ internal class StorageGroup : IGroup if (Software.OperatingSystem.IsUnix) return; - var storageSpaceDiskToPhysicalDiskMap = StorageSpaceDiskToPhysicalDiskMapping(); + Dictionary> storageSpaceDiskToPhysicalDiskMap = GetStorageSpaceDiskToPhysicalDiskMap(); + AddHardware(settings, storageSpaceDiskToPhysicalDiskMap); + } - //https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive - using var diskDriveSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive") { Options = { Timeout = TimeSpan.FromSeconds(10) } }; - foreach (ManagementBaseObject diskDrive in diskDriveSearcher.Get()) + public IReadOnlyList Hardware => _hardware; + + /// + /// Adds the hardware. + /// + /// The settings. + /// The storage space disk to physical disk map. + private void AddHardware(ISettings settings, Dictionary> storageSpaceDiskToPhysicalDiskMap) + { + try { - string deviceId = (string)diskDrive.Properties["DeviceId"].Value; // is \\.\PhysicalDrive0..n - uint idx = Convert.ToUInt32(diskDrive.Properties["Index"].Value); - ulong diskSize = Convert.ToUInt64(diskDrive.Properties["Size"].Value); - int scsi = Convert.ToInt32(diskDrive.Properties["SCSIPort"].Value); + // https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive + using var diskDriveSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive") { Options = { Timeout = TimeSpan.FromSeconds(10) } }; - if (deviceId != null) + foreach (ManagementBaseObject diskDrive in diskDriveSearcher.Get()) { - var instance = AbstractStorage.CreateInstance(deviceId, idx, diskSize, scsi, settings); - if (instance != null) - { - _hardware.Add(instance); - } + string deviceId = (string)diskDrive.Properties["DeviceId"].Value; // is \\.\PhysicalDrive0..n + uint index = Convert.ToUInt32(diskDrive.Properties["Index"].Value); + ulong diskSize = Convert.ToUInt64(diskDrive.Properties["Size"].Value); + int scsi = Convert.ToInt32(diskDrive.Properties["SCSIPort"].Value); - if (storageSpaceDiskToPhysicalDiskMap.ContainsKey(idx)) + if (deviceId != null) { - var physicalDisks = storageSpaceDiskToPhysicalDiskMap[idx]; - foreach ((uint, ulong) physicalDisk in physicalDisks) + var instance = AbstractStorage.CreateInstance(deviceId, index, diskSize, scsi, settings); + if (instance != null) + _hardware.Add(instance); + + if (storageSpaceDiskToPhysicalDiskMap.ContainsKey(index)) { - var physicalDiskInstance = AbstractStorage.CreateInstance(@$"\\.\PHYSICALDRIVE{physicalDisk.Item1}", physicalDisk.Item1, physicalDisk.Item2, scsi, settings); - if (physicalDiskInstance != null) + foreach ((uint, ulong) physicalDisk in storageSpaceDiskToPhysicalDiskMap[index]) { - _hardware.Add(physicalDiskInstance); + var physicalDiskInstance = AbstractStorage.CreateInstance(@$"\\.\PHYSICALDRIVE{physicalDisk.Item1}", physicalDisk.Item1, physicalDisk.Item2, scsi, settings); + if (physicalDiskInstance != null) + _hardware.Add(physicalDiskInstance); } } } } } + catch + { + // Ignored. + } } /// /// Maps each StorageSpace to the PhysicalDisks it is composed of. /// - /// - private static Dictionary> StorageSpaceDiskToPhysicalDiskMapping() + private static Dictionary> GetStorageSpaceDiskToPhysicalDiskMap() { var diskToPhysicalDisk = new Dictionary>(); + if (!Software.OperatingSystem.IsWindows8OrGreater) - { return diskToPhysicalDisk; - } - ManagementScope scope = new ManagementScope(@"\root\Microsoft\Windows\Storage"); - - // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-disk - // Lists all the disks visible to your system, the output is the same as Win32_DiskDrive. - // If you're using a storage Space, the "hidden" disks which compose your storage space will not be listed. - using var diskSearcher = new ManagementObjectSearcher(scope, new ObjectQuery("SELECT * FROM MSFT_Disk")); - foreach (ManagementBaseObject disk in diskSearcher.Get()) + try { - var diskIdx = (uint)disk["Number"]; - diskToPhysicalDisk[diskIdx] = new List<(uint, ulong)>(); - // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-virtualdisk - // Maps the current Disk to its corresponding VirtualDisk. If the current Disk is not a storage space, it does not have a corresponding VirtualDisk. - // Each Disk maps to one or zero VirtualDisk. - using (var toVirtualDisk = new ManagementObjectSearcher(scope, new ObjectQuery(FollowAssociationQuery("MSFT_Disk", (string)disk["ObjectId"], "MSFT_VirtualDiskToDisk")))) + ManagementScope scope = new(@"\root\Microsoft\Windows\Storage"); + + // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-disk + // Lists all the disks visible to your system, the output is the same as Win32_DiskDrive. + // If you're using a storage Space, the "hidden" disks which compose your storage space will not be listed. + using var diskSearcher = new ManagementObjectSearcher(scope, new ObjectQuery("SELECT * FROM MSFT_Disk")); + + foreach (ManagementBaseObject disk in diskSearcher.Get()) { - foreach (ManagementBaseObject virtualDisk in toVirtualDisk.Get()) + try { - // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-physicaldisk - // Maps the current VirtualDisk to the PhysicalDisk it is composed of. - // Each VirtualDisk maps to one or more PhysicalDisk. - using (var toPhysicalDisk = new ManagementObjectSearcher(scope, new ObjectQuery(FollowAssociationQuery("MSFT_VirtualDisk", (string)virtualDisk["ObjectId"], "MSFT_VirtualDiskToPhysicalDisk")))) - { - foreach (ManagementBaseObject physicalDisk in toPhysicalDisk.Get()) - { - var physicalDiskSize = (ulong)physicalDisk["Size"]; - uint physicalDiskIdx; - if (uint.TryParse((string)physicalDisk["DeviceId"], out physicalDiskIdx)) - { - diskToPhysicalDisk[diskIdx].Add((physicalDiskIdx, physicalDiskSize)); - } - } - } + List<(uint, ulong)> map = MapDiskToPhysicalDisk(disk, scope); + if (map.Count > 0) + diskToPhysicalDisk[(uint)disk["Number"]] = map; + } + catch + { + // Ignored. } } } + catch + { + // Ignored. + } return diskToPhysicalDisk; } + /// + /// Maps a disk to a physical disk. + /// + /// The disk. + /// The scope. + private static List<(uint, ulong)> MapDiskToPhysicalDisk(ManagementBaseObject disk, ManagementScope scope) + { + var map = new List<(uint, ulong)>(); + + // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-virtualdisk + // Maps the current Disk to its corresponding VirtualDisk. If the current Disk is not a storage space, it does not have a corresponding VirtualDisk. + // Each Disk maps to one or zero VirtualDisk. + using var toVirtualDisk = new ManagementObjectSearcher(scope, new ObjectQuery(FollowAssociationQuery("MSFT_Disk", (string)disk["ObjectId"], "MSFT_VirtualDiskToDisk"))); + + foreach (ManagementBaseObject virtualDisk in toVirtualDisk.Get()) + { + // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-physicaldisk + // Maps the current VirtualDisk to the PhysicalDisk it is composed of. + // Each VirtualDisk maps to one or more PhysicalDisk. + + using var toPhysicalDisk = new ManagementObjectSearcher(scope, + new ObjectQuery(FollowAssociationQuery("MSFT_VirtualDisk", + (string)virtualDisk["ObjectId"], + "MSFT_VirtualDiskToPhysicalDisk"))); + + foreach (ManagementBaseObject physicalDisk in toPhysicalDisk.Get()) + { + ulong physicalDiskSize = (ulong)physicalDisk["Size"]; + + if (uint.TryParse((string)physicalDisk["DeviceId"], out uint physicalDiskId)) + map.Add((physicalDiskId, physicalDiskSize)); + } + } + + return map; + } + private static string FollowAssociationQuery(string source, string objectId, string associationClass) { return @$"ASSOCIATORS OF {{{source}.ObjectId=""{objectId.Replace(@"\", @"\\").Replace(@"""", @"\""")}""}} WHERE AssocClass = {associationClass}"; } - public IReadOnlyList Hardware => _hardware; - public string GetReport() { return null; diff --git a/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs b/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs index a3a4070..7e1d821 100644 --- a/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs +++ b/LibreHardwareMonitorLib/Hardware/Storage/WindowsStorage.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Management; using System.Runtime.InteropServices; -using System.Text; using LibreHardwareMonitor.Interop; namespace LibreHardwareMonitor.Hardware.Storage; @@ -21,11 +20,7 @@ internal static class WindowsStorage if (handle?.IsInvalid != false) return null; - var query = new Kernel32.STORAGE_PROPERTY_QUERY - { - PropertyId = Kernel32.STORAGE_PROPERTY_ID.StorageDeviceProperty, - QueryType = Kernel32.STORAGE_QUERY_TYPE.PropertyStandardQuery - }; + var query = new Kernel32.STORAGE_PROPERTY_QUERY { PropertyId = Kernel32.STORAGE_PROPERTY_ID.StorageDeviceProperty, QueryType = Kernel32.STORAGE_QUERY_TYPE.PropertyStandardQuery }; if (!Kernel32.DeviceIoControl(handle, Kernel32.IOCTL.IOCTL_STORAGE_QUERY_PROPERTY, @@ -66,9 +61,7 @@ internal static class WindowsStorage if (o is ManagementObject dp) { foreach (ManagementBaseObject ld in dp.GetRelated("Win32_LogicalDisk")) - { list.Add(((string)ld["Name"]).TrimEnd(':')); - } } } }