[DELPHI] OBTER SERIAL HD

O serial físico do HD é uma identificação única desta peça de hardware e não tem formato definido, isto é, cada fabricante tem seu próprio modelo de seriais. Alguns usam apenas números, outros letras e números, o que vale mesmo é que, dentro de um mesmo fabricante, é IMPOSSÍVEL que existam dois seriais iguais e entre fabricantes diferentes, é IMPROVÁVEL que existam dois seriais idênticos. Estas características tornam este serial uma informação extremamente útil quando se quer identificar uma máquina como um todo. Outra característica importante desses seriais é que eles não podem ser alterados ou clonados de nenhuma forma.

procedure TForm1.Button1Click(Sender: TObject);
begin
 showmessage(GetIdeDiskSerialNumber);
end;

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;

//função que pega o serial FÍSICO do HD e retorna string 
function TfrmWindows.GetIdeDiskSerialNumber: String;
type
  TSrbIoControl = packed record
    HeaderLength: ULONG;
    Signature: Array [0 .. 7] of char;
    Timeout: ULONG;
    ControlCode: ULONG;
    ReturnCode: ULONG;
    length: ULONG;
  end;

  SRB_IO_CONTROL = TSrbIoControl;
  PSrbIoControl = ^TSrbIoControl;

  TIDERegs = packed record
    bFeaturesReg: byte; // especificar "comandos" SMART
    bSectorCountReg: byte; // registro de contador de setor
    bSectorNumberReg: byte; // registro de número de setores
    bCylLowReg: byte; // valor de cilindro (byte mais baixo)
    bCylHighReg: byte; // valor de cilindro (byte mais alto)
    bDriveHeadReg: byte; // registro de drive/cabeça
    bCommandReg: byte; // comando IDE
    bReserved: byte; // reservado- tem que ser zero
  end;

  IDEREGS = TIDERegs;
  PIDERegs = ^TIDERegs;

  TSendCmdInParams = packed record
    cBufferSize: DWORD;
    irDriveRegs: TIDERegs;
    bDriveNumber: byte;
    bReserved: Array [0 .. 2] of byte;
    dwReserved: Array [0 .. 3] of DWORD;
    bBuffer: Array [0 .. 0] of byte;
  end;

  SENDCMDINPARAMS = TSendCmdInParams;
  PSendCmdInParams = ^TSendCmdInParams;

  TIdSector = packed record
    wGenConfig: word;
    wNumCyls: word;
    wReserved: word;
    wNumHeads: word;
    wBytesPerTrack: word;
    wBytesPerSector: word;
    wSectorsPerTrack: word;
    wVendorUnique: Array [0 .. 2] of word;
    sSerialNumber: Array [0 .. 19] of char;
    wBufferType: word;
    wBufferSize: word;
    wECCSize: word;
    sFirmwareRev: Array [0 .. 7] of char;
    sModelNumber: Array [0 .. 39] of char;
    wMoreVendorUnique: word;
    wDoubleWordIO: word;
    wCapabilities: word;
    wReserved1: word;
    wPIOTiming: word;
    wDMATiming: word;
    wBS: word;
    wNumCurrentCyls: word;
    wNumCurrentHeads: word;
    wNumCurrentSectorsPerTrack: word;
    ulCurrentSectorCapacity: ULONG;
    wMultSectorStuff: word;
    ulTotalAddressableSectors: ULONG;
    wSingleWordDMA: word;
    wMultiWordDMA: word;
    bReserved: Array [0 .. 127] of byte;
  end;

  PIdSector = ^TIdSector;
const
  IDE_ID_FUNCTION = $EC;
  IDENTIFY_BUFFER_SIZE = 512;
  DFP_RECEIVE_DRIVE_DATA = $0007C088;
  IOCTL_SCSI_MINIPORT = $0004D008;
  IOCTL_SCSI_MINIPORT_IDENTIFY = $001B0501;
  DataSize = SizeOf(TSendCmdInParams) - 1 + IDENTIFY_BUFFER_SIZE;
  BufferSize = SizeOf(SRB_IO_CONTROL) + DataSize;
  W9xBufferSize = IDENTIFY_BUFFER_SIZE + 16;
var
  hDevice: THandle;
  cbBytesReturned: DWORD;
  pInData: PSendCmdInParams;
  pOutData: pointer; // PSendCmdOutParams
  Buffer: Array [0 .. BufferSize - 1] of byte;
  srbControl: TSrbIoControl absolute Buffer;
begin
  result := '';
  FillChar(Buffer, BufferSize, #0);
  // Windows NT, Windows 2000, Windows XP
  if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    // recuperar handle da porta SCSI
    hDevice := CreateFile('\\.\Scsi0:',
      // Nota: '\\.\C:' precisa de privilégios administrativos
      GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
    if hDevice = INVALID_HANDLE_VALUE then
      exit;
    try
      srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);
      System.Move('SCSIDISK', srbControl.Signature, 8);
      srbControl.Timeout := 2;
      srbControl.length := DataSize;
      srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;
      pInData := PSendCmdInParams(PChar(@Buffer) + SizeOf(SRB_IO_CONTROL));
      pOutData := pInData;
      with pInData^ do
      begin
        cBufferSize := IDENTIFY_BUFFER_SIZE;
        bDriveNumber := 0;
        with irDriveRegs do
        begin
          bFeaturesReg := 0;
          bSectorCountReg := 1;
          bSectorNumberReg := 1;
          bCylLowReg := 0;
          bCylHighReg := 0;
          bDriveHeadReg := $A0;
          bCommandReg := IDE_ID_FUNCTION;
        end;
      end;
      if not DeviceIoControl(hDevice, IOCTL_SCSI_MINIPORT, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil) then
        exit;
    finally
      CloseHandle(hDevice);
    end;
  end
  else
  begin
    // Windows 95 OSR2, Windows 98, Windows ME
    hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
    if hDevice = INVALID_HANDLE_VALUE then
      exit;
    try
      pInData := PSendCmdInParams(@Buffer);
      pOutData := @pInData^.bBuffer;
      with pInData^ do
      begin
        cBufferSize := IDENTIFY_BUFFER_SIZE;
        bDriveNumber := 0;
        with irDriveRegs do
        begin
          bFeaturesReg := 0;
          bSectorCountReg := 1;
          bSectorNumberReg := 1;
          bCylLowReg := 0;
          bCylHighReg := 0;
          bDriveHeadReg := $A0;
          bCommandReg := IDE_ID_FUNCTION;
        end;
      end;
      if not DeviceIoControl(hDevice, DFP_RECEIVE_DRIVE_DATA, pInData, SizeOf(TSendCmdInParams) - 1, pOutData, W9xBufferSize, cbBytesReturned, nil) then
        exit;
    finally
      CloseHandle(hDevice);
    end;
  end;
  with PIdSector(PChar(pOutData) + 16)^ do
  begin
    ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
    SetString(result, sSerialNumber, SizeOf(sSerialNumber));
  end;
end;

Gostou? Deixe seu comentário... Convido você a seguir meu blog, sua presença é bem vinda!【ツ】

Nenhum comentário:

Postar um comentário