Guard against invalid storage namespace.

[ci skip]
This commit is contained in:
PhyxionNL
2022-12-01 10:45:39 +01:00
parent 7265bde10f
commit bc4a4002b0
2 changed files with 97 additions and 63 deletions
@@ -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<AbstractStorage> _hardware = new();
@@ -19,99 +21,138 @@ internal class StorageGroup : IGroup
if (Software.OperatingSystem.IsUnix)
return;
var storageSpaceDiskToPhysicalDiskMap = StorageSpaceDiskToPhysicalDiskMapping();
Dictionary<uint, List<(uint, ulong)>> 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<IHardware> Hardware => _hardware;
/// <summary>
/// Adds the hardware.
/// </summary>
/// <param name="settings">The settings.</param>
/// <param name="storageSpaceDiskToPhysicalDiskMap">The storage space disk to physical disk map.</param>
private void AddHardware(ISettings settings, Dictionary<uint, List<(uint, ulong)>> 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.
}
}
/// <summary>
/// Maps each StorageSpace to the PhysicalDisks it is composed of.
/// </summary>
/// <returns></returns>
private static Dictionary<uint, List<(uint, ulong)>> StorageSpaceDiskToPhysicalDiskMapping()
private static Dictionary<uint, List<(uint, ulong)>> GetStorageSpaceDiskToPhysicalDiskMap()
{
var diskToPhysicalDisk = new Dictionary<uint, List<(uint, ulong)>>();
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;
}
/// <summary>
/// Maps a disk to a physical disk.
/// </summary>
/// <param name="disk">The disk.</param>
/// <param name="scope">The scope.</param>
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<IHardware> Hardware => _hardware;
public string GetReport()
{
return null;
@@ -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(':'));
}
}
}
}