[Delphi] IDE/SATA 하드 디스크 일련 번호 가져오기
2580 단어 DelphiWindows 프로그래밍
다음은 수정된 코드를 간소화하고 첫 번째 하드디스크의 시퀀스 번호만 찾으며 Win7 + XE 테스트가 통과되었습니다.먼저 JwApi 함수 라이브러리를 설치해야 합니다. 왜냐하면 일부 구조체가 라이브러리에 성명되어 있기 때문입니다.
unit uGetHDSN;
interface
uses
Windows, JwaWinIoctl;
function GetIdeSerialNumber: AnsiString;
implementation
type
TIdSector = packed record
wGenConfig: USHORT;
wNumCyls: USHORT;
wReserved: USHORT;
wNumHeads: USHORT;
wBytesPerTrack: USHORT;
wBytesPerSector: USHORT;
wSectorsPerTrack: USHORT;
wVendorUnique: array [0 .. 2] of USHORT;
sSerialNumber: array [0 .. 19] of AnsiChar;
wBufferType: USHORT;
wBufferSize: USHORT;
wECCSize: USHORT;
sFirmwareRev: array [0 .. 7] of AnsiChar;
sModelNumber: array [0 .. 39] of AnsiChar;
wMoreVendorUnique: USHORT;
wDoubleWordIO: USHORT;
wCapabilities: USHORT;
wReserved1: USHORT;
wPIOTiming: USHORT;
wDMATiming: USHORT;
wBS: USHORT;
wNumCurrentCyls: USHORT;
wNumCurrentHeads: USHORT;
wNumCurrentSectorsPerTrack: USHORT;
ulCurrentSectorCapacity: ULONG;
wMultSectorStuff: USHORT;
ulTotalAddressableSectors: ULONG;
wSingleWordDMA: USHORT;
wMultiWordDMA: USHORT;
bReserved: array [0 .. 127] of Byte;
end;
PIdSector = ^TIdSector;
const
IDE_ATA_IDENTIFY = $EC;
function LittleToBig(Data: Word): Word;
asm
xchg ah, al
end;
function GetIdeSerialNumber: AnsiString;
var
hDevice: THandle;
Size, cbBytesReturned: DWORD;
SCIP: TSendCmdInParams;
SCOP: PSendCmdOutParams;
P: PWORD;
I: Integer;
begin
Result := '';
hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hDevice = INVALID_HANDLE_VALUE then
Exit;
Size := SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1;
SCOP := AllocMem(Size);
SCIP.irDriveRegs.bCommandReg := IDE_ATA_IDENTIFY;
if DeviceIoControl(hDevice, SMART_RCV_DRIVE_DATA, @SCIP, SizeOf(TSendCmdInParams) - 1, SCOP, Size,
cbBytesReturned, nil) = False then
begin
FreeMem(SCOP);
CloseHandle(hDevice);
Exit;
end;
//
with PIdSector(@SCOP^.bBuffer[0])^ do
begin
SetLength(Result, Length(sSerialNumber));
P := @Result[1];
CopyMemory(P, @sSerialNumber[0], Length(sSerialNumber));
for I := 1 to Length(sSerialNumber) div 2 do
begin
P^ := LittleToBig(P^);
Inc(P);
end;
end;
FreeMem(SCOP);
end;
end.