delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (4)


Getting the BIOS serial numberComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
How to read manufacturer's information from the ROM BIOS chip
Product:
Delphi all versions
Category:
System
Skill Level:
Scoring:
Last Update:
07/11/2001
Search Keys:
delphi delphi3000 article borland vcl code-snippet how howto how-to get getting obtain obtaining read reading rom bios rom-bios serial number no no. serial-number serial-no serial-no. manufacturer manufacturer's eprom chip
Times Scored:
17
Visits:
17541
Uploader: Ernesto De Spirito
Company: Latium Software
Reference: Pascal Newsletter #20
Component Download: http://www.latiumsoftware.com/download/p0020.zip
 
Question/Problem/Abstract:
Different BIOS manufacturers have placed the serial numbers and other BIOS information in different memory locations, so the code you can usually find in the net to get this information might work with some machines but not with others...
Answer:



For a simple copy-protection scheme we need to know whether the machine that is executing our application is the one where it was installed. We can save the machine data in the Windows Registry when the application is installed or executed for the first time, and then every time the application gets executed we compare the machine data with the one we saved to see if they are the same or not.

But, what machine data should we use and how do we get it? In a past issue we showed how to get the volume serial number of a logical disk drive, but normally this is not satisfying for a software developer since this number can be changed.

A better solution could be using the BIOS serial number. BIOS stands for Basic Input/Output System and basically is a chip on the motherboard of the PC that contains the initialization program of the PC (everything until the load of the boot sector of the hard disk or other boot device) and some basic device-access routines. Unfortunately, different BIOS manufacturers have placed the serial numbers and other BIOS information in different memory locations, so the code you can usually find in the net to get this information might work with some machines but not with others. However, most (if not all) BIOS manufacturers have placed the information somewhere in the last 8 Kb of the first Mb of memory, i.e. in the address space from $000FE000 to $000FFFFF. Assuming that "s" is a string variable, the following code would store these 8 Kb in it:

    SetString(s, PChar(Ptr($FE000)), $2000);  // $2000 = 8196

We can take the last 64 Kb to be sure we are not missing anything:

    SetString(s, PChar(Ptr($F0000)), $10000);  // $10000 = 65536

The problem is that it's ill-advised to store "large volumes" of data in the Windows Registry. It would be better if we could restrict to 256 bytes or less using some hashing/checksum technique. For example we can use the SHA1 unit (and optionally the Base64 unit) introduced in the issue #17 of the Pascal Newsletter:

    http://www.latiumsoftware.com/en/pascal/0017.php3

The code could look like the following:

  uses SHA1, Base64;

  function GetHashedBiosInfo: string;
  var
    SHA1Context: TSHA1Context;
    SHA1Digest: TSHA1Digest;
  begin
    // Get the BIOS data
    SetString(Result, PChar(Ptr($F0000)), $10000);
    // Hash the string
    SHA1Init(SHA1Context);
    SHA1Update(SHA1Context, PChar(Result), Length(Result));
    SHA1Final(SHA1Context, SHA1Digest);
    SetString(Result, PChar(@SHA1Digest), sizeof(SHA1Digest));
    // Return the hash string encoded in printable characters
    Result := B64Encode(Result);
  end;

This way we get a short string that we can save in the Windows Registry without any problems.

The full source code example corresponding to this article is available for download:

  http://www.latiumsoftware.com/download/p0020.zip

The full source code example of this article is available for download:

  http://www.latiumsoftware.com/download/p0020.zip


DISPLAYING BIOS INFORMATION
---------------------------

If we wanted to display the BIOS information we should parse the bytes to extract all null-terminated strings with ASCII printable characters at least 8-characters length, as it is done in the following function:

  function GetBiosInfoAsText: string;
  var
    p, q: pchar;
  begin
    q := nil;
    p := PChar(Ptr($FE000));
    repeat
      if q <> nil then begin
        if not (p^ in [#10, #13, #32..#126, #169, #184]) then begin
          if (p^ = #0) and (p - q >= 8) then begin
            Result := Result + TrimRight(String(q)) + #13#10;
          end;
          q := nil;
        end;
      end else
        if p^ in [#33..#126, #169, #184] then
          q := p;
      inc(p);
    until p > PChar(Ptr($FFFFF));
    Result := TrimRight(Result);
  end;

Then we can use the return value for example to display it in a memo:

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    Memo1.Lines.Text := GetBiosInfoAsText;
  end;






Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
2000 / NT issue
    Mike Heydon (May 8 2001 4:49AM)

You could use a hybrid approach using the try except statement to get info from both 95/98 and 2000/NT systems

examples (simplified)

// ================================================
// Bios Information 95/98 and 2000/NT compatible
// ================================================

uses TRegistry;

function BiosDate : string;
var Retvar : string;
    WinReg : TRegistry;
begin
  WinReg := nil;
  RetVar := '????????';

  try
    // Win 9x
    SetString(Retvar,PChar(Ptr($FFFF5)),10);
  except
    // Win 2000/NT
    try
      WinReg := TRegistry.Create;
      WinReg.RootKey := HKEY_LOCAL_MACHINE;
      if WinReg.OpenKeyReadOnly('\HARDWARE\DESCRIPTION\System') then
         RetVar := WinReg.ReadString('SystemBiosDate');
    finally
      WinReg.Free;
    end;
  end;

  Result := Retvar;
end;


function BiosID : string;
var Retvar : string;
    Buffer : PChar;
    WinReg : TRegistry;
begin
  WinReg := nil;
  RetVar := '????????';

  try
    // Win 9x
    SetString(RetVar,PChar(Ptr($F0000)),$2000);
  except
    // Win 2000/NT
    try
      WinReg := TRegistry.Create;
      WinReg.RootKey := HKEY_LOCAL_MACHINE;
      if WinReg.OpenKeyReadOnly('\HARDWARE\DESCRIPTION\System') then begin
         GetMem(Buffer,$2000);
         WinReg.ReadBinaryData('SystemBiosVersion',Buffer^,$2000);
         RetVar := WinReg.ReadString('Identifier') + ' ' + Buffer;
         FreeMem(Buffer);
      end;
    finally
      WinReg.Free;
    end;
  end;
    
  Result := Retvar;
end;



Respond

Access Viloation
    Chris Viklund (May 4 2001 9:34AM)

Hi, I get an Access Viloation after running your Demo Application (that I downloaded from the Web).

If seems to be at this row,
if p^ in [#33..#126, #169, #184] then

Running Delphi 5 Enterprise + Windows2000

Any ideas?
Respond

RE: Access Viloation
Flurin Honegger (May 4 2001 2:54PM)

pchar(ptr($fe000) is not allowed under NT. You can not access directly physical memory under NT. NT has HAL, hardware abstraction layer. You can read Bios Information in a kernel mode driver. But under NT this is not necessary any way. Visit the registry keys

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System

With its values

SystemBiosDate
SystemBiosVersion
VideoBiosDate
VideoBiosVersion.

Under HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0

you find even the speed of your CPU (~MHz) as an integer.

Note that all data in the key HKEY_LOCAL_MACHINE\HARDWARE is recreated each time the system is started.




Respond

RE: Access Viloation
Maarten de Haan (May 7 2001 6:08AM)

Reading and writing memory locations outside the memory that reserved for the application itself, will give an error on the NT-platform. This is to protect the operating system and other running applications from corruption.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
R. Lefter
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)