zoukankan      html  css  js  c++  java
  • 获得硬盘的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.
  • 相关阅读:
    SSD
    NMS---非极大值抑制
    检测评价函数 IOU
    Ground Truth
    耿建超英语语法---状语从句
    联合索引创建时候的排序规则
    order by limit的原理
    mysql事务四种隔离级别
    为什么 Redis 快照使用子进程
    MYSQL查询~ 存在一个表而不在另一个表中的数据
  • 原文地址:https://www.cnblogs.com/westsoft/p/8353104.html
Copyright © 2011-2022 走看看