获得硬盘的ID序列号(XE10.1+WIN8.1)

Posted 我的学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获得硬盘的ID序列号(XE10.1+WIN8.1)相关的知识,希望对你有一定的参考价值。

获得硬盘的ID序列号(XE10.1+WIN8.1)

 

相关资料:

https://zhidao.baidu.com/question/195408580.html

 

注意事项:

1.记得右击以管理员运行。

2.SysUtils 在XE中要改为System.SysUtils。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Vcl.Imaging.jpeg;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Memo1: TMemo;
    Button1: TButton;
    Label1: TLabel;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetScsiSerialNumber(const i: smallint): string;
type
  TScsiPassThrough = record
    Length: Word;
    ScsiStatus: Byte;
    PathId: Byte;
    TargetId: Byte;
    Lun: Byte;
    CdbLength: Byte;
    SenseInfoLength: Byte;
    DataIn: Byte;
    DataTransferLength: ULONG;
    TimeOutValue: ULONG;
    DataBufferOffset: DWORD;
    SenseInfoOffset: ULONG;
    Cdb: array[0..15] of Byte;
  end;
  TScsiPassThroughWithBuffers = record
    spt: TScsiPassThrough;
    bSenseBuf: array[0..31] of Byte;
    bDataBuf: array[0..191] of Byte;
  end;
var
  dwReturned: DWORD;
  len: DWORD;
  Buffer: array[0..SizeOf(TScsiPassThroughWithBuffers) + SizeOf(TScsiPassThrough) - 1] of Byte;
  sptwb: TScsiPassThroughWithBuffers absolute Buffer;
  hDevice: thandle;
begin
  Result := \'\';
  if SysUtils.win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    if i = 0 then
      hDevice := CreateFile(\'//./PhysicalDrive0\',
        GENERIC_READ or GENERIC_WRITE,
        FILE_SHARE_READ or FILE_SHARE_WRITE,
        nil, OPEN_EXISTING, 0, 0)
    else
      hDevice := CreateFile(\'//./PhysicalDrive1\',
        GENERIC_READ or GENERIC_WRITE,
        FILE_SHARE_READ or FILE_SHARE_WRITE,
        nil, OPEN_EXISTING, 0, 0);
  end
  else exit;
  if hDevice = invalid_handle_value then exit;
  FillChar(Buffer, SizeOf(Buffer), #0);
  with sptwb.spt do
  begin
    Length := SizeOf(TScsiPassThrough);
    CdbLength := 6; // CDB6GENERIC_LENGTH
    SenseInfoLength := 24;
    DataIn := 1; // SCSI_IOCTL_DATA_IN
    DataTransferLength := 192;
    TimeOutValue := 2;
    DataBufferOffset := PChar(@sptwb.bDataBuf) - PChar(@sptwb);
    SenseInfoOffset := PChar(@sptwb.bSenseBuf) - PChar(@sptwb);
    Cdb[0] := $12; //  OperationCode := SCSIOP_INQUIRY;
    Cdb[1] := $01; //  Flags := CDB_INQUIRY_EVPD;  Vital product data
    Cdb[2] := $80; //  PageCode            Unit serial number
    Cdb[4] := 192; // AllocationLength
  end;
  len := sptwb.spt.DataBufferOffset + sptwb.spt.DataTransferLength;
  if DeviceIoControl(hDevice, $0004D004, @sptwb, SizeOf(TScsiPassThrough), @sptwb, len, dwReturned, nil)
    and ((PChar(@sptwb.bDataBuf) + 1)^ = #$80) then
    SetString(Result, PChar(@sptwb.bDataBuf) + 4, Ord((PChar(@sptwb.bDataBuf) + 3)^));
end;

function GetIdeSerialNumber: pchar;
const IDENTIFY_BUFFER_SIZE = 512;
type
  TIDERegs = packed record
    bFeaturesReg: BYTE;
    bSectorCountReg: BYTE;
    bSectorNumberReg: BYTE;
    bCylLowReg: BYTE;
    bCylHighReg: BYTE;
    bDriveHeadReg: BYTE;
    bCommandReg: BYTE;
    bReserved: BYTE;
  end;
  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;
  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: DWORD;
    wMultSectorStuff: Word;
    ulTotalAddressableSectors: DWORD;
    wSingleWordDMA: Word;
    wMultiWordDMA: Word;
    bReserved: array[0..127] of BYTE;
  end;
  PIdSector = ^TIdSector;
  TDriverStatus = packed record
    bDriverError: Byte;
    bIDEStatus: Byte;
    bReserved: array[0..1] of Byte;
    dwReserved: array[0..1] of DWORD;
  end;
  TSendCmdOutParams = packed record
    cBufferSize: DWORD;
    DriverStatus: TDriverStatus;
    bBuffer: array[0..0] of BYTE;
  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;
var
  hDevice: Thandle;
  cbBytesReturned: DWORD;
  SCIP: TSendCmdInParams;
  aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1) - 1] of Byte;
  IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;
begin
  Result := \'\';
  if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then
    //   Windows   NT,   Windows   2000
    hDevice := CreateFile(\'//./PhysicalDrive0\', GENERIC_READ or GENERIC_WRITE,
      FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0)
  else
    //   Version   Windows   95   OSR2,   Windows   98
    hDevice := CreateFile(\'//./SMARTVSD\', 0, 0, nil, CREATE_NEW, 0, 0);
  if hDevice = INVALID_HANDLE_VALUE then Exit;
  try
    FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);
    FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
    cbBytesReturned := 0;
    with SCIP do begin
      cBufferSize := IDENTIFY_BUFFER_SIZE;
      with irDriveRegs do begin
        bSectorCountReg := 1;
        bSectorNumberReg := 1;
        bDriveHeadReg := $A0;
        bCommandReg := $EC;
      end;
    end;
    if not DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) - 1,
      @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;
  finally
    CloseHandle(hDevice);
  end;
  with PIdSector(@IdOutCmd.bBuffer)^ do begin
    ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
    (Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;
    Result := Pchar(@sSerialNumber);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  stmp:String;
begin
  //记得右击以管理员运行
  stmp := StrPas(PAnsiChar(GetIdeSerialNumber));
  if stmp<>\'\' then
  begin
    Memo1.Lines.Add(\'无参:\' + stmp);
  end
  else
  begin
    stmp := Trim(GetScsiSerialNumber(0));
    Memo1.Lines.Add(\'有参:\' + stmp);
  end;
end;

end.

 

以上是关于获得硬盘的ID序列号(XE10.1+WIN8.1)的主要内容,如果未能解决你的问题,请参考以下文章

Delphi XE10.1 引用计数(Delphi XE10.1 Berlin终于增加了对接口的Weak, UnSafe的支持)

Delphi XE10.1 引用计数

Delphi XE10.1 引用计数

radstudio10keygen怎么破解delphi xe 10.1

发送邮件(XE10.1+WIN764)

咏南中间件+开发框架支持最新的DELPHI XE10.1(BERLIN) UPDATE2