获得硬盘的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.