0% found this document useful (0 votes)
291 views

Delphi - in Delphi7, How Can I Retrieve Hard Disk Unique Serial Number - Stack Overflow

The document is a Stack Overflow post from 2011 asking how to retrieve the unique serial number of a hard disk in Delphi 7 without administrator privileges. It received several responses, including a translation of some C++ code to Delphi that uses Windows API calls to access the disk information without elevated privileges. A code sample is provided to demonstrate its use.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
291 views

Delphi - in Delphi7, How Can I Retrieve Hard Disk Unique Serial Number - Stack Overflow

The document is a Stack Overflow post from 2011 asking how to retrieve the unique serial number of a hard disk in Delphi 7 without administrator privileges. It received several responses, including a translation of some C++ code to Delphi that uses Windows API calls to access the disk information without elevated privileges. A code sample is provided to demonstrate its use.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number?

- Stack Overflow

in Delphi7, How can I retrieve hard disk unique serial number?


Asked
11 years, 2 months ago Modified
8 years, 10 months ago Viewed
21k times

Hi
I want to retrieve HDD unique (hardware) serial number.
I use some functions but in
Windows Seven or Vista they don't work correctly because of admin right.
Is it possible
16 retrieve it without run as Administrator?

delphi hardware delphi-7

11
Share Improve this question edited Mar 6, 2011 at 0:29 asked Mar 5, 2011 at 6:58

Follow Sertac Akyuz Amin


53.4k 4 95 161 1,230 2 12 24

Possibly related: How to generate an unique computer id on Delphi?, How To Get An Unique ID?
– Sertac Akyuz
Mar 6, 2011 at 0:31

The usual reason people want this is copy protection. Be aware that some RAID controllers will respond
with the serial number of whatever drive is available to answer and thus you'll get different answers
different times.
– Loren Pechtel
Mar 6, 2011 at 1:17

Sorted by:
5 Answers
Highest score (default)

Following the links in the question comments Sertac posted, I came across this interesting
C++ question, where Fredou answered with a nice link to a codeproject example showing how
23 to do this in .NET, which in turn was based on a link to Borland C++ code and article.

The cool thing is that this C++ code works as a non-administrator user too!

Now you need someone to help you translate this C++ code to Delphi.

Edit: Found a Delphi unit that does this for you.

I wrote some sample use for it:

program DiskDriveSerialConsoleProject;

{$APPTYPE CONSOLE}

uses
Windows,
SysUtils,
hddinfo in 'hddinfo.pas';

const
// Max number of drives assuming primary/secondary, master/slave topology
MAX_IDE_DRIVES = 16;

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 1/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
procedure ReadPhysicalDriveInNTWithZeroRights ();
var
DriveNumber: Byte;
HDDInfo: THDDInfo;
begin
HDDInfo := THDDInfo.Create();
try
for DriveNumber := 0 to MAX_IDE_DRIVES - 1 do
try
HDDInfo.DriveNumber := DriveNumber;
if HDDInfo.IsInfoAvailable then
begin
Writeln('VendorId: ', HDDInfo.VendorId);
Writeln('ProductId: ', HDDInfo.ProductId);
Writeln('ProductRevision: ', HDDInfo.ProductRevision);
Writeln('SerialNumber: ', HDDInfo.SerialNumber);
Writeln('SerialNumberInt: ', HDDInfo.SerialNumberInt);
Writeln('SerialNumberText: ', HDDInfo.SerialNumberText);
end;
except
on E: Exception do
Writeln(Format('DriveNumber %d, %s: %s', [DriveNumber, E.ClassName,
E.Message]));
end;
finally
HDDInfo.Free;
end;
end;

begin
ReadPhysicalDriveInNTWithZeroRights;
Write('Press <Enter>');
Readln;
end.

Unit from http://www.delphipraxis.net/564756-post28.html

// http://www.delphipraxis.net/564756-post28.html

unit hddinfo;

interface

uses Windows, SysUtils, Classes;

