📄 diskinfo.pas
字号:
unit DiskInfo;
interface
uses
Windows, SysUtils, smart;
type
TDiskInfo = Record
Smart: Boolean;
bVersion: Byte; // Binary driver version.
bRevision: Byte; // Binary driver revision.
fCapabilities: DWORD;
Cylinders,
Heads,
Sectors: WORD;
ModelNumber,
FirmwareRev: String;
SerialNumber: String;
Temperature: Integer;
PowerOnTime: Integer;
IdOutCmd: array [1 .. sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1] of Byte;
AttrOutCmd: array [1 .. sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1] of Byte;
ThreshOutCmd: array [1 ..sizeof(SENDCMDOUTPARAMS) + READ_THRESHOLD_BUFFER_SIZE - 1] of Byte;
end;
var
ADiskInfo: TDiskInfo;
procedure DoPrintData;
procedure GetDiskInfo;
implementation
type
PByteArray = ^TByteArray;
TByteArray = array[0..32767] of Byte;
var
hSMARTIOCTL: THandle;
procedure ChangeByteOrder(var Data; Size: Integer);
var
ptr : PChar;
i : Integer;
c : Char;
begin
ptr := @Data;
for i := 0 to (Size shr 1)-1 do
begin
c := ptr^;
ptr^ := (ptr+1)^;
(ptr+1)^ := c;
Inc(ptr,2);
end;
end;
function DoIDENTIFY(pSCIP: PSENDCMDINPARAMS; pSCOP: PSENDCMDOUTPARAMS;
bIDCmd: Byte; bDriveNum: Byte; var lpcbBytesReturned: DWORD): Boolean;
begin
with pSCIP^ do
begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
with irDriveRegs do
begin
bFeaturesReg := 0;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := 0;
bCylHighReg := 0;
bDriveHeadReg := $A0 + ((bDriveNum and 1) shl 4);
end;
irDriveRegs.bCommandReg := bIDCmd;
bDriveNumber := bDriveNum;
cBufferSize := IDENTIFY_BUFFER_SIZE;
end; // with pSCIP^
Result := DeviceIoControl(hSMARTIOCTL, DWORD (DFP_RECEIVE_DRIVE_DATA),
Pointer( pSCIP), sizeof(SENDCMDINPARAMS) - 1,
Pointer( pSCOP), sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
lpcbBytesReturned, nil);
end;
function DoReadAttributesCmd (pSCIP: PSENDCMDINPARAMS;
pSCOP: PSENDCMDOUTPARAMS; bDriveNum: Byte): Boolean;
var
pRet: DWORD;
begin
with pSCIP^ do begin
cBufferSize := READ_ATTRIBUTE_BUFFER_SIZE;
with irDriveRegs do begin
bFeaturesReg := SMART_READ_ATTRIBUTE_VALUES;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := SMART_CYL_LOW;
bCylHighReg := SMART_CYL_HI;
end; {with irDriveRegs}
irDriveRegs.bDriveHeadReg := $A0 + ((bDriveNum and 1) shl 4);
irDriveRegs.bCommandReg := IDE_EXECUTE_SMART_FUNCTION;
bDriveNumber := bDriveNum;
end; {with pSCIP^}
Result := DeviceIoControl(hSMARTIOCTL, DFP_RECEIVE_DRIVE_DATA,
Pointer (pSCIP), sizeof(SENDCMDINPARAMS) - 1,
Pointer (pSCOP), sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1,
pRet, nil);
end;
function DoReadThresholdsCmd (pSCIP: PSENDCMDINPARAMS; pSCOP: PSENDCMDOUTPARAMS;
bDriveNum: Byte): Boolean;
var
pRet: DWORD;
begin
with pSCIP^ do begin
cBufferSize := READ_THRESHOLD_BUFFER_SIZE;
with irDriveRegs do begin
bFeaturesReg := SMART_READ_ATTRIBUTE_THRESHOLDS;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := SMART_CYL_LOW;
bCylHighReg := SMART_CYL_HI;
end; {with irDriveRegs}
irDriveRegs.bDriveHeadReg := $A0 + ((bDriveNum and 1) shl 4);
irDriveRegs.bCommandReg := IDE_EXECUTE_SMART_FUNCTION;
bDriveNumber := bDriveNum;
end; {with pSCIP}
Result := DeviceIoControl(hSMARTIOCTL, DFP_RECEIVE_DRIVE_DATA,
Pointer (pSCIP), sizeof(SENDCMDINPARAMS) - 1,
Pointer (pSCOP), sizeof(SENDCMDOUTPARAMS) + READ_THRESHOLD_BUFFER_SIZE - 1,
pRet, nil);
end;
function MakeInt64(RawValue: array of Byte): int64;
var
Word1,
Word2: WORD;
C1,
C2: Cardinal;
begin
Word1 := MakeWord(RawValue[0], RawValue[1]);
Word2 := MakeWord(RawValue[2], RawValue[3]);
C1 := MakeLong(Word1, Word2);
Word1 := MakeWord(RawValue[4], RawValue[5]);
C2 := MakeLong(Word1, 0);
Result := C1 Shl 32;
Result := Result + C2;
end;
procedure DoPrintData;
var
i,idx: Integer;
pDA: PDRIVEATTRIBUTE;
pAT: PATTRTHRESHOLD;
Temp: PByteArray;
S: String;
begin
Temp := @(PSENDCMDOUTPARAMS(@ADiskInfo.AttrOutCmd)^.bBuffer);
pDa := PDRIVEATTRIBUTE(@Temp[2]);
Temp := @(PSENDCMDOUTPARAMS(@ADiskInfo.ThreshOutCmd)^.bBuffer);
pAT := PATTRTHRESHOLD(@Temp[2]);
for i := 0 to (NUM_ATTRIBUTE_STRUCTS - 1) do
begin
if pDA^.bAttrID = 0 then continue;
if (pDA^.bAttrid = 231) or (pDA^.bAttrid = 194) then
begin
if pDA^.bAttrID > pDA^.bWorstValue then //希捷硬盘取的是AttrValue
ADiskInfo.Temperature := pDA^.bRawValue[0] //貌似其他硬盘取的是RawValue
else
ADiskInfo.Temperature := pDA^.bAttrValue;
end;
if PDA^.bAttrID = 9 then
ADiskInfo.PowerOnTime := MakeInt64(PDA^.bRawValue);
// idx := LVItemAdd(Format('%.2X: %s', [pDA^.bAttrID, AttribName(pDA^.bAttrid)]));
// LVSetItem(idx, 1,Format('%d',[pDA^.bAttrValue]),0,[],0,0,0 );
// LVSetItem(idx, 2,Format('%d',[pDA^.bWorstValue]),0,[],0,0,0 );
// LVSetItem(idx, 3,Format('%d',[pAT^.bWarrantyThreshold]),0,[],0,0,0 );
// S := Int2Hex(MakeInt64(PDA^.bRawValue),0);
// LVSetItem(idx, 4, S, 0, [], 0, 0, 0 );
Inc(pDA);
Inc(PAT);
end; {for}
end;
procedure GetDiskInfo;
var
pSCIP: SENDCMDINPARAMS;
//pOutCmd: SENDCMDOUTPARAMS;
pVParam: GETVERSIONOUTPARAMS;
pRet: DWORD;
pIdCmd: Byte;
pids: PIDSECTOR;
begin
FillChar(ADiskInfo, SizeOf(ADiskInfo), 0);
hSMARTIOCTL := CreateFile('\\.\PhysicalDrive0',
GENERIC_READ + GENERIC_WRITE,
FILE_SHARE_READ + FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
0,
0);
if hSMARTIOCTL = INVALID_HANDLE_VALUE then exit;
ZeroMemory(@pVParam, sizeof (pVParam));
if (DeviceIoControl (hSMARTIOCTL, DFP_GET_VERSION, nil, 0, @pVParam, sizeof(pVParam), pRet, nil)) then
begin
ADiskInfo.Smart := True;
ADiskInfo.bVersion := pvparam.bVersion;
ADiskInfo.bRevision := pVParam.bRevision;
ADiskInfo.fCapabilities := PVParam.fCapabilities;
end;
if (pVParam.bIDEDeviceMap and $10) = 1 then
pIDCmd := IDE_ATAPI_ID
else
pIDCmd := IDE_ID_FUNCTION;
with ADiskInfo do
begin
if DoIDENTIFY(@pSCIP,@IdOutCmd, pIDCmd,0, pret) then
begin
pIds := @PSENDCMDOUTPARAMS(@IdOutCmd).bBuffer;
Heads := Pids^.wNumHeads;
Cylinders := Pids^.wNumCyls;
// wBytesPerTrack
// Cylinders := PIDS^.wBytesPerSector;
ChangeByteOrder(pids^.sModelNumber, sizeof (pids^.sModelNumber));
ModelNumber := Trim(Pids^.sModelNumber);
ChangeByteOrder (pids^.sFirmwareRev, sizeof (pids^.sFirmwareRev));
FirmwareRev := Trim(pids^.sFirmwareRev);
ChangeByteOrder(pids^.sSerialNumber, sizeof (pids^.sSerialNumber));
SerialNumber := Trim(pids^.sSerialNumber);
// FillChar(AttrOutCmd, SizeOf(ADiskInfo.AttrOutCmd), 0);
// FillChar(ThreshOutCmd, SizeOf(ADiskInfo.ThreshOutCmd), 0);
DoReadAttributesCmd(@pSCIP, PSENDCMDOUTPARAMS(@AttrOutCmd), 0);
DoReadThresholdsCmd(@pSCIP, PSENDCMDOUTPARAMS(@ThreshOutCmd), 0);
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -