[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

HardDisk Id

Posted on 2006-05-24
5
Medium Priority
?
510 Views
Last Modified: 2010-05-18
How to get harddisk id or somthing that would be same only on 1 computer.
0
Comment
Question by:65zgtre45rr
5 Comments
 
LVL 17

Accepted Solution

by:
TheRealLoki earned 2000 total points
ID: 16757423
I think it's

procedure TForm1.Button1Click(Sender: TObject);
var
  SerialNum : dword;
  a, b : dword;
  Buffer  : array [0..255] of char;
begin
  if GetVolumeInformation('c:\', Buffer, SizeOf(Buffer), @SerialNum, a, b, nil, 0) then
    ShowMessage (IntToStr(SerialNum))
// or if you prefer hex    ShowMessage (IntToHex(SerialNum, 8))
  else
    ShowMessage ('- unknown -');
end;
0
 
LVL 9

Expert Comment

by:sun4sunday
ID: 16757888
>>somthing that would be same only on 1 computer
  The answer for this one is the network card ID. That mac address will be unique for all the network cards

Has to find the mac address and ti will give the unique identity for the comptuer.

Are you trying to write something to stop piracy ;)

Hope this helps

sun4sunday
0
 
LVL 16

Expert Comment

by:CodedK
ID: 16758794
>>somthing that would be same only on 1 computer

Hardware ids are more reliable...
But

The HD serial changes if you replace the hd. This happens quite often.
MAC address isnt a reliable method because someone might not have a lan card, just dial up.

You could use Bios version but this isnt reliable too, because a user upgrades the bios quite often.
BIOS name rarely changes.
You could also use CPUID.
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20803727.html

Also a unique ID under windows is the SID - the Security Identifier.

Finally
You can use a combination of all those serials and then allow small changes to take place
3 of 5 serials is good enough to verify the machine is the same.


0
 
LVL 20

Expert Comment

by:Mark Brady
ID: 16759850
Sounds like you need the Hard drive fiscal number which does not change even after a format.  Here is the function and procedure to get that.

///////////////////////////////////////////////////////////////////////////////////////

function GetIdeDiskSerialNumber : String;
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; // especificar "comandos" SMART
     bSectorCountReg  : Byte; // registro de contador de setor
     bSectorNumberReg : Byte; // registro de número de setores
     bCylLowReg       : Byte; // valor de cilindro (byte mais baixo)
     bCylHighReg      : Byte; // valor de cilindro (byte mais alto)
     bDriveHeadReg    : Byte; // registro de drive/cabeça
     bCommandReg      : Byte; // comando IDE
     bReserved        : Byte; // reservado- tem que ser 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;
var
   hDevice : THandle;
   cbBytesReturned : DWORD;
   pInData : PSendCmdInParams;
   pOutData : Pointer; // PSendCmdOutParams
   Buffer : Array[0..BufferSize-1] of Byte;
   srbControl : TSrbIoControl absolute Buffer;

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 := '';
   FillChar(Buffer,BufferSize,#0);
   if Win32Platform=VER_PLATFORM_WIN32_NT then
   // Windows NT, Windows 2000, Windows XP
   begin
   // recuperar handle da porta SCSI
     hDevice := CreateFile('\\.\Scsi0:',
     // Nota: '\\.\C:' precisa de privilégios administrativos
     GENERIC_READ or GENERIC_WRITE,
     FILE_SHARE_READ or FILE_SHARE_WRITE,
     nil, OPEN_EXISTING, 0, 0);

     if hDevice=INVALID_HANDLE_VALUE then Exit;
     try
       srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);
       System.Move('SCSIDISK',srbControl.Signature,8);
       srbControl.Timeout      := 2;
       srbControl.Length       := DataSize;
       srbControl.ControlCode  := IOCTL_SCSI_MINIPORT_IDENTIFY;
       pInData := PSendCmdInParams(PChar(@Buffer) + SizeOf(SRB_IO_CONTROL));
       pOutData := pInData;
       with pInData^ do
       begin
         cBufferSize  := IDENTIFY_BUFFER_SIZE;
         bDriveNumber := 0;
         with irDriveRegs do
         begin
           bFeaturesReg     := 0;
           bSectorCountReg  := 1;
           bSectorNumberReg := 1;
           bCylLowReg       := 0;
           bCylHighReg      := 0;
           bDriveHeadReg    := $A0;
           bCommandReg      := IDE_ID_FUNCTION;
         end;
       end;

       if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil) then
         Exit;
       finally
         CloseHandle(hDevice);
       end;
     end
   else
     begin
     // Windows 95 OSR2, Windows 98, Windows ME
     hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
     if hDevice=INVALID_HANDLE_VALUE then Exit;
     try
       pInData := PSendCmdInParams(@Buffer);
       pOutData := @pInData^.bBuffer;
       with pInData^ do
       begin
         cBufferSize  := IDENTIFY_BUFFER_SIZE;
         bDriveNumber := 0;
         with irDriveRegs do
         begin
           bFeaturesReg     := 0;
           bSectorCountReg  := 1;
           bSectorNumberReg := 1;
           bCylLowReg       := 0;
           bCylHighReg      := 0;
           bDriveHeadReg    := $A0;
           bCommandReg      := IDE_ID_FUNCTION;
         end;
       end;

       if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA,
       pInData, SizeOf(TSendCmdInParams)-1, pOutData, W9xBufferSize, cbBytesReturned, nil ) then
         Exit;
       finally
         CloseHandle(hDevice);
       end;
     end;

     with PIdSector(PChar(pOutData)+16)^ do
     begin
       ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
       SetString(Result,sSerialNumber,SizeOf(sSerialNumber));
     end;
end;



////////////////////////////////////////////////////////////////////////////////////////////

//  Now add this procedure and modify it as you wish......but if added to button1 for eg:


procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
rc : DWORD;
begin
s := GetIdeDiskSerialNumber;
     if s='' then
     begin
       rc := GetLastError;
       if rc=0 then
         showmessage('Drive IDE don´t suport SMART')
       else
         showmessage(SysErrorMessage(rc));
     end
     else
       showmessage('Fisical serial number disk is: ' + s);

end;


//////////////////////////////////

Note:

As it is written, it will return the serial for fixed drive '0'
To check other fixed drives change this line......

with pInData^ do
       begin
         cBufferSize  := IDENTIFY_BUFFER_SIZE;
         bDriveNumber := 0;   // change to // bDriveNumber := 1;
         with irDriveRegs do


Regards

Elvin
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses
Course of the Month19 days, 9 hours left to enroll

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question