const
IOCTL_STORAGE_QUERY_PROPERTY = $2D1400;

type
THDDInfo = class (TObject)
private
FDriveNumber: Byte;
FFileHandle: Cardinal;
FInfoAvailable: Boolean;
FProductRevision: string;
FProductId: string;
FSerialNumber: string;
FVendorId: string;
procedure ReadInfo;
procedure SetDriveNumber(const Value: Byte);
public
constructor Create;
property DriveNumber: Byte read FDriveNumber write SetDriveNumber;
property VendorId: string read FVendorId;
https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 2/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
property ProductId: string read FProductId;
property ProductRevision: string read FProductRevision;
property SerialNumber: string read FSerialNumber;
function SerialNumberInt: Cardinal;
function SerialNumberText: string;
function IsInfoAvailable: Boolean;
end;

implementation

type
STORAGE_PROPERTY_QUERY = packed record
PropertyId: DWORD;
QueryType: DWORD;
AdditionalParameters: array[0..3] of Byte;
end;

STORAGE_DEVICE_DESCRIPTOR = packed record


Version: ULONG;
Size: ULONG;
DeviceType: Byte;
DeviceTypeModifier: Byte;
RemovableMedia: Boolean;
CommandQueueing: Boolean;
VendorIdOffset: ULONG;
ProductIdOffset: ULONG;
ProductRevisionOffset: ULONG;
SerialNumberOffset: ULONG;
STORAGE_BUS_TYPE: DWORD;
RawPropertiesLength: ULONG;
RawDeviceProperties: array[0..511] of Byte;
end;

function ByteToChar(const B: Byte): Char;


begin
Result := Chr(B + $30)
end;

function SerialNumberToCardinal (SerNum: String): Cardinal;


begin
HexToBin(PChar(SerNum), PChar(@Result), SizeOf(Cardinal));
end;

function SerialNumberToString(SerNum: String): String;


var
I, StrLen: Integer;
Pair: string;
B: Byte;
Ch: Char absolute B;

begin
Result := '';
StrLen := Length(SerNum);

if Odd(StrLen) then Exit;

I := 1;

while I < StrLen do


begin
Pair := Copy (SerNum, I, 2);
HexToBin(PChar(Pair), PChar(@B), 1);
Result := Result + Chr(B);
Inc(I, 2);
end;

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 3/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
I := 1;

while I < Length(Result) do


begin
Ch := Result[I];
Result[I] := Result[I + 1];
Result[I + 1] := Ch;
Inc(I, 2);
end;
end;

constructor THddInfo.Create;
begin
inherited;

SetDriveNumber(0);
end;

function THDDInfo.IsInfoAvailable: Boolean;


begin
Result := FInfoAvailable
end;

procedure THDDInfo.ReadInfo;
type
PCharArray = ^TCharArray;
TCharArray = array[0..32767] of Char;

var
Returned: Cardinal;
Status: LongBool;
PropQuery: STORAGE_PROPERTY_QUERY;
DeviceDescriptor: STORAGE_DEVICE_DESCRIPTOR;
PCh: PChar;

begin
FInfoAvailable := False;
FProductRevision := '';
FProductId := '';
FSerialNumber := '';
FVendorId := '';

try
FFileHandle := CreateFile(
PChar('\\.\PhysicalDrive' + ByteToChar(FDriveNumber)),
0,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
0,
0
);

if FFileHandle = INVALID_HANDLE_VALUE then


RaiseLastOSError;

ZeroMemory(@PropQuery, SizeOf(PropQuery));
ZeroMemory(@DeviceDescriptor, SizeOf(DeviceDescriptor));

DeviceDescriptor.Size := SizeOf(DeviceDescriptor);

Status := DeviceIoControl(
FFileHandle,
IOCTL_STORAGE_QUERY_PROPERTY,
@PropQuery,
SizeOf(PropQuery),

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 4/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
@DeviceDescriptor,
DeviceDescriptor.Size,
Returned,
nil
);

