自己想出来的用户验证方法,软件安装/运行时如何取得本机的唯一编号,如CPU编号?

解决方案 »

  1.   

    http://www.csdn.net/expert/topic/975/975928.xml?temp=.8823969
      

  2.   

    得到硬盘的序列号:
      uses
    SysUtils, Windows;function Get_DiskSerialNo(DriveID : char) : string;
    var
    VolumeSerialNumber : DWORD;
    MaximumComponentLength : DWORD;
    FileSystemFlags : DWORD;
    begin
    result := '';
    try
    GetVolumeInformation(PChar(DriveID + ':\'),
    nil, 0, @VolumeSerialNumber,
    MaximumComponentLength, FileSystemFlags,
    nil, 0);
    result := IntToHex(HiWord(VolumeSerialNumber), 4) +
    '-' + IntToHex(LoWord(VolumeSerialNumber), 4);
    exceptend;
    end;
    获取主板信息:
      添加一个Tbutton和一个Tmemo组件到窗体并写如下代码到按钮的OnClick事件:with Memo1.Lines do 
    begin 
    Add('MainBoardBiosName:'+^I+string(Pchar(Ptr($FE061)))); 
    Add('MainBoardBiosCopyRight:'+^I+string(Pchar(Ptr($FE091)))); 
    Add('MainBoardBiosDate:'+^I+string(Pchar(Ptr($FFFF5)))); 
    Add('MainBoardBiosSerialNo:'+^I+string(Pchar(Ptr($FEC71)))); 
    end; 
      

  3.   

    网卡的MAC地址是全球唯一的。。
      

  4.   

    procedure GetCpuInfo;
    var R: array[0..19] of Char;
    var CpuID: Integer;
    begin
      FillChar(R, 20, 0);
      asm
        mov eax, 0
        db 0fh, 0a2h               // 其实就是cpuid汇编指令
        mov dword ptr R[0],  ebx
        mov dword ptr R[4],  edx
        mov dword ptr R[8],  ecx
        mov eax, 1
        db 0fh, 0a2h               // cpuid
        mov CpuID, edx
      end;
      ShowMessage('CPU制造商为:' + R);
      ShowMessage('序列号为:' + IntToStr(CpuID));
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      GetCpuInfo;
    end;unit DiskSN;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,DsgnIntf;
    type
    TSrbIoControl = packed record
    HeaderLength : ULONG;
    Signature : Array[0..7] of Char; 
    Timeout : ULONG; 
    ControlCode : ULONG; 
    ReturnCode : ULONG;
    Length : ULONG; 
    end; 
    SRB_IO_CONTROL = TSrbIoControl; 
    PSrbIoControl = ^TSrbIoControl; TIDERegs = packed record 
    bFeaturesReg : Byte; // Used for specifying SMART "commands". 
    bSectorCountReg : Byte; // IDE sector count register
    bSectorNumberReg : Byte; // IDE sector number register 
    bCylLowReg : Byte; // IDE low order cylinder value 
    bCylHighReg : Byte; // IDE high order cylinder value 
    bDriveHeadReg : Byte; // IDE drive/head register 
    bCommandReg : Byte; // Actual IDE command. 
    bReserved : Byte; // reserved. Must be zero. 
    end;
    IDEREGS = TIDERegs;
    PIDERegs = ^TIDERegs; 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;
    SENDCMDINPARAMS = TSendCmdInParams;
    PSendCmdInParams = ^TSendCmdInParams; 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 : ULONG; 
    wMultSectorStuff : Word;
    ulTotalAddressableSectors : ULONG; 
    wSingleWordDMA : Word; 
    wMultiWordDMA : Word; 
    bReserved : Array[0..127] of Byte; 
    end;
    PIdSector = ^TIdSector; const
    IDE_ID_FUNCTION = $EC; 
    IDENTIFY_BUFFER_SIZE = 512;
    DFP_RECEIVE_DRIVE_DATA = $0007c088;
    IOCTL_SCSI_MINIPORT = $0004d008;
    IOCTL_SCSI_MINIPORT_IDENTIFY = $001b0501;
    DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
    BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize;
    W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;
    type  TDISKSN = class(TComponent)
      private
        FAbout  : string;
        FSerialNumber: string;
        { Private declarations }
      protected
        { Protected declarations }
      public
         
        constructor Create(AOwner:TComponent); override;
        procedure Loaded; override;
        destructor Destroy; override;
        procedure ShowAbout;
        { Public declarations }
      published
            { Published declarations }
      property About: string read FAbout write FAbout stored False;
      property GetDiskSN :string read FSerialNumber;
      end;procedure Register;implementation
    type
    TGate = record
    Off2,op,seg,off1:WORD;
    end;
    LONGDWORD = INT64;
    var
    IDTR: LONGDWORD;
    SavedGate:TGate;
    OurGate: TGate;
    dd: array [0..256] of word;
    dsn:array [0..20] of char; //存放硬盘序列号procedure Ring0Proc();
    asm
    // Wait for controller not busy
    mov dx,01f7h
    @1:in al,dx
    cmp al,050h
    jne @1// Get first/second drive
    dec dx
    mov al,0a0h
    out dx,al// Get drive info data
    inc dx
    mov al,0ech
    out dx,al
    nop
    nop// Wait for data ready
    @2:in al,dx
    cmp al,058h
    jne @2
    nop
    nop
    // Read sector
    xor ecx,ecx
    mov dx,01f0h
    @3:in ax,dx
    mov word ptr dd[ecx*2],ax
    inc ecx
    cmp ecx,256
    jne @3iretd //中断返回
    end;
    procedure Change2Ring0();
    var i :integer;
    begin
    asm
    mov eax, offset Ring0Proc
    mov OurGate.off2, ax // 将 中 断 函 数 的 地 址
    shr eax, 16 // 填 入 新 造 的 中 断 门
    mov OurGate.off1, ax // 描 述 符
    mov OurGate.op,0028h
    mov OurGate.seg,0ee00h
    mov ebx,offset IDTR
    sidt [ebx]
    // 将 中 断 描 述 符 表 寄 存 器(IDTR)的 内 容 取 出
    mov ebx, dword ptr [IDTR+2]
    // 取 出 中 断 描 述 符 表(IDT) 基 地 址
    add ebx, 8*3
    // 计 算Int 3 的 描 述 符 应 放 置 的 地 址 选 用
    //Int3 是 因 为 它 在Win32 保 护 模 式 下 未 占 用
    mov edi, offset SavedGate
    mov esi, ebx
    movsd // 保 存 原 来 的Int 9 描 述 符 到
    movsd //SavedGate 以 便 恢 复mov edi, ebx
    mov esi, offset OurGate
    cli
    movsd // 替 换 原 来 的 中 断 门 描 述 符
    movsd // 以 安 装 中 断 服 务 例 程
    sti
    mov eax,6200h
    // 用 以 测 试 放 在EAX 中 的 数 据 能 否 正 确 传 到Ring0 中 断
    mov ecx,0
    // 用 以 测 试 放 在ECX 中 的 数 据
    // 能 否 正 确 传 到Ring0 中 断
    // 因 为 很 多VxD 服 务 都 用此二 寄 存 器 传 递 参 数
    int 3h
    // 人 为 触 发 中 断, 平 时 会 出 现保 护 错 误 蓝 屏 或 非 法 操
    // 作 对 话 框, 现 在 安 装 了
    // 中 断 服 务 例 程 后, 就 会 通 过
    //VMM 在Ring0 调 用 中 断 服 务 例 程Ring0Proc
    mov edi, ebx
    mov esi, offset SavedGate
    cli
    movsd // 恢 复 原 来 的 中 断 门 描 述 符
    movsd
    sti
    end;asm
    xor ecx,ecx
    mov ebx,offset dd[10*2]
    @4:mov ax,[ebx]
    mov byte ptr dsn[ecx],ah
    inc ecx
    mov byte ptr dsn[ecx],al
    inc ebx
    inc ebx
    inc ecx
    cmp ecx,20
    jne @4
    end;
    for i:=0 to 10 do
    dsn[i]:=dsn[i+10];
    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;