【Delphi】获取IDE/SATA硬盘序列号

网上有这种代码了,只是因为写的较早,有些地方写的不那么言简意赅,而且在XE后的版本中有问题(因为Unicode字符的关系)

下面是精简修改过的代码,只取第一块硬盘的序列号,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.


 

你可能感兴趣的:(Delphi,Windows编程)