if not Status then


RaiseLastOSError;

if DeviceDescriptor.VendorIdOffset <> 0 then


begin
PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.VendorIdOffset];
FVendorId := PCh;
end;

if DeviceDescriptor.ProductIdOffset <> 0 then


begin
PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductIdOffset];
FProductId := PCh;
end;

if DeviceDescriptor.ProductRevisionOffset <> 0 then


begin
PCh :=
@PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductRevisionOffset];
FProductRevision := PCh;
end;

if DeviceDescriptor.SerialNumberOffset <> 0 then


begin
PCh :=
@PCharArray(@DeviceDescriptor)^[DeviceDescriptor.SerialNumberOffset];
FSerialNumber := PCh;
end;

FInfoAvailable := True;
finally
if FFileHandle <> INVALID_HANDLE_VALUE then
CloseHandle(FFileHandle);
end;
end;

function THDDInfo.SerialNumberInt: Cardinal;


begin
Result := 0;
if ((IsInfoAvailable = True) and (FSerialNumber <> '')) then Result :=
SerialNumberToCardinal(FSerialNumber)
end;

function THDDInfo.SerialNumberText: string;


begin
Result := '';
if ((IsInfoAvailable = True) and (FSerialNumber <> '')) then Result :=
SerialNumberToString(FSerialNumber)
end;

procedure THDDInfo.SetDriveNumber(const Value: Byte);


begin
FDriveNumber := Value;
ReadInfo;
end;

end.

Edit: RAID configurations require special provisions.


https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 5/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow

For instance, I got a RAID system with multiple RAID 5 array; only the first one displays, and it
does not show the drive serial numbers, but the serial number of the RAID array:

VendorId: AMCC
ProductId: 9550SXU-16ML
ProductRevision: 3.08
SerialNumber: 006508296D6A2A00DE82
SerialNumberInt: 688416000

--jeroen

Share Improve this answer Follow edited May 23, 2017 at 10:27 answered Mar 6, 2011 at 7:53
Community Bot Jeroen Wiert Pluimers
1 1 23.4k 7 69 147

Thanks for your post, Yes, I saw this code before, but I can't found any way or library for translate it in
Delphi 7
–  Amin
Mar 6, 2011 at 8:07

@Amin maybe you can ask another question here for people to help you translate that code into
Delphi?
– Jeroen Wiert Pluimers
Mar 6, 2011 at 8:24

the key elements of the code in that C++ sample are h := CreateFile( Format("\\\\.\\PhysicalDrive%d",
drive), 0,...) and then DeviceIoControl (h, IOCTL_STORAGE_QUERY_PROPERTY, query, ...). The rest is error
checking and result checking.
– Warren P
Mar 6, 2011 at 15:47

2 /me thanks the downvoters for not leaving a comment; now please turn back your downvote into
upvote since I did edit it to add a complete working solution that does not require Admin rights.
– Jeroen Wiert Pluimers
Mar 6, 2011 at 21:16

1 I know this is not what the OP asked, but be noted the code doesn't work with SSD (which obviously is
not HDD) :)
– Edwin Yip
Jul 18, 2019 at 18:44

You can use the WMI (Windows Management Instrumentation) to get information related to
windows hardware.
6
Exist two wmi classes wich exposes a property called SerialNumber which store the Number
allocated by the manufacturer to identify the physical media. these classes are
Win32_DiskDrive and Win32_PhysicalMedia .to access the SerialNumber property of these
classes you must know the DeviceId of the Disk which is something like this
\\.\PHYSICALDRIVE0 . Another way is use a association class which link the Physical drive with
the logical drive (C,D,E)

so you must find this link previous to obtain the serial number. the sequence to find this
association is like this.

Win32_DiskPartition -> Win32_LogicalDiskToPartition -> Win32_DiskDrive

Note 1 : The SerialNumber property for the Win32_DiskDrive class does not exist in Windows
Server 2003, Windows XP, Windows 2000, and Windows NT 4.0, so how you are talking about
use Windows Vista or Windows 7, will work ok for you.

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 6/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow

