diff --git a/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs b/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs
index b3e039b..41c8f0a 100644
--- a/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs
+++ b/LibreHardwareMonitorLib/Hardware/Storage/StorageGroup.cs
@@ -19,6 +19,8 @@ internal class StorageGroup : IGroup
if (Software.OperatingSystem.IsUnix)
return;
+ var storageSpaceDiskToPhysicalDiskMap = StorageSpaceDiskToPhysicalDiskMapping();
+
//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())
@@ -35,10 +37,79 @@ internal class StorageGroup : IGroup
{
_hardware.Add(instance);
}
+
+ if (storageSpaceDiskToPhysicalDiskMap.ContainsKey(idx))
+ {
+ var physicalDisks = storageSpaceDiskToPhysicalDiskMap[idx];
+ foreach ((uint, ulong) physicalDisk in physicalDisks)
+ {
+ var physicalDiskInstance = AbstractStorage.CreateInstance(@$"\\.\PHYSICALDRIVE{physicalDisk.Item1}", physicalDisk.Item1, physicalDisk.Item2, scsi, settings);
+ if (physicalDiskInstance != null)
+ {
+ _hardware.Add(physicalDiskInstance);
+ }
+ }
+ }
}
}
}
+ ///
+ /// Maps each StorageSpace to the PhysicalDisks it is composed of.
+ ///
+ ///
+ private static Dictionary> StorageSpaceDiskToPhysicalDiskMapping()
+ {
+ 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())
+ {
+ 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"))))
+ {
+ 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())
+ {
+ var physicalDiskSize = (ulong)physicalDisk["Size"];
+ uint physicalDiskIdx;
+ if (uint.TryParse((string)physicalDisk["DeviceId"], out physicalDiskIdx))
+ {
+ diskToPhysicalDisk[diskIdx].Add((physicalDiskIdx, physicalDiskSize));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return diskToPhysicalDisk;
+ }
+
+ 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()
@@ -51,4 +122,4 @@ internal class StorageGroup : IGroup
foreach (AbstractStorage storage in _hardware)
storage.Close();
}
-}
\ No newline at end of file
+}
diff --git a/LibreHardwareMonitorLib/Software/OperatingSystem.cs b/LibreHardwareMonitorLib/Software/OperatingSystem.cs
index d1ec00c..4c16bb7 100644
--- a/LibreHardwareMonitorLib/Software/OperatingSystem.cs
+++ b/LibreHardwareMonitorLib/Software/OperatingSystem.cs
@@ -20,10 +20,13 @@ public static class OperatingSystem
{
// The operating system doesn't change during execution so let's query it just one time.
PlatformID platform = Environment.OSVersion.Platform;
+ Version version = Environment.OSVersion.Version;
IsUnix = platform is PlatformID.Unix or PlatformID.MacOSX;
if (Environment.Is64BitOperatingSystem)
Is64Bit = true;
+
+ IsWindows8OrGreater = !IsUnix && ((version.Major == 6 && version.Minor >= 2) || version.Major > 6);
}
///
@@ -35,4 +38,9 @@ public static class OperatingSystem
/// Gets information about whether the current system is Unix based.
///
public static bool IsUnix { get; }
-}
\ No newline at end of file
+
+ ///
+ /// Returns true if the current system is Windows 8 or a more recent Windows version
+ ///
+ public static bool IsWindows8OrGreater { get; }
+}