delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
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








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 (19)


To capture the Fisical serial number of Hard DiskFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi 5.x (or higher)
Category:
System
Skill Level:
Scoring:
Last Update:
12/16/2004
Search Keys:
delphi delphi3000 article borland vcl code-snippet Hard;Drive;number of the Volume
Times Scored:
31
Visits:
15833
Uploader: Walter Alves Chagas Junior
Company: Telemont - Eng.de Telecomunic.
Reference: N/A
 
Question/Problem/Abstract:
How to obtain the physical number of Hard Drive (not a logical number of the Volume)
Answer:



To capture the Fisical serial number of Hard Disk:

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;



how to call the function:
1) Create this variables:
       s : String;
       rc : DWORD;

2) on onClick of Event of Button, paste this code
     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);





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
How To adapt this Program under Delphi 2009 Architect?.
    edelweiss Salem (Jan 31 2009 9:54PM)

This program is correct under Delphi 7 Entreprise, Migrer towards Delphi 2009 Architect, RC returns the messge "Indique Two Numbers of Incompatible Version", L' OS is generally Xp SP2. Thank you for your support
Respond

Windows Vista
    Giyora Alon (Nov 28 2008 9:12PM)

Does anyone know if this code suppose to be ok also on Windows Vista ?
I have some problem using it on vista and I am not sure the prob is really the OS or something else.
If yes, what can be the solutions ?

Many thanks

Respond

A Propos de Physical Disk Serial Number
    edelweiss Salem (Jun 1 2008 12:37AM)

Je suis trés fièr d"avoir enfin ce fameux programme que j'ai tant recherché jusqu'au deséspoir, j'en ai vraiment besoin pour blinder des algorithmes à l'exécution .
J'ai testé le programme et comparé les resultats avec les utilitaires d'HIREN's Vraiment c'est formidable .
Je presente mes vives reconnaissances à son auteur respectif .
                                                             Pour de meilleus sucés.
                                                                            
Respond

Very good routine
    Stanko Brus (Sep 27 2007 11:46AM)

Thanks a lot for saving my time.
Respond

Não funciona na IDE1
    José Carlos Jr. (Jan 4 2006 2:16PM)

Bom dia!

Gostaria de saber se você pode implementar essa função para utilizar tanto na IDE0 como a IDE1 e como detectar em qual a IDE o HD está instalado? Pois o meu micro está com a IDE0 queimada.

Espero resposta.
José Carlos Jr.

Respond

RE: Não funciona na IDE1
Walter Alves Chagas Junior (Nov 3 2006 4:08PM)

Se não me engano, a constante "IDE_ID_FUNCTION" é quem determina em qual IDE ela vai ler. Já tentou trocar este valor?
Respond

Windows 2003
    Tiago Rossini Coradini (Sep 26 2005 5:40PM)

Gostaria de saber se essa função funciona para windows 2003, pois não não esta funcionando no mesmo..
Obrigado
Respond

RE: Windows 2003
Walter Alves Chagas Junior (Nov 3 2006 4:06PM)

Eu nunca testei ela no Windows 2003.
Respond

Device is not found in SCSI RAID
    faridh jmr (Sep 11 2005 12:04PM)

Hi

It works fine in my computer OS: Windows 2000, Single HardDisk IDE.
But it doesn't work in the server machine. OS : Windows 2003, SCSI RAID Controller

After executing this line, system raise this error
'Device is not connected'
code segment:
if not DeviceIoControl(hDeivce,IOCTL_SCSI_MINIPORT,@Buffer, BufferSize,@Buffer,BufferSize,cbBytesReturned,nil)  
Respond

Funciona pela Rede?
    Reinaldo Cesar Dias Martins (Jul 14 2005 3:00PM)

Eu consigo detectar o serial de um outro HD que esteja mapeado atráves dessa função?


I obtain to detect the serial one of one another HD that is mapead of this function?

Reinaldo

Respond

RE: Funciona pela Rede?
Walter Alves Chagas Junior (Jul 19 2005 8:51PM)

Olá amigo. Infelizmente não há como porque esta função lê a controladora do HD

Hello Friend, friend. Unhappyly it doesn't have as because this function reads the HD hardware controller.
Respond

yuck !!!
    v v (Jul 13 2005 9:27AM)

only works on IDE .. not on Serial ATA
Respond

solution:
v v (Jul 13 2005 9:43AM)

modify this code:
     hDevice := CreateFile('\\.\PhysicalDrive0',

Respond

Win98
    Alosi Teixeira (Jul 5 2005 10:41PM)

Não funciona no windows 98, e em uma máquina XP, devolve valor em branco.
Respond

RE: Win98
Walter Alves Chagas Junior (Jul 7 2005 1:57PM)

Você tem que habilitar o S.M.A.R.T. do HD no setup da maquina. Fiz um teste e se o S.M.A.R.T não estiver habilitado, não lê mesmo não.
Respond

RE: RE: Win98
Alosi (Jul 14 2005 3:42PM)

Mas o cliente não vai ativar isso, teria que ter a função API que habilita isso, ai funcionaria.
Respond

RE: RE: RE: Win98
Walter Alves Chagas Junior (Jul 19 2005 8:53PM)

Infelizmente sem ativar o S.M.A.R.T não tem como. E acho que toda e qualquer leitura da controladora visando obter dados, tem que ativar este recurso.

Unhappyly without activating the S.M.A.R.T it does not have as. And I find that all and any reading of the controller aiming at to get given, has that to activate this resource.
Respond

HD fisical serial number
    kilson leite (May 25 2005 12:07AM)

Very good!
Thanks you...
Respond

Excellent!
    Gradius van Tonder (Feb 23 2005 11:24AM)

Great example code! Only I had to change the drive index from 0 to 1 to get mine to give the right serial.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
Hans Gulö
 
   














 







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