Note 2 : The code does not require a administrator account to run.

check this code

{$APPTYPE CONSOLE}

uses
SysUtils,
ActiveX,
ComObj,
Variants;

function GetDiskSerial(const Drive:AnsiChar):string;


var
FSWbemLocator : OLEVariant;
objWMIService : OLEVariant;
colDiskDrives : OLEVariant;
colLogicalDisks: OLEVariant;
colPartitions : OLEVariant;
objDiskDrive : OLEVariant;
objPartition : OLEVariant;
objLogicalDisk : OLEVariant;
oEnumDiskDrive : IEnumvariant;
oEnumPartition : IEnumvariant;
oEnumLogical : IEnumvariant;
iValue : LongWord;
DeviceID : string;
begin;
Result:='';
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
objWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '',
''); //Connect to the WMI
colDiskDrives := objWMIService.ExecQuery('SELECT * FROM
Win32_DiskDrive','WQL',0);
oEnumDiskDrive:= IUnknown(colDiskDrives._NewEnum) as IEnumVariant;
while oEnumDiskDrive.Next(1, objDiskDrive, iValue) = 0 do
begin
DeviceID := StringReplace(objDiskDrive.DeviceID,'\','\\',
[rfReplaceAll]); //Escape the `\` chars in the DeviceID value because the '\' is
a reserved character in WMI.
colPartitions := objWMIService.ExecQuery(Format('ASSOCIATORS OF
{Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass =
Win32_DiskDriveToDiskPartition',[DeviceID]));//link the Win32_DiskDrive class
with the Win32_DiskDriveToDiskPartition class
oEnumPartition := IUnknown(colPartitions._NewEnum) as IEnumVariant;
while oEnumPartition.Next(1, objPartition, iValue) = 0 do
begin
colLogicalDisks := objWMIService.ExecQuery('ASSOCIATORS OF
{Win32_DiskPartition.DeviceID="'+objPartition.DeviceID+'"} WHERE AssocClass =
Win32_LogicalDiskToPartition'); //link the Win32_DiskPartition class with
theWin32_LogicalDiskToPartition class.
oEnumLogical := IUnknown(colLogicalDisks._NewEnum) as IEnumVariant;
while oEnumLogical.Next(1, objLogicalDisk, iValue) = 0 do
begin
if objLogicalDisk.DeviceID=(Drive+':') then //compare the device id
begin
Result:=objDiskDrive.SerialNumber;
Exit;
end;
objLogicalDisk:=Unassigned;
end;
objPartition:=Unassigned;
end;
end;

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 7/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
end;

begin
try
CoInitialize(nil);
try
Writeln(GetDiskSerial('C'));
Readln;
finally
CoUninitialize;
end;
except
on E:Exception do
begin
Writeln(E.Classname, ':', E.Message);
Readln;
end;
end;
end.

Share Improve this answer Follow answered Mar 6, 2011 at 21:40


RRUZ
133k 16 348 476

i've tried your code but return EOleSysError Bad variable type and pointing to this line colPartitions :=
objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE
AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID]));//link the Win32_DiskDrive class with the
Win32_DiskDriveToDiskPartition class
– Erwan
Mar 15, 2014 at 3:41

Which OS and Delphi version are you using?


– RRUZ
Mar 15, 2014 at 4:17

I have the same problem with EOleSysError at this line of code. I am using Windows 7. If I compile it
with Delphi 2007, it works; if I compile it with Delphi 10.1 Berlin, it does not work. Maybe it is a Unicode
problem? I couldn't find the problem, so I used this code, which worked for me:
stackoverflow.com/questions/4292395/…
– Daniel Marschall
Oct 17, 2016 at 16:52

Here is another DiskId32 translation from C++ to Delphi by Victor Derevyanko

1 project:
http://code.google.com/p/dvsrc/

Because the first method (WithZeroRights) doesn't work for me, I wrote another for
ReadIdeDriveAsScsiDriveInNT method:

unit HDScsiInfo;

interface

uses
Windows, SysUtils;

const
IDENTIFY_BUFFER_SIZE = 512;
FILE_DEVICE_SCSI = $0000001b;
IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI shl 16) + $0501);
IDE_ATA_IDENTIFY = $EC; // Returns ID sector for ATA.
IOCTL_SCSI_MINIPORT = $0004D008; // see NTDDSCSI.H for definition

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 8/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow

