如何得到CPU的序列号,或者是硬盘的物理序列号
我是想让软件知道一台特定的电脑上运行

解决方案 »

  1.   

    type
     TCPUIDResult = record
       EAX: DWord;
       EBX: DWord;
       ECX: DWord;
       EDX: DWord;
     end;
    ……
    function CPUID(EAX:DWord): TCPUIDResult;
    asm
     push eax
     push ebx
     push ecx
     push edx
     mov eax,EAX
     //******************************************************
     //cpuid指令,因为Delphi的汇编编译器没有内置该指令,
     //所以用该指令的机器语言代码$0F,$A2来实现
     //******************************************************
     db $0F,$A2
     mov Result.EAX,EAX
     mov Result.EBX,EBX
     mov Result.ECX,ECX
     mov Result.EDX,EDX
     pop edx
     pop ecx
     pop ebx
     pop eax
    end;
      

  2.   

    Function GetIdeSerialNumber(): PChar; stdcall;
    Const
      IDENTIFY_BUFFER_SIZE = 512;
    Type
      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 for future use. Must be zero.
      End;  TSendCmdInParams = Packed Record
        // Buffer size in bytes
        cBufferSize: DWORD;
        // Structure with drive register values.
        irDriveRegs: TIDERegs;
        // Physical drive number to send command to (0,1,2,3).
        bDriveNumber: BYTE;
        bReserved: Array[0..2] Of BYTE;
        dwReserved: Array[0..3] Of DWORD;
        bBuffer: Array[0..0] Of BYTE; // Input buffer.
      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
        // Çý¶¯Æ÷·µ»ØµÄ´íÎó´úÂ룬ÎÞ´íÔò·µ»Ø0
        bDriverError: BYTE;
        // IDE³ö´í¼Ä´æÆ÷µÄÄÚÈÝ£¬Ö»Óе±bDriverError Îª SMART_IDE_ERROR Ê±ÓÐЧ
        bIDEStatus: BYTE;
        bReserved: Array[0..1] Of BYTE;
        dwReserved: Array[0..1] Of DWORD;
      End;  TSendCmdOutParams = Packed Record
        // bBufferµÄ´óС
        cBufferSize: DWORD;
        // Çý¶¯Æ÷״̬
        DriverStatus: TDriverStatus;
        // ÓÃÓÚ±£´æ´ÓÇý¶¯Æ÷¶Á³öµÄÊý¾ÝµÄ»º³åÇø£¬Êµ¼Ê³¤¶ÈÓÉcBufferSize¾ö¶¨
        bBuffer: Array[0..0] Of BYTE;
      End;Var
      hDevice: THandle;
      cbBytesReturned: DWORD;
      SCIP: TSendCmdInParams;
      aIdOutCmd: Array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1) - 1] Of BYTE;
      IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;  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;Begin
      Result := ''; // Èç¹û³ö´íÔò·µ»Ø¿Õ´®  If SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT Then // Windows NT, Windows 2000
      Begin
        // Ìáʾ! ¸Ä±äÃû³Æ¿ÉÊÊÓÃÓÚÆäËüÇý¶¯Æ÷£¬ÈçµÚ¶þ¸öÇý¶¯Æ÷£º '\\.\PhysicalDrive1\'
        hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ Or GENERIC_WRITE,
          FILE_SHARE_READ Or FILE_SHARE_WRITE, Nil, OPEN_EXISTING, 0, 0);
      End
      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;
      

  3.   

    to smiler007(笑一笑):
    你给出的函数中,那个EAX:DWord应该填入什么?
      

  4.   

    //******************************************************
     //cpuid指令,因为Delphi的汇编编译器没有内置该指令,
     //所以用该指令的机器语言代码$0F,$A2来实现
     //******************************************************
     db $0F,$A2别的版本没用过,D6支持cpuid指令,不需要DBeax中的内容参见cpuid指令的详细介绍,Intel网站上有pdf文件可以下载
      

  5.   

    Intel Architecture
    Software Developer’s
    Manual