CARRIE 发表于 2014-3-4 15:52:41

获取硬盘序列号(IDE,SATA,SCSI)强大的源码

{
获取SCSI硬盘出厂系列号
需要系统管理员权限,不支持磁盘阵列
这里只取了第0个或第1个硬盘的序列号
}
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 of Byte;
end;
TScsiPassThroughWithBuffers = record
    spt: TScsiPassThrough;
    bSenseBuf: array of Byte;
    bDataBuf: array of Byte;
end;
var
dwReturned: DWORD;
len: DWORD;
Buffer: array 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 := $12; //OperationCode := SCSIOP_INQUIRY;
    Cdb := $01; //Flags := CDB_INQUIRY_EVPD;Vital product data
    Cdb := $80; //PageCode            Unit serial number
    Cdb := 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;

{
获取IDE和SATA硬盘出厂系列号
需要系统管理员权限,不支持磁盘阵列
这里只取了第0个硬盘的序列号,要取其它硬盘只需要改变PhysicalDrive0后的数字
}
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 of Byte;
    dwReserved: array of DWORD;
    bBuffer: array of Byte;
end;
TIdSector = packed record
    wGenConfig: Word;
    wNumCyls: Word;
    wReserved: Word;
    wNumHeads: Word;
    wBytesPerTrack: Word;
    wBytesPerSector: Word;
    wSectorsPerTrack: Word;
    wVendorUnique: array of Word;
    sSerialNumber: array of CHAR;
    wBufferType: Word;
    wBufferSize: Word;
    wECCSize: Word;
    sFirmwareRev: array of Char;
    sModelNumber: array 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 of BYTE;
end;
PIdSector = ^TIdSector;
TDriverStatus = packed record
    bDriverError: Byte;
    bIDEStatus: Byte;
    bReserved: array of Byte;
    dwReserved: array of DWORD;
end;
TSendCmdOutParams = packed record
    cBufferSize: DWORD;
    DriverStatus: TDriverStatus;
    bBuffer: array 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 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;

tiandihuike 发表于 2016-4-10 20:15:53

谢谢分享 ,已试过有效果

耕望平所 发表于 2019-7-14 18:35:04

哦~~~~











static/image/common/sigline.gif
房产资讯新闻信息
房地产资讯新闻信息
房价资讯新闻信息
页: [1]
查看完整版本: 获取硬盘序列号(IDE,SATA,SCSI)强大的源码