type
TDiskData = array [0..256-1] of DWORD;
TDriveInfo = record
ControllerType: Integer; //0 - primary, 1 - secondary, 2 - Tertiary, 3 -
Quaternary
DriveMS: Integer; //0 - master, 1 - slave
DriveModelNumber: String;
DriveSerialNumber: String;
DriveControllerRevisionNumber: String;
ControllerBufferSizeOnDrive: Int64;
DriveType: String; //fixed or removable or unknown
DriveSizeBytes: Int64;
end;

THDScsiInfo = class (TObject)


private
FDriveNumber: Byte;
FFileHandle: Cardinal;
FInfoAvailable: Boolean;
FProductRevision: string;
FSerialNumber: string;
FControllerType: Integer;
FDriveMS: Integer;
FDriveModelNumber: string;
FControllerBufferSizeOnDrive: Int64;
FDriveType: string;
FDriveSizeBytes: Int64;
procedure ReadInfo;
procedure SetDriveNumber(const Value: Byte);
procedure PrintIdeInfo(DiskData: TDiskData);
public
constructor Create;
property DriveNumber: Byte read FDriveNumber write SetDriveNumber;
property ProductRevision: string read FProductRevision;
property SerialNumber: string read FSerialNumber;
property ControllerType: Integer read FControllerType;
property DriveMS: Integer read FDriveMS;
property DriveModelNumber: string read FDriveModelNumber;
property ControllerBufferSizeOnDrive: Int64 read
FControllerBufferSizeOnDrive;
property DriveType: string read FDriveType;
property DriveSizeBytes: Int64 read FDriveSizeBytes;
function IsInfoAvailable: Boolean;
end;

implementation

type

SRB_IO_CONTROL = record
HeaderLength: Cardinal;
Signature: array [0..8-1] of Byte;
Timeout: Cardinal;
ControlCode: Cardinal;
ReturnCode: Cardinal;
Length: Cardinal;
end;
PSRB_IO_CONTROL = ^SRB_IO_CONTROL;

DRIVERSTATUS = record
bDriverError: Byte;// Error code from driver, or 0 if no error.
bIDEStatus: Byte;// Contents of IDE Error register.
// Only valid when bDriverError is SMART_IDE_ERROR.
bReserved: array [0..1] of Byte;// Reserved for future expansion.
dwReserved: array [0..1] of Longword;// Reserved for future expansion.

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 9/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
end;

SENDCMDOUTPARAMS = record
cBufferSize: Longword;// Size of bBuffer in bytes
DriverStatus: DRIVERSTATUS;// Driver status structure.
bBuffer: array [0..0] of Byte;// Buffer of arbitrary length in which to store
the data read from the //
drive.
end;
IDEREGS = 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;
SENDCMDINPARAMS = record
cBufferSize: Longword;// Buffer size in bytes
irDriveRegs: IDEREGS; // Structure with drive register values.
bDriveNumber: Byte;// Physical drive number to send
// command to (0,1,2,3).
bReserved: array[0..2] of Byte;// Reserved for future expansion.
dwReserved: array [0..3] of Longword;// For future use.
bBuffer: array [0..0] of Byte;// Input buffer. //!TODO: this is array of
single element
end;
PSENDCMDINPARAMS = ^SENDCMDINPARAMS;

