unit JyDiskInfoDll;

interface
uses Windows, SysUtils, Classes;
{$IFDEF CPUX64}
const dllname = 'JyDisk64.dll';
{$else}
const dllname = 'JyDisk.dll';
{$endif}
type
  {$Z4+} //枚举4字节对齐 和vc一致//hsj 2017-09-21
  HOST_READS_WRITES_UNIT =
    (
    HOST_READS_WRITES_UNKNOWN = 0,
    HOST_READS_WRITES_512B,
    HOST_READS_WRITES_32MB,
    HOST_READS_WRITES_GB);
  INTERFACE_TYPE = (
    INTERFACE_TYPE_UNKNOWN = 0,
    INTERFACE_TYPE_PATA,
    INTERFACE_TYPE_SATA,
    INTERFACE_TYPE_USB,
    INTERFACE_TYPE_IEEE1394,
    INTERFACE_TYPE_UASP,
    INTERFACE_TYPE_SCSI,
    INTERFACE_TYPE_NVME);
  VENDOR_ID =
    (
    HDD_GENERAL = 0,
    SSD_GENERAL = 1,
    SSD_VENDOR_MTRON = 2,
    SSD_VENDOR_INDILINX = 3,
    SSD_VENDOR_JMICRON = 4,
    SSD_VENDOR_INTEL = 5,
    SSD_VENDOR_SAMSUNG = 6,
    SSD_VENDOR_SANDFORCE = 7,
    SSD_VENDOR_MICRON = 8,
    SSD_VENDOR_OCZ = 9,
    HDD_SSD_VENDOR_SEAGATE = 10,
    HDD_VENDOR_WESTERN_DIGITAL = 11,
    SSD_VENDOR_PLEXTOR = 12,
    SSD_VENDOR_SANDISK = 13,
    SSD_VENDOR_OCZ_VECTOR = 14,
    HDD_SSD_VENDOR_TOSHIBA = 15,
    SSD_VENDOR_CORSAIR = 16,
    SSD_VENDOR_KINGSTON = 17,
    SSD_VENDOR_MICRON_MU02 = 18,
    SSD_VENDOR_NVME = 19,
    SSD_VENDOR_MAX = 99,

    VENDOR_UNKNOWN = $0000,
    USB_VENDOR_BUFFALO = $0411,
    USB_VENDOR_IO_DATA = $04BB,
    USB_VENDOR_LOGITEC = $0789,
    USB_VENDOR_INITIO = $13FD,
    USB_VENDOR_SUNPLUS = $04FC,
    USB_VENDOR_JMICRON = $152D,
    USB_VENDOR_CYPRESS = $04B4,
    USB_VENDOR_OXFORD = $0928,
    USB_VENDOR_PROLIFIC = $067B,
    USB_VENDOR_ALL = $FFFF);
   
  byteArr6 = array[0..5] of Byte;
  JyHDiskInfo = record
    IsSmartSupported: Boolean; //获取smart是否成功
    IsApmSupported: Boolean;
    IsApmEnabled: Boolean;
    IsAamSupported: Boolean;
    IsAamEnabled: Boolean;
    IsLba48Supported: Boolean;
    IsNcqSupported: Boolean;
    IsNvCacheSupported: Boolean;
    IsTrimSupported: Boolean;
    IsSsd: Boolean;
    IsDeviceSleepSupported: Boolean;
    IsMaxtorMinute: Boolean;
    IsRawValues8: Boolean;
    IsRawValues7: Boolean;
    DetectedTimeUnitType: Cardinal;

    ModelNumber: array[0..39] of ansichar; //硬盘名称
    FirmwareRev: array[0..7] of ansichar; //固件版本号
    SerialNumber: array[0..19] of ansichar; //序列号

    //bVersion: Byte; // Binary driver version.
    //bRevision: Byte; // Binary driver revision.
    //fCapabilities: DWORD;
    Cylinders: int64;
    Heads: DWORD;
    BytesPerSector: DWORD;
    SectorsPerTrack: dWORD;
    TracksPerCylinder: DWORD;
    disksize: int64;
    Temperature: Integer; //温度
    PowerOnTime: Integer; //通电时间
    PowerOnCount: Integer; //通电次数
    RotationRate: Word; //转速
    BufferSize: dWord; //缓存大小
    HostWrites: Int64; //主机写入量总计-扇区数
    HostReads: Int64; //主机读取量总计-扇区数
    CurrentTransferMode: array[0..255] of ansichar; // ShortString;
    MaxTransferMode: array[0..255] of ansichar; // ShortString;
    Interface_: array[0..255] of ansichar; // ShortString;

    TransferModeType: DWORD;
    Major: Cardinal;
    Life: Int64;
    MajorVersion: array[0..255] of ansichar; // ShortString;
    MinorVersion: array[0..255] of ansichar; // ShortString;
    SmartKeyName: array[0..255] of ansichar; // ShortString;
    SsdVendorString: array[0..255] of ansichar; // ShortString;
    SmartCount: integer;
    ItemId: array[0..29] of Byte;
    CurrentValue: array[0..29] of Byte;
    WorstValue: array[0..29] of Byte;
    ThresholdValue: array[0..29] of Byte;
    DataValue: array[0..29] of int64;
    DataValueArr: array[0..29] of byteArr6;
    State: array[0..29] of byte;
    StatusFlags: array[0..29] of byte;
    InterfaceType: INTERFACE_TYPE;
    HostReadsWritesUnit: HOST_READS_WRITES_UNIT;

    DiskVendorId: VENDOR_ID;
    //IdOutCmd: array[1..sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1] of Byte;
    //AttrOutCmd: array[1..sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1] of Byte;
    //ThreshOutCmd: array[1..sizeof(SENDCMDOUTPARAMS) + READ_THRESHOLD_BUFFER_SIZE - 1] of Byte;
  end;
