我正在尝试在 Windows 上获取内部 sata 驱动器的温度,到目前为止,我已成功获取驱动器 ID,它的所有信息,如存储容量、序列号。,型号等,但无法获得其温度详细信息,尽管我的 sata 驱动器通过工具(水晶信息)提供温度。我也通过文件来解决这个问题,但没有得到太多。
这是将命令发送到磁盘的示例代码
typedef struct _SCSI_PASS_THROUGH {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
ULONG_PTR DataBufferOffset;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
}SCSI_PASS_THROUGH;
#define SCSI_IOCTL_DATA_IN 1
#define READ_ATTRIBUTE_BUFFER_SIZE 512
#define READ_ATTRIBUTES 0xD0
void smartStatus()
{
BOOL bRet;
DWORD dwReturned;
DWORD length;
typedef struct _SMART_ATTRIBUTE
{
BYTE Id;
WORD StatusFlags;
BYTE CurrentValue;
BYTE WorstValue;
BYTE RawValue[6];
BYTE Reserved;
} SMART_ATTRIBUTE;
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {
SCSI_PASS_THROUGH Spt;
ULONG Filler; // realign buffers to double word boundary
UCHAR SenseBuf[32];
UCHAR DataBuf[4096];
} SCSI_PASS_THROUGH_WITH_BUFFERS;
SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
ZeroMemory(&sptwb, sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.Spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.Spt.PathId = 0;
sptwb.Spt.TargetId = 0;
sptwb.Spt.Lun = 0;
sptwb.Spt.SenseInfoLength = 24;
sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.Spt.DataTransferLength = READ_ATTRIBUTE_BUFFER_SIZE;
sptwb.Spt.TimeOutValue = 2;
sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf);
sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseBuf);
sptwb.Spt.CdbLength = 12;
sptwb.Spt.Cdb[0] = 0xA1;//ATA PASS THROUGH(12) OPERATION CODE(A1h)
sptwb.Spt.Cdb[1] = (4 << 1) | 0; //MULTIPLE_COUNT=0,PROTOCOL=4(PIO Data-In),Reserved
sptwb.Spt.Cdb[2] = (1 << 3) | (1 << 2) | 2;//OFF_LINE=0,CK_COND=0,Reserved=0,T_DIR=1(ToDevice),BYTE_BLOCK=1,T_LENGTH=2
sptwb.Spt.Cdb[3] = READ_ATTRIBUTES;//FEATURES (7:0)
sptwb.Spt.Cdb[4] = 1;//SECTOR_COUNT (7:0)
sptwb.Spt.Cdb[5] = 1;//LBA_LOW (7:0)
sptwb.Spt.Cdb[6] = 0x4F;//LBA_MID (7:0)
sptwb.Spt.Cdb[7] = 0xc2;//LBA_HIGH (7:0)
sptwb.Spt.Cdb[8] = 0xA0;
sptwb.Spt.Cdb[9] = 0xb0;//COMMAND
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf) + sptwb.Spt.DataTransferLength;
bRet = ::DeviceIoControl(hDev, IOCTL_SCSI_PASS_THROUGH,
&sptwb, sizeof(SCSI_PASS_THROUGH),
&sptwb, length, &dwReturned, NULL);
DWORD err = GetLastError();
log(logDEBUG1) << "Error smartStatus" << " Error " << err;
DWORD count = 0;
for (int i = 0; i < 512; i++)
{
count += sptwb.DataBuf[i];
}
if (count == 0)
{
return;
}
int life = -1;
BYTE SmartReadData[512] = {0};
SMART_ATTRIBUTE Attribute;
memcpy(SmartReadData,sptwb.DataBuf, 512);
//HexDump(SmartReadData, 512);
int j = 0;
for (int i = 0; i < 30; i++)
{
//DWORD rawValue = 0;
memcpy(&(Attribute),
&SmartReadData[i * sizeof(SMART_ATTRIBUTE) + 2], sizeof(SMART_ATTRIBUTE));
if (i == 0)
{
if (Attribute.CurrentValue <= 100)
{
//log(logINFO) << "before case ";
life = Attribute.CurrentValue;
//log(logINFO) << "life " << life;
}
}
if (Attribute.Id != 0)
{
switch (Attribute.Id)
{
case 0xC2: // Temperature
if ((Attribute.RawValue[1] != 0 || Attribute.RawValue[0] > 70))
{
disk_info.temperature = ((Attribute.RawValue[1] & 0xff) | ((Attribute.RawValue[0] & 0xff)<<8));
}
else if (Attribute.RawValue[0] > 0)
{
disk_info.temperature = (Attribute.RawValue[0] * 1);
}
if (disk_info.temperature >= 100)
{
disk_info.temperature = 0;
}
break;
default:
break;
}
j++;
}
}
//disk_info.temperature = SmartReadData[0x2] * 256 + SmartReadData[0x1] - 273;
//if (disk_info.temperature == -273)
//{
// disk_info.temperature = -1000;
//}
//life = 100 - SmartReadData[0x05];
if (life < 0)
{
life = 0;
}
if (life > 10)
{
disk_info.health = DISK_STATUS_GOOD;
}
else if (life == 10)
{
disk_info.health = DISK_STATUS_CAUTION;
}
else if (life < 10)
{
disk_info.health = DISK_STATUS_BAD;
}
else
{
disk_info.health = DISK_STATUS_UNKNOWN;
}
//_aligned_free(identifyResp);
return;
在我的情况下,“DeviceIoControl”函数之后的计数始终为零,这意味着缓冲区未填充。disk_info 只是收集与驱动器相关的所有详细信息的结构。看到日志后,我发现“DeviceIoControl”返回错误代码 1117。请帮我解决这个问题