zoukankan      html  css  js  c++  java
  • 获取硬盘序列号(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[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;

    {
    获取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[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;
  • 相关阅读:
    前端打印去除水印
    mybatis实现多数据库操作(个人封装注解版本)
    vue项目用hbuilder打包成APP后,返回键退出程序的解决办法
    Java迭代器Iterator的remove()方法的使用
    零基础学Java语言(浙江大学mooc)
    Oracle查询一个字段在哪张表里
    slf4j重定向日志输出
    SpringBoot嵌入pentaho-kettle工具实现数据trans转换和job任务手动执行
    Apache的karaf启动报错
    SpringBoot扩展接口- Bean实例化前后扩展点
  • 原文地址:https://www.cnblogs.com/klaus/p/1957867.html
Copyright © 2011-2022 走看看