PSENDCMDOUTPARAMS = ^SENDCMDOUTPARAMS;
IDSECTOR = record
wGenConfig: Word;
wNumCyls: Word;
wReserved: Word;
wNumHeads: Word;
wBytesPerTrack: Word;
wBytesPerSector: Word;
wSectorsPerTrack: Word;
wVendorUnique: array [0..3-1] of Word;
sSerialNumber: array [0..20-1] of AnsiChar;
wBufferType: Word;
wBufferSize: Word;
wECCSize: Word;
sFirmwareRev: array [0..8-1] of AnsiChar;
sModelNumber: array [0..40-1] of AnsiChar;
wMoreVendorUnique: Word;
wDoubleWordIO: Word;
wCapabilities: Word;
wReserved1: Word;
wPIOTiming: Word;
wDMATiming: Word;
wBS: Word;
wNumCurrentCyls: Word;
wNumCurrentHeads: Word;
wNumCurrentSectorsPerTrack: Word;
ulCurrentSectorCapacity: Cardinal;
wMultSectorStuff: Word;
ulTotalAddressableSectors: Cardinal;
wSingleWordDMA: Word;
wMultiWordDMA: Word;
bReserved: array [0..128-1] of Byte;
end;
PIDSECTOR = ^IDSECTOR;

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 10/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
TArrayDriveInfo = array of TDriveInfo;

type
DeviceQuery = record
HeaderLength: Cardinal;
Signature: array [0..8-1] of Byte;
Timeout: Cardinal;
ControlCode: Cardinal;
ReturnCode: Cardinal;
Length: Cardinal;
cBufferSize: Longword;// Buffer size in bytes
irDriveRegs: IDEREGS; // Structure with drive register values.
bDriveNumber: Byte;// Physical drive number to send
bReserved: array[0..2] of Byte;// Reserved for future expansion.
dwReserved: array [0..3] of Longword;// For future use.
bBuffer: array [0..0] of Byte;// Input buffer. //!TODO: this is array of
single element
end;

function ConvertToString (diskdata: TDiskData;


firstIndex: Integer;
lastIndex: Integer;
buf: PAnsiChar): PAnsiChar;
var
index: Integer;
position: Integer;
begin
position := 0;
// each integer has two characters stored in it backwards
for index := firstIndex to lastIndex do begin
// get high byte for 1st character
buf[position] := AnsiChar(Chr(diskdata [index] div 256));
inc(position);
// get low byte for 2nd character
buf [position] := AnsiChar(Chr(diskdata [index] mod 256));
inc(position);
end;
// end the string
buf[position] := Chr(0);

// cut off the trailing blanks


index := position - 1;
while (index >0) do begin
// if not IsSpace(AnsiChar(buf[index]))
if (AnsiChar(buf[index]) <> ' ')
then break;
buf [index] := Chr(0);
dec(index);
end;

Result := buf;
end;

constructor THDScsiInfo.Create;
begin
inherited;
SetDriveNumber(0);
end;

function THDScsiInfo.IsInfoAvailable: Boolean;


begin
Result := FInfoAvailable
end;

procedure THDScsiInfo.PrintIdeInfo (DiskData: TDiskData);


var

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 11/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
nSectors: Int64;
serialNumber: array [0..1024-1] of AnsiChar;
modelNumber: array [0..1024-1] of AnsiChar;
revisionNumber: array [0..1024-1] of AnsiChar;
begin
// copy the hard drive serial number to the buffer
ConvertToString (DiskData, 10, 19, @serialNumber);
ConvertToString (DiskData, 27, 46, @modelNumber);
ConvertToString (DiskData, 23, 26, @revisionNumber);
FControllerType := FDriveNumber div 2;
FDriveMS := FDriveNumber mod 2;
FDriveModelNumber := modelNumber;
FSerialNumber := serialNumber;
FProductRevision := revisionNumber;
FControllerBufferSizeOnDrive := DiskData [21] * 512;
if ((DiskData [0] and $0080) <> 0)
then FDriveType := 'Removable'
else if ((DiskData [0] and $0040) <> 0)
then FDriveType := 'Fixed'
else FDriveType := 'Unknown';
// calculate size based on 28 bit or 48 bit addressing
// 48 bit addressing is reflected by bit 10 of word 83
if ((DiskData[83] and $400) <> 0) then begin
nSectors := DiskData[103] * Int64(65536) * Int64(65536) * Int64(65536) +
DiskData[102] * Int64(65536) * Int64(65536) +
DiskData[101] * Int64(65536) +
DiskData[100];
end else begin
nSectors := DiskData [61] * 65536 + DiskData [60];
end;
// there are 512 bytes in a sector
FDriveSizeBytes := nSectors * 512;
end;