procedure FreeJyDiskDll; //释放动态库
procedure InitJyDiskDll(); //动态库初始化
procedure DoReg(User, regid: ansistring); //注册控件
function IsRegisted(): Boolean; //判断控件是否成功注册
//以admin用户运行
function RunAsAdmin: boolean;
//得磁盘序号
function GetDiskIndex(drive: ansiChar): Integer;
function GetDiskSerialNumber(drive: ansiChar;PNPDeviceID:Bool=false): ansistring; overload;
function GetDiskSerialNumber(index: integer;PNPDeviceID:Bool=false): ansistring; overload;
//0--硬盘，1--移动硬盘，2--u盘
function GetDiskTypeStr(itype: integer): widestring;
function GetDiskType(drive: ansiChar): Integer; overload;
function GetDiskType(i: integer): Integer; overload;
//得物理设备个数

function GetPhysicalDriveCount(st: tstrings): Integer;
//得物理磁盘对应的分区盘符

function GetDiskDrive(PhysicalDriveId: integer): string;
//得当前可用的盘符

function GetDriverList: string;
//得物理设备分区数,设备号从0开始，0为第1个

function GetPhysicalDrivePartitionCount(PhysicalDriveId: Integer): integer;
//得硬盘分区序号,从0开始,-1为非物理硬盘
function GetHardDiskPartitionInfo(const DriveLetter: ansiChar;
  var VolumeName, VolumeSerialNumber, PartitionType: ansistring;
  var TotalSpace, TotalFreeSpace: int64): boolean;
//得硬盘分区序号,从1开始,0为非物理硬盘
function GetDiskPartitionIndex(drive: ansiChar): Integer;
//得smart信息
function GetDiskInfo(index: integer; var ainfo: JyHDiskInfo): boolean;
//得smart信息项目对应的中文名称

function GetSmartItemAttribName(const anId: Integer): string;
//0未知,1良好,2异常,3警告

function getStateStr(i: Integer): string;

function JyStringLink(s1, s2: string; fgf: string = ' '): string;

function GetMd5String(ins: ansistring): ansistring;
function GetCpuID(): string;
function GetBiosID(): string;
function GetDisplayDeviceID():string;
function GetIP():string;
function GetMacAddr():string;
function IsWin64: boolean;
//函数初始化
procedure Init;

function getUsbPNPDeviceID(drive: ansichar): ansistring;overload;
function getUsbPNPDeviceID(index: integer): ansistring;overload;
//得磁盘容量
function GetDiskSize(index: Integer = 0): Int64; overload;
function GetDiskSize(drv: AnsiChar): Int64; overload;

