Fixes #1919
This commit is contained in:
@@ -51,7 +51,7 @@ public abstract class AtaStorage : AbstractStorage
|
||||
ISmart smart = new WindowsSmart(storageInfo.Index);
|
||||
string name = null;
|
||||
string firmwareRevision = null;
|
||||
AtaSmart.SMART_ATTRIBUTE[] smartAttributes = { };
|
||||
AtaSmart.SMART_ATTRIBUTE[] smartAttributes = [];
|
||||
|
||||
if (smart.IsValid)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ public abstract class AtaStorage : AbstractStorage
|
||||
{
|
||||
const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
|
||||
|
||||
return Activator.CreateInstance(type, flags, null, new object[] { storageInfo, smart, name, firmwareRevision, storageInfo.Index, settings }, null) as AtaStorage;
|
||||
return Activator.CreateInstance(type, flags, null, [storageInfo, smart, name, firmwareRevision, storageInfo.Index, settings], null) as AtaStorage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using LibreHardwareMonitor.Interop;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Storage.FileSystem;
|
||||
using Windows.Win32.System.Ioctl;
|
||||
using static LibreHardwareMonitor.Interop.AtaSmart;
|
||||
|
||||
namespace LibreHardwareMonitor.Hardware.Storage;
|
||||
|
||||
@@ -50,8 +51,8 @@ internal class WindowsSmart : ISmart
|
||||
irDriveRegs =
|
||||
{
|
||||
bFeaturesReg = 0xD8,
|
||||
bCylLowReg = AtaSmart.SMART_LBA_MID,
|
||||
bCylHighReg = AtaSmart.SMART_LBA_HI,
|
||||
bCylLowReg = (byte)PInvoke.SMART_CYL_LOW,
|
||||
bCylHighReg = (byte)PInvoke.SMART_CYL_HI,
|
||||
bCommandReg = (byte) PInvoke.SMART_CMD
|
||||
}
|
||||
};
|
||||
@@ -68,7 +69,7 @@ internal class WindowsSmart : ISmart
|
||||
null);
|
||||
}
|
||||
|
||||
public unsafe AtaSmart.SMART_ATTRIBUTE[] ReadSmartData()
|
||||
public unsafe SMART_ATTRIBUTE[] ReadSmartData()
|
||||
{
|
||||
if (_handle.IsClosed)
|
||||
throw new ObjectDisposedException(nameof(WindowsSmart));
|
||||
@@ -78,14 +79,14 @@ internal class WindowsSmart : ISmart
|
||||
bDriveNumber = (byte)_driveNumber,
|
||||
irDriveRegs =
|
||||
{
|
||||
bFeaturesReg = 0xD0,
|
||||
bCylLowReg = AtaSmart.SMART_LBA_MID,
|
||||
bCylHighReg = AtaSmart.SMART_LBA_HI,
|
||||
bFeaturesReg = (byte)PInvoke.READ_ATTRIBUTES,
|
||||
bCylLowReg = (byte)PInvoke.SMART_CYL_LOW,
|
||||
bCylHighReg = (byte)PInvoke.SMART_CYL_HI,
|
||||
bCommandReg = (byte) PInvoke.SMART_CMD
|
||||
}
|
||||
};
|
||||
|
||||
int cb = sizeof(SENDCMDOUTPARAMS) + 2 + 512; // 2 bytes padding + 512 bytes buffer.
|
||||
int cb = sizeof(SENDCMDOUTPARAMS) + 512; // 512 bytes buffer.
|
||||
IntPtr buffer = Marshal.AllocHGlobal(cb);
|
||||
|
||||
bool isValid = PInvoke.DeviceIoControl(_handle,
|
||||
@@ -99,11 +100,16 @@ internal class WindowsSmart : ISmart
|
||||
|
||||
if (isValid)
|
||||
{
|
||||
AtaSmart.SMART_ATTRIBUTE[] attributes = new AtaSmart.SMART_ATTRIBUTE[512 / sizeof(AtaSmart.SMART_ATTRIBUTE)];
|
||||
AtaSmart.SMART_ATTRIBUTE* pAttributes = (AtaSmart.SMART_ATTRIBUTE*)((byte*)buffer + (int)Marshal.OffsetOf<SENDCMDOUTPARAMS>(nameof(SENDCMDOUTPARAMS.bBuffer)) + 2);
|
||||
var attributes = new SMART_ATTRIBUTE[30]; // A maximum of 30 are returned.
|
||||
|
||||
for (int i = 0; i < attributes.Length; i++)
|
||||
attributes[i] = pAttributes[i];
|
||||
var sendCmdOutParams = (SENDCMDOUTPARAMS*)buffer;
|
||||
fixed (byte* pBuffer = &sendCmdOutParams->bBuffer[0])
|
||||
{
|
||||
var pAttribute = (SMART_ATTRIBUTE*)(pBuffer + 2); // + 2 padding.
|
||||
|
||||
for (int i = 0; i < attributes.Length; i++)
|
||||
attributes[i] = pAttribute[i];
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
return attributes;
|
||||
@@ -113,7 +119,7 @@ internal class WindowsSmart : ISmart
|
||||
return null;
|
||||
}
|
||||
|
||||
public unsafe AtaSmart.SMART_THRESHOLD[] ReadSmartThresholds()
|
||||
public unsafe SMART_THRESHOLD[] ReadSmartThresholds()
|
||||
{
|
||||
if (_handle.IsClosed)
|
||||
throw new ObjectDisposedException(nameof(WindowsSmart));
|
||||
@@ -123,14 +129,14 @@ internal class WindowsSmart : ISmart
|
||||
bDriveNumber = (byte)_driveNumber,
|
||||
irDriveRegs =
|
||||
{
|
||||
bFeaturesReg = 0xD1,
|
||||
bCylLowReg = AtaSmart.SMART_LBA_MID,
|
||||
bCylHighReg = AtaSmart.SMART_LBA_HI,
|
||||
bFeaturesReg = (byte)PInvoke.READ_THRESHOLDS,
|
||||
bCylLowReg = (byte)PInvoke.SMART_CYL_LOW,
|
||||
bCylHighReg = (byte)PInvoke.SMART_CYL_HI,
|
||||
bCommandReg = (byte) PInvoke.SMART_CMD
|
||||
}
|
||||
};
|
||||
|
||||
int cb = sizeof(SENDCMDOUTPARAMS) + 2 + 512; // 2 bytes padding + 512 bytes buffer.
|
||||
int cb = sizeof(SENDCMDOUTPARAMS) + 512; // 2 bytes padding + 512 bytes buffer.
|
||||
IntPtr buffer = Marshal.AllocHGlobal(cb);
|
||||
bool isValid = PInvoke.DeviceIoControl(_handle,
|
||||
PInvoke.SMART_RCV_DRIVE_DATA,
|
||||
@@ -143,11 +149,16 @@ internal class WindowsSmart : ISmart
|
||||
|
||||
if (isValid)
|
||||
{
|
||||
AtaSmart.SMART_THRESHOLD[] thresholds = new AtaSmart.SMART_THRESHOLD[512 / sizeof(AtaSmart.SMART_THRESHOLD)];
|
||||
AtaSmart.SMART_THRESHOLD* pThresholds = (AtaSmart.SMART_THRESHOLD*) ((byte*)buffer + (int)Marshal.OffsetOf<SENDCMDOUTPARAMS>(nameof(SENDCMDOUTPARAMS.bBuffer)) + 2);
|
||||
var thresholds = new SMART_THRESHOLD[30]; // A maximum of 30 are returned.
|
||||
|
||||
for (int i = 0; i < thresholds.Length; i++)
|
||||
thresholds[i] = pThresholds[i];
|
||||
var sendCmdOutParams = (SENDCMDOUTPARAMS*)buffer;
|
||||
fixed (byte* pBuffer = &sendCmdOutParams->bBuffer[0])
|
||||
{
|
||||
var pThreshold = (SMART_THRESHOLD*)(pBuffer + 2); // + 2 padding.
|
||||
|
||||
for (int i = 0; i < thresholds.Length; i++)
|
||||
thresholds[i] = pThreshold[i];
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
return thresholds;
|
||||
@@ -171,7 +182,7 @@ internal class WindowsSmart : ISmart
|
||||
}
|
||||
};
|
||||
|
||||
int cb = sizeof(SENDCMDOUTPARAMS) + sizeof(AtaSmart.IDENTIFY_DEVICE_DATA);
|
||||
int cb = sizeof(SENDCMDOUTPARAMS) + sizeof(IDENTIFY_DEVICE_DATA);
|
||||
IntPtr buffer = Marshal.AllocHGlobal(cb);
|
||||
|
||||
bool valid = PInvoke.DeviceIoControl(_handle,
|
||||
@@ -191,7 +202,7 @@ internal class WindowsSmart : ISmart
|
||||
return false;
|
||||
}
|
||||
|
||||
AtaSmart.IDENTIFY_DEVICE_DATA identity = *(AtaSmart.IDENTIFY_DEVICE_DATA*)((byte*)buffer + (int)Marshal.OffsetOf<SENDCMDOUTPARAMS>(nameof(SENDCMDOUTPARAMS.bBuffer)));
|
||||
IDENTIFY_DEVICE_DATA identity = *(IDENTIFY_DEVICE_DATA*)((byte*)buffer + (int)Marshal.OffsetOf<SENDCMDOUTPARAMS>(nameof(SENDCMDOUTPARAMS.bBuffer)));
|
||||
|
||||
byte* p = identity.ModelNumber;
|
||||
for (int i = 0; i < 40; i += 2)
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
// Copyright (C) LibreHardwareMonitor and Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Win32.Storage.IscsiDisc;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace LibreHardwareMonitor.Interop;
|
||||
|
||||
public class AtaSmart
|
||||
public unsafe class AtaSmart
|
||||
{
|
||||
internal const int IOCTL_BUFFER_SIZE = 4096;
|
||||
internal const int SCSI_IOCTL_SENSE_SIZE = 24;
|
||||
@@ -25,24 +26,26 @@ public class AtaSmart
|
||||
internal const byte SMART_LBA_HI = 0xC2;
|
||||
internal const byte SMART_LBA_MID = 0x4F;
|
||||
|
||||
public unsafe struct SMART_ATTRIBUTE
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SMART_ATTRIBUTE
|
||||
{
|
||||
public byte Id;
|
||||
public short Flags;
|
||||
public byte CurrentValue;
|
||||
public byte WorstValue;
|
||||
public fixed byte RawValue[6];
|
||||
public byte Reserved;
|
||||
internal byte Id;
|
||||
internal ushort Flags;
|
||||
internal byte CurrentValue;
|
||||
internal byte WorstValue;
|
||||
internal fixed byte RawValue[6];
|
||||
internal byte Reserved;
|
||||
}
|
||||
|
||||
public unsafe struct SMART_THRESHOLD
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SMART_THRESHOLD
|
||||
{
|
||||
public byte Id;
|
||||
public byte Threshold;
|
||||
public fixed byte Reserved[10];
|
||||
}
|
||||
|
||||
internal unsafe struct IDENTIFY_DEVICE_DATA
|
||||
internal struct IDENTIFY_DEVICE_DATA
|
||||
{
|
||||
public ushort GeneralConfiguration;
|
||||
public ushort NumberOfCylinders;
|
||||
@@ -75,7 +78,7 @@ public class AtaSmart
|
||||
public fixed ushort Reserved3[197];
|
||||
}
|
||||
|
||||
internal unsafe struct NVME_PASS_THROUGH_IOCTL
|
||||
internal struct NVME_PASS_THROUGH_IOCTL
|
||||
{
|
||||
public SRB_IO_CONTROL SrbIoCtrl;
|
||||
public fixed uint VendorSpecific[NVME_IOCTL_VENDOR_SPECIFIC_DW_SIZE];
|
||||
@@ -89,7 +92,7 @@ public class AtaSmart
|
||||
public fixed byte DataBuffer[IOCTL_BUFFER_SIZE];
|
||||
}
|
||||
|
||||
internal unsafe struct SCSI_PASS_THROUGH
|
||||
internal struct SCSI_PASS_THROUGH
|
||||
{
|
||||
public Windows.Win32.Storage.IscsiDisc.SCSI_PASS_THROUGH Spt;
|
||||
public fixed byte SenseBuf[SCSI_IOCTL_SENSE_SIZE];
|
||||
|
||||
@@ -67,3 +67,7 @@ GetProcAddress
|
||||
SCSI_IOCTL_*
|
||||
SMART_CMD
|
||||
BATTERY_UNKNOWN_*
|
||||
SMART_CYL_LOW
|
||||
SMART_CYL_HI
|
||||
READ_ATTRIBUTES
|
||||
READ_THRESHOLDS
|
||||
|
||||
Reference in New Issue
Block a user