procedure THDScsiInfo.ReadInfo;
type
DataArry = array [0..256-1] of WORD;
PDataArray = ^DataArry;
const
SENDIDLENGTH = sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
var
I: Integer;
buffer: array [0..sizeof (SRB_IO_CONTROL) + SENDIDLENGTH - 1] of AnsiChar;
dQuery: DeviceQuery;
dummy: DWORD;
pOut: PSENDCMDOUTPARAMS;
pId: PIDSECTOR;
DiskData: TDiskData;
pIdSectorPtr: PWord;
begin
FInfoAvailable := False;
FFileHandle := CreateFile (PChar(Format('\\.\Scsi%d:', [FDriveNumber])),
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, 0, 0);
if (FFileHandle <> INVALID_HANDLE_VALUE) then begin
ZeroMemory(@dQuery, SizeOf(dQuery));
dQuery.HeaderLength := sizeof (SRB_IO_CONTROL);
dQuery.Timeout := 10000;
dQuery.Length := SENDIDLENGTH;
dQuery.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;
StrLCopy(@dQuery.Signature, 'SCSIDISK', 8);
dQuery.irDriveRegs.bCommandReg := IDE_ATA_IDENTIFY;
dQuery.bDriveNumber := FDriveNumber;
if (DeviceIoControl (FFileHandle, IOCTL_SCSI_MINIPORT,
@dQuery,

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 12/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
SizeOf(dQuery),
@buffer,
sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
dummy, nil))
then begin
pOut := PSENDCMDOUTPARAMS(buffer + sizeof (SRB_IO_CONTROL));
//!TOCHECK
pId := PIDSECTOR(@pOut^.bBuffer[0]);
if (pId^.sModelNumber[0] <> Chr(0) ) then begin
pIdSectorPtr := PWord(pId);
for I := 0 to 256-1 do
DiskData[I] := PDataArray(pIdSectorPtr)[I];
PrintIdeInfo (DiskData);
FInfoAvailable := True;
end;

end;
CloseHandle(FFileHandle);
end;
end;

procedure THDScsiInfo.SetDriveNumber(const Value: Byte);


begin
FDriveNumber := Value;
ReadInfo;
end;

end.

Sample usage:

procedure ReadIdeDriveAsScsiDriveInNT;
var
DriveNumber: Byte;
HDDInfo: THDScsiInfo;
begin
HDDInfo := THDScsiInfo.Create();
try
for DriveNumber := 0 to MAX_IDE_DRIVES - 1 do
try
HDDInfo.DriveNumber := DriveNumber;
if HDDInfo.IsInfoAvailable then begin
Writeln('Available Drive: ', HDDInfo.DriveNumber);
Writeln('ControllerType: ', HDDInfo.ControllerType);
Writeln('DriveMS: ', HDDInfo.DriveMS);
Writeln('DriveModelNumber: ', HDDInfo.DriveModelNumber);
Writeln('ControllerBufferSizeOnDrive: ',
HDDInfo.ControllerBufferSizeOnDrive);
Writeln('DriveType: ', HDDInfo.DriveType);
Writeln('DriveSizeBytes: ', HDDInfo.DriveSizeBytes);
Writeln('ProductRevision: ', HDDInfo.ProductRevision);
Writeln('SerialNumber: ', HDDInfo.SerialNumber);
end;
except
on E: Exception do
Writeln(Format('DriveNumber %d, %s: %s', [DriveNumber, E.ClassName,
E.Message]));
end;
finally
HDDInfo.Free;
end;
end;

