[Delphi] IDE/SATA 하드 디스크 일련 번호 가져오기

인터넷에 이런 코드가 있는데, 단지 비교적 일찍 썼기 때문에, 어떤 부분은 그렇게 간단명료하지 않고, XE 이후의 버전에 문제가 있기 때문이다. (유니코드 문자의 관계 때문)
다음은 수정된 코드를 간소화하고 첫 번째 하드디스크의 시퀀스 번호만 찾으며 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.

좋은 웹페이지 즐겨찾기