function GetDiskName(index:integer):Ansistring;overload;
function GetDiskName(drive:AnsiChar):Ansistring;overload;
implementation
//{$DEFINE for_vb}
var hdll: NativeUInt = 0;
var getDiskSerialNumber_1: procedure(drive: ansiChar;  pout: PAnsiChar; var poutsize: integer;PNPDeviceID:bool=false); stdcall; //{$IFDEF for_vb}var{$ENDIF}pout: PAnsiChar;
  getDiskSerialNumber_2: procedure(index: integer;  pout: PAnsiChar; var poutsize: integer;PNPDeviceID:bool=false); stdcall; //{$IFDEF for_vb}var{$ENDIF}pout
  getDiskType_1: function(drive: ansiChar): Integer; stdcall;
  getDiskType_2: function(i: Integer): Integer; stdcall;
  getDiskIndex_: function(drive: ansiChar): Integer; stdcall;
  doReg_: procedure(fuser: PansiChar; usersize: integer; fregid: PansiChar; regidsize: integer); stdcall;
  isRegisted_: function(): bool; stdcall;
  getDiskTypeStr_: procedure(i: integer;  pout: PwideChar; var poutsize: integer); stdcall; //{$IFDEF for_vb}var{$ENDIF}pout
  getPhysicalDriveCount_: function(pout: PAnsiChar; var poutsize: integer): Integer; stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  runAsAdmin_: function(): bool; stdcall;
  getDiskDrive_: procedure(PhysicalDriveId: integer;  pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  getDriverList_: procedure(pout: PAnsiChar; var poutsize: integer); stdcall; //{$IFDEF for_vb}var{$ENDIF}pout
  getPhysicalDrivePartitionCount_: function(PhysicalDriveId: Integer): integer; stdcall;
  getDiskPartitionIndex_: function(drive: ansiChar): Integer; stdcall;
  getHardDiskPartitionInfo_: function(const DriveLetter: ansiChar;
    VolumeName: PAnsiChar; var VolumeNameSize: Integer;//{$IFDEF for_vb}var{$ENDIF}VolumeName
    VolumeSerialNumber: PAnsiChar; var VolumeSerialNumberSize: Integer;//{$IFDEF for_vb}var{$ENDIF}VolumeSerialNumber
    PartitionType: PAnsiChar;//{$IFDEF for_vb}var{$ENDIF}PartitionType
    var PartitionTypeSize: Integer; var TotalSpace, TotalFreeSpace: int64): bool; stdcall;
  getDiskInfo_: function(index: integer; var ainfo: JyHDiskInfo): bool; stdcall;
  getMd5String_: procedure(pin: pansichar; pinsize: integer; pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  getCpuID_: procedure(pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  getBiosID_: procedure(pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  getDisplayDeviceID_: procedure(pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  getIP_: procedure(pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  getMacAddr_: procedure(pout: PAnsiChar; var poutsize: integer); stdcall;//{$IFDEF for_vb}var{$ENDIF}pout
  isWin64_: function(): bool; stdcall;
  init_: procedure(); stdcall;
  getUsbPNPDeviceID_1:procedure(d: ansichar;pout: PAnsiChar; var poutsize: integer);stdcall;
  getUsbPNPDeviceID_2:procedure(index: integer;pout: PAnsiChar; var poutsize: integer);stdcall;
  getDiskSize_1:function(d: ansichar):int64;stdcall;
  getDiskSize_2:function(index: integer):int64;stdcall;
  getDiskName_1:procedure(d: ansichar;pout: PAnsiChar; var poutsize: integer);stdcall;
  getDiskName_2:procedure(index: integer;pout: PAnsiChar; var poutsize: integer);stdcall;
procedure Init();
begin
  Init_();
end;
//注册控件

procedure DoReg(User, regid: ansistring);
begin
  DoReg_(@User[1], Length(User), @regid[1], Length(regid));
end;
//判断控件是否成功注册

function IsRegisted(): Boolean;
begin
  result := IsRegisted_();
end;
//0未知,1良好,2异常,3警告

function getStateStr(i: Integer): string;
begin
  case i of
    1: result := '良好';
    2: result := '异常';
    3: result := '警告';
  else
    result := '';
  end;
end;
//得smart信息项目对应的中文名称

function GetSmartItemAttribName(const anId: Integer): string;
{begin
  case anId of     //翻译得不准确，不过找不到中文资料
      0: Result := 'No Attribute Here       ';
      1: Result := '数据读取错误率';
      2: Result := '吞吐量';
      3: Result := '电机启动时间';
      4: Result := '电机启动/停止次数';
      5: Result := '重定位扇区次数';
      6: Result := 'Read Channel Margin';
      7: Result := '寻道错误率';
      8: Result := '寻道时间性能';
      9: Result := '磁盘上电时间';
     10: Result := '电机起动重试次数';
     11: Result := '校正重试次数 ';
     12: Result := '电源开关次数';
     13, 201: Result := '软件读取错误率';
    192,225: Result := '电源关闭次数';
    193: Result := '磁头归位次数';
    194, 231: Result := '温度';
    195: Result := '硬件ECC恢复';
    196: Result := '重定位事件次数';
    197: Result := '当前等待扇区数';
    198: Result := '无法纠正扇区数';
    199: Result := 'UDMA CRC 错误数';
    200: Result := '写入数据错误率';
    202: Result := 'DAM错误数';
    206: Result := '磁头悬浮高度';
    240: Result := '磁头悬浮时间';
    else
      Result := '未知属性';
 end;
{
0 00h Invalid Invalid attribute identifier
1 01h 数据读取错误率   从磁盘读取原始数据的出错频率
2 02h 吞吐量 磁盘平均读写效率
3 03h 启动时间 启动旋转所需时间
4 04h Start/Stop count Number of spindle start/stop cycles
5 05h Reallocated sector count Quantity of remapped sectors
6 06h Read channel margin Reserve of channel while reading
7 07h Seek error rate Frequency of errors while positioning
8 08h Seek timer performance Average efficiency of operations while  positioning
9 09h Power-on hours count Number of hours elapsed in the power-on state
10 0Ah Spinup retry count Number of retry attempts to spin up
11 0Bh Calibration retry count Number of attempts to calibrate the device
12 0Ch Power cycle count Number of power-on events
13 0Dh Soft read error rate Frequency of ‘program’ errors while reading
from a disk
187 BBh vendor-specific vendor-specific
189 BDh vendor-specific vendor-specific
190 BEh vendor-specific vendor-specific
191 BFh G-sense error rate Fequency of mistakes as a result of impact
loads
192 C0h Power-off retract count         Number of power-off or emergency retract cycles
193 C1h Load/Unload cycle count         Number of cycles into landing zone position
194 C2h HDA temperature                 Temperature of a hard disk assembly
195 C3h Hardware ECC recovered Number of ECC on-the-fly errors
196 C4h Reallocation count Number of remapping operations
197 C5h Current pending sector count   Number of unstable sectors (waiting for
remapping)
198 C6h Offline scan uncorrectable count   Number of uncorrected errors
199 C7h UDMA CRC error rate Number of CRC errors during UDMA mode
200 C8h Write error rate Number of errors while writing to disk (or)
multi-zone error rate (or)
flying height
201 C9h Soft read error rate Number of off-track errors
202 Cah Data Address Mark errors Number of Data Address Mark (DAM) errors
(or) vendor-specific
203 CBh Run out cancel Number of ECC errors
204 CCh Soft ECC correction Number of errors corrected by software ECC
205 CDh Thermal asperity rate
(TAR)
Number of thermal asperity errors
206 CEh Flying height Height of heads above the disk surface
207 CFh Spin high current Amount of high current used to spin up the
drive
208 D0h Spin buzz Number of buzz routines to spin up the drive
209 D1h Offline seek performance Drive’s seek performance during offline
operations
220 DCh Disk shift            Shift of disk is possible as a result of strong
shock loading in the store, as a result of falling
(or) temperature
221 DDh G-sense error rate Number of errors as a result of impact loads
as detected by a shock sensor
222 DEh Loaded hours Number of hours in general operational state
223 DFh Load/unload retry count Loading on drive caused by numerous
recurrences of operations, like reading,
recording, positioning of heads, etc.
224 E0h Load friction Load on drive caused by friction in mechanical
parts of the store
225 E1h Load/Unload cycle count Total number of load cycles
226 E2h Load-in time General time for loading in a drive
227 E3h Torque amplification count Quantity efforts of the rotating moment of a
drive
228 E4h Power-off retract count Number of power-off retract events.
230 E6h GMR head amplitude Amplitude of heads trembling (GMR-head) in
running mode
231 E7h Temperature Temperature of a drive
240 F0h Head flying hours Time while head is positioning
250 FAh Read error retry rate Number of errors while reading from a disk

}
//function GetSmartCodeName(): string;
var code: string;
begin
  result := '未知属性'; //返回空就是不关心的参数,可不管
  code := IntToHex(anId, 2);
  if code = '01' then result := '(底层)数据读取错误率';
  if code = '02' then result := '吞吐性能(读写通量性能)'; //，数据值越大越好
  if code = '03' then result := '马达旋转到标准转速所需时间';
  if code = '04' then result := '马达启动/停止转速';
  if code = '05' then result := '重映射扇区计数';
  if code = '06' then result := '读取通道边界'; //这一项功能不明，现在的硬盘也不显示这一项
  if code = '07' then result := '寻道错误率';
  if code = '08' then result := '寻道时间性能';
  if code = '09' then result := '累计通电时间计数';
  if code = '0A' then result := '马达重试计数';
  if code = '0B' then result := '校准重试计数';
  if code = '0C' then result := '通电周期计数';
  if code = '0D' then result := '软件读出误码率';
  if code = 'AA' then result := '读写失败的块增长的总数';
  if code = 'AB' then result := 'Flash编程失败块的数量';
  if code = 'AC' then result := '擦写失败块的数量';
  if code = 'AD' then result := '所有好块的平均擦写次数';
  if code = 'AE' then result := '硬盘自启用后发生意外断电事件的次数';
  if code = 'B1' then result := '磨损最重的块与磨损最轻的块的磨损百分比之差';
  if code = 'B3' then result := '已使用的保留块计数(总计)';
  if code = 'B4' then result := '尚未使用的预留的存储单元数量';
  if code = 'B5' then result := '已编程失败的次数，与（AB）参数相似';
  if code = 'B5' then result := '非4KB对齐访问数';
  if code = 'B6' then result := '硬盘自启用后块擦写失败的次数，与（AC）参数相似';
  if code = 'B7' then result := 'SATA降档错误计数';
  if code = 'B8' then result := '端到端错误';
  if code = 'B9' then result := '磁头稳定性'; //意义不明
  if code = 'BA' then result := '感应运算振动检测';
  if code = 'BB' then result := '反馈无法校正的错误';
  if code = 'BC' then result := '指令超时';
  if code = 'BD' then result := '统计了写入时磁头飞行高度出现偏差的次数/出厂坏块计数';
  //if code = 'BD' then result := '';
  if code = 'BE' then result := '硬盘内部盘片表面的气流温度';
  if code = 'BF' then result := '硬盘受到机械冲击导致出错的频度';
  if code = 'C0' then result := '断电磁头缩回计数';
  if code = 'C1' then result := '磁头执行加载/卸载操作的累计次数';
  if code = 'C2' then result := '硬盘内部的当前温度';
  if code = 'C3' then result := '磁头在盘片上读写时通过ECC技术校正错误的次数';
  if code = 'C4' then result := '重新分配事件计数';
  if code = 'C5' then result := '目前待映射扇区数';
  if code = 'C6' then result := '无法校正扇区数';
  if code = 'C7' then result := 'Ultra DMA CRC 错误计数';
  if code = 'C8' then result := '多区域错误率';
  if code = 'C9' then result := '软读出误码率';
  if code = 'CA' then result := '数据地址标记错误';
  if code = 'CB' then result := '错误检查和纠正（ECC）出错的频度';
  if code = 'CC' then result := '通过软件ECC纠正错误的计数';
  if code = 'CD' then result := '由超温导致的错误';
  if code = 'CE' then result := '磁头距离盘片表面的垂直距离';
  if code = 'CF' then result := '主轴电机运行时出现浪涌电流的次数';
  if code = 'D0' then result := '电力不足马达重试计数';
  if code = 'D1' then result := '离线寻轨性能';
  if code = 'D2' then result := '通常数据值为0，意义不明';
  if code = 'D3' then result := '写入数据时受到受到外部振动的记录';
  if code = 'D4' then result := '写入数据时受到受到外部机械冲击的记录';
  if code = 'DC' then result := '硬盘中的盘片相对主轴的偏移量';
  if code = 'DD' then result := '震动侦测错误率';
  if code = 'DE' then result := '作业时间';
  if code = 'DF' then result := '磁头升降重试次数';
  if code = 'E0' then result := '加载摩擦';
  if code = 'E1' then result := '磁头升降周期计数';
  if code = 'E2' then result := '载入时间';
  if code = 'E3' then result := '扭矩放大计数';
  if code = 'E4' then result := '断电磁头缩回周期';
  if code = 'E6' then result := '巨磁电阻头振幅';
  if code = 'E7' then result := '温度';
  if code = 'E8' then result := '硬盘已擦写次数与设计最大可擦写次数的百分比';
  if code = 'E9' then result := '加电时间/介质耗损指标'; //对于普通硬盘来说，这一项与（09）相同
  if code = 'EB' then result := '不安全关闭计数';
  if code = 'F0' then result := '磁头位于工作位置的时间';
  if code = 'F1' then result := 'LBA写入数的累计';
  if code = 'F2' then result := 'LBA读取数的累计';
  if code = 'FA' then result := '从磁盘上读取时出错的次数';

  if code = 'FE' then result := '自由坠落保护装置动作的次数';

end;
//以admin用户运行

function RunAsAdmin: boolean;
begin
  Result := RunAsAdmin_();
end;
function IsWin64: boolean;
begin
  Result := IsWin64_();
end;
//0--硬盘，1--移动硬盘，2--u盘

function GetDiskTypeStr(itype: integer): widestring;
var i, sz: Integer;
  p: pwideChar;
begin
  result := '';
  getmem(p, 255);
  try
    GetDiskTypeStr_(itype, p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;

function GetDiskType(drive: ansiChar): Integer;
begin
  result := GetDiskType_1(drive);
end;

function GetDiskType(i: integer): Integer;
begin
  result := GetDiskType_2(i);
end;
//得硬盘分区序号,从1开始,0为非物理硬盘

function GetDiskPartitionIndex(drive: ansiChar): Integer;
begin
  result := GetDiskPartitionIndex_(drive);
end;
//得物理设备个数

function GetPhysicalDriveCount(st: tstrings): Integer;
var sz, i: Integer;
  p: pansiChar;
  s: string;
begin
  getmem(p, 512);
  try
    result := GetPhysicalDriveCount_(p, sz);
    s := '';
    for i := 1 to sz do
    begin
      s := s + p[i - 1];
    end;
    st.Delimiter := ',';
    st.DelimitedText := s;
  finally
    freemem(p);
  end;
end;
//得磁盘序号

function GetDiskIndex(drive: ansiChar): Integer;
begin
  result := GetDiskIndex_(drive);
end;

function GetDiskSerialNumber(drive: ansiChar;PNPDeviceID:bool): ansistring;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 255);
  try
    GetDiskSerialNumber_1(drive, p, sz,PNPDeviceID);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;

function GetDiskSerialNumber(index: integer;PNPDeviceID:bool): ansistring;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 255);
  try
    GetDiskSerialNumber_2(index, p, sz,PNPDeviceID);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;
//得硬盘分区序号,从0开始,-1为非物理硬盘

function GetHardDiskPartitionInfo(const DriveLetter: ansiChar;
  var VolumeName, VolumeSerialNumber, PartitionType: ansistring;
  var TotalSpace, TotalFreeSpace: int64): boolean;
var pVolumeName, pVolumeSerialNumber, pPartitionType: pAnsiChar;
  pVolumeNameSize, pVolumeSerialNumberSize, pPartitionTypeSize: Integer;
  i: Integer;
begin
  VolumeName := '';
  VolumeSerialNumber := '';
  PartitionType := '';
  TotalSpace := 0;
  TotalFreeSpace := 0;
  getmem(pVolumeName, 255);
  try
    getmem(pVolumeSerialNumber, 255);
    try
      getmem(pPartitionType, 255);
      try
        result := GetHardDiskPartitionInfo_(DriveLetter, pVolumeName, pVolumeNameSize, pVolumeSerialNumber, pVolumeSerialNumberSize, pPartitionType, pPartitionTypeSize, TotalSpace, TotalFreeSpace);
        for i := 1 to pVolumeNameSize do
        begin
          VolumeName := VolumeName + pVolumeName[i - 1];
        end;
        for i := 1 to pVolumeSerialNumberSize do
        begin
          VolumeSerialNumber := VolumeSerialNumber + pVolumeSerialNumber[i - 1];
        end;
        for i := 1 to pPartitionTypeSize do
        begin
          PartitionType := PartitionType + pPartitionType[i - 1];
        end;
      finally
        freemem(pPartitionType);
      end;
    finally
      freemem(pVolumeSerialNumber);
    end;
  finally
    freemem(pVolumeName);
  end;
end;
//得物理磁盘对应的分区盘符

function GetDiskDrive(PhysicalDriveId: integer): string;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 11);
  try
    GetDiskDrive_(PhysicalDriveId, p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;
//得当前可用的盘符

function GetDriverList: string;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 26);
  try
    GetDriverList_(p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;
//得物理设备分区数,设备号从0开始，0为第1个

function GetPhysicalDrivePartitionCount(PhysicalDriveId: Integer): integer;
begin
  Result := GetPhysicalDrivePartitionCount_(PhysicalDriveId);
end;
//得smart信息

function GetDiskInfo(index: integer; var ainfo: JyHDiskInfo): boolean;
begin
  Result := GetDiskInfo_(index, ainfo);
end;

function GetMd5String(ins: ansistring): ansistring;
var pout: pansiChar;
  i, poutsize: integer;
begin
  result := '';
  getmem(pout, 100);
  try
    GetMd5String_(@ins[1], length(ins), pout, poutsize);
    for i := 1 to poutsize do
    begin
      result := result + pout[i - 1];
    end;
  finally
    freemem(pout);
  end;
end;

function GetCpuID(): string;
var pout: pansiChar;
  i, poutsize: integer;
begin
  result := '';
  getmem(pout, 1000);
  try
    GetCpuID_(pout, poutsize);
    for i := 1 to poutsize do
    begin
      result := result + pout[i - 1];
    end;
  finally
    freemem(pout);
  end;
end;
function GetBiosID(): string;
var pout: pansiChar;
  i, poutsize: integer;
begin
  result := '';
  getmem(pout, 1000);
  try
    GetBiosID_(pout, poutsize);
    for i := 1 to poutsize do
    begin
      result := result + pout[i - 1];
    end;
  finally
    freemem(pout);
  end;
end;
function GetDisplayDeviceID(): string;
var pout: pansiChar;
  i, poutsize: integer;
begin
  result := '';
  getmem(pout, 1000);
  try
    GetDisplayDeviceID_(pout, poutsize);
    for i := 1 to poutsize do
    begin
      result := result + pout[i - 1];
    end;
  finally
    freemem(pout);
  end;
end;
function GetIP(): string;
var pout: pansiChar;
  i, poutsize: integer;
begin
  result := '';
  getmem(pout, 1000);
  try
    GetIP_(pout, poutsize);
    for i := 1 to poutsize do
    begin
      result := result + pout[i - 1];
    end;
  finally
    freemem(pout);
  end;
end;
function GetMacAddr(): string;
var pout: pansiChar;
  i, poutsize: integer;
begin
  result := '';
  getmem(pout, 1000);
  try
    GetMacAddr_(pout, poutsize);
    for i := 1 to poutsize do
    begin
      result := result + pout[i - 1];
    end;
  finally
    freemem(pout);
  end;
end;
function JyStringLink(s1, s2: string; fgf: string = ' '): string;
begin
  result := '';
  if (s1 = '') and (s2 = '') then Exit;
  if s1 = '' then
  begin
    result := s2;
    Exit;
  end;
  if s2 = '' then
  begin
    result := s1;
    Exit;
  end;
  result := s1 + fgf + s2;
end;

function GetCurrentPath: string;
var
  current_path: string;
begin
  current_path := ExtractFilePath(paramstr(0));
  if current_path[Length(current_path)] <> '\' then
    current_path := current_path + '\';
  Result := current_path;
end;

function getUsbPNPDeviceID(drive: ansiChar): ansistring;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 255);
  try
    getUsbPNPDeviceID_1(drive, p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;

function getUsbPNPDeviceID(index: integer): ansistring;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 255);
  try
    getUsbPNPDeviceID_2(index, p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;
function GetDiskSize(index: Integer = 0): Int64;
begin
   result:=GetDiskSize_2(index);
end;
function GetDiskSize(drv: AnsiChar): Int64;
begin
   result:=GetDiskSize_1(drv);
end;
function GetDiskName(index:integer):Ansistring;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 255);
  try
    GetDiskName_2(index, p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;
function GetDiskName(drive:AnsiChar):Ansistring;
var sz, i: Integer;
  p: pansiChar;
begin
  result := '';
  getmem(p, 255);
  try
    GetDiskName_1(drive, p, sz);
    for i := 1 to sz do
    begin
      result := result + p[i - 1];
    end;
  finally
    freemem(p);
  end;
end;
//动态库初始化

procedure InitJyDiskDll();
var diskdll, dllpath: string;
begin
  if hDll > 0 then Exit;

  dllpath := GetCurrentPath;
  diskdll := dllpath + dllname;

  hDll := safeLoadLibrary(diskdll);
  if hDll <= 0 then
  begin
    raise exception.create('disk库初始化失败!' + #13#10 + diskdll);
    Exit;
  end;
  init_ := GetProcAddress(hDll, 'init');
  getDiskSerialNumber_1 := GetProcAddress(hDll, 'getDiskSerialNumber1');
  getDiskSerialNumber_2 := GetProcAddress(hDll, 'getDiskSerialNumber2');
  getDiskTypeStr_ := GetProcAddress(hDll, 'getDiskTypeStr');
  getDiskType_1 := GetProcAddress(hDll, 'getDiskType1');
  getDiskType_2 := GetProcAddress(hDll, 'getDiskType2');
  getDiskIndex_ := GetProcAddress(hDll, 'getDiskIndex');
  doReg_ := GetProcAddress(hDll, 'doReg');
  isRegisted_ := GetProcAddress(hDll, 'isRegisted');
  getPhysicalDriveCount_ := GetProcAddress(hDll, 'getPhysicalDriveCount');
  runAsAdmin_ := GetProcAddress(hDll, 'runAsAdmin');
  getDiskDrive_ := GetProcAddress(hDll, 'getDiskDrive');
  getDriverList_ := GetProcAddress(hDll, 'getDriverList');
  getPhysicalDrivePartitionCount_ := GetProcAddress(hDll, 'getPhysicalDrivePartitionCount');
  getDiskPartitionIndex_ := GetProcAddress(hDll, 'getDiskPartitionIndex');
  getHardDiskPartitionInfo_ := GetProcAddress(hDll, 'getHardDiskPartitionInfo');
  getDiskInfo_ := GetProcAddress(hDll, 'getDiskInfo');
  getMd5String_ := GetProcAddress(hDll, 'getMd5String');
  getCpuID_:= GetProcAddress(hDll, 'getCpuID');
  getBiosID_:= GetProcAddress(hDll, 'getBiosID');
  getDisplayDeviceID_:= GetProcAddress(hDll, 'getDisplayDeviceID');
  getIP_:= GetProcAddress(hDll, 'getIP');
  getMacAddr_:= GetProcAddress(hDll, 'getMacAddr');
  isWin64_ := GetProcAddress(hDll, 'isWin64');
  getUsbPNPDeviceID_1 := GetProcAddress(hDll, 'getUsbPNPDeviceID1');
  getUsbPNPDeviceID_2 := GetProcAddress(hDll, 'getUsbPNPDeviceID2');
  getDiskSize_1 := GetProcAddress(hDll, 'getDiskSize1');
  getDiskSize_2 := GetProcAddress(hDll, 'getDiskSize2');
  getDiskName_1:= GetProcAddress(hDll, 'getDiskName1');
  getDiskName_2:= GetProcAddress(hDll, 'getDiskName2');
end;
//释放动态库

procedure FreeJyDiskDll;
begin
  if (hDll <= 0) then Exit;
  FreeLibrary(hDll);
  hDll := 0;
  init_:=nil;
  getDiskSerialNumber_1 := nil;
  getDiskSerialNumber_2 := nil;
  getDiskTypeStr_ := nil;
  getDiskType_1 := nil;
  getDiskType_2 := nil;
  getDiskIndex_ := nil;
  doReg_ := nil;
  isRegisted_ := nil;
  getPhysicalDriveCount_ := nil;
  runAsAdmin_ := nil;
  getDiskDrive_ := nil;
  getDriverList_ := nil;
  getPhysicalDrivePartitionCount_ := nil;
  getDiskPartitionIndex_ := nil;
  getHardDiskPartitionInfo_ := nil;
  getDiskInfo_ := nil;
  getMd5String_ := nil;
  getCpuID_:=nil;
  getBiosID_:=nil;
  getDisplayDeviceID_:=nil;
  getIP_:=nil;
  getMacAddr_:=nil;
  isWin64_:=nil;
  getUsbPNPDeviceID_1:=nil;
  getUsbPNPDeviceID_2:=nil;
  getDiskSize_1:=nil;
  getDiskSize_2:=nil;
  getDiskName_1:= nil;
  getDiskName_2:= nil;
end;
initialization
  hDll := 0;
finalization
  FreeJyDiskDll;
end.