begin
https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 13/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow
ReadIdeDriveAsScsiDriveInNT;
Write('Press <Enter>');
end.

This works great with my WD disk.

Share Improve this answer Follow edited Nov 14, 2011 at 19:49 answered Nov 13, 2011 at 4:28
Kachwahed
542 7 16

I found this code, it is fixed one and working fine with me on windows 7 64

1 https://code.google.com/p/dvsrc/downloads/detail?
name=20120116DiskId32Port_fixed.7z&can=2&q=

and this his all work

https://code.google.com/p/dvsrc/downloads/list

Share Improve this answer Follow answered Jun 27, 2013 at 11:00
wahm sarab
89 5

Please, try to summarize the contents of the pages you linked, instead of just link them.
– toro2k
Jun 27,
2013 at 11:22

Posting this purely for completeness sake, and to possibly satisfy those interested or die hard
hardware fanatics.
0
I do not have a Pascal compiler at my disposal to test these routines on current Windows
systems, but I do know this code worked back in the DOS era. Maybe it still works from a
command prompt window.

Pascal code:

uses
Dos, Crt;

type
SerNoType = record
case Integer of
0: (SerNo1, SerNo2: Word);
1: (SerNo: Longint);
end;

DiskSerNoInfoType = record
Infolevel: Word;
VolSerNo: SerNoType;
VolLabel: array[1..11] of Char;
FileSys: array[1..8] of Char;
end;

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 14/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow

function HexDigit(N: Byte): Char;


begin
if N < 10 then
HexDigit := Chr(Ord('0') + N)
else
HexDigit := Chr(Ord('A') + (N - 10));
end;

function GetVolSerialNo(DriveNo: Byte): String;


var
ReturnArray: DiskSerNoInfoType;
Regs: Registers;
begin
with Regs do
begin
AX := $440d;
BL := DriveNo;
CH := $08;
CL := $66;
DS := Seg(ReturnArray);
DX := Ofs(ReturnArray);
Intr($21, Regs);
if (Flags and FCarry) <> 0 then
GetVolSerialNo := ''
else
with ReturnArray.VolSerNo do
GetVolSerialNo :=
HexDigit(Hi(SerNo2) div 16) + HexDigit(Hi(SerNo2) mod 16) +
HexDigit(Lo(SerNo2) div 16) + HexDigit(Lo(SerNo2) mod 16) +
HexDigit(Hi(SerNo1) div 16) + HexDigit(Hi(SerNo1) mod 16) +
HexDigit(Lo(SerNo1) div 16) + HexDigit(Lo(SerNo1) mod 16);
end;
end;

procedure PutVolSerialNo(DriveNo: Byte; SerialNo: Longint);


var
ReturnArray: DiskSerNoInfoType;
Regs: Registers;
begin
with Regs do
begin
AX := $440d;
BL := DriveNo;
CH := $08;
CL := $66;
DS := Seg(ReturnArray);
DX := Ofs(ReturnArray);
Intr($21, Regs);
if (Flags and FCarry) = 0 then
begin
ReturnArray.VolSerNo.SerNo := SerialNo;
AH := $69;
BL := DriveNo;
AL := $01;
DS := Seg(ReturnArray);
DX := Ofs(ReturnArray);
Intr($21, Regs);
end;
end;
end;

Please feel free to update this answer in order to get it working (if possible at all) in Delphi.

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 15/16
5/12/22, 10:19 AM delphi - in Delphi7, How can I retrieve hard disk unique serial number? - Stack Overflow

Share Improve this answer Follow answered Nov 15, 2011 at 22:35
NGLN
41.9k 8 103 194

https://stackoverflow.com/questions/5202270/in-delphi7-how-can-i-retrieve-hard-disk-unique-serial-number 16/16

You might also like