How to read the manufacturer’s serial number from a Hard Drive with Delphi — and without WMI
It’s surprisingly a non-trivial issue to retrieve the manufacturer’s information from a hard drive. Some people recommend using the GetVolumeInformation API function. The problem is that this is not the serial number printed on the hard drive and assigned by the manufacturer, but is (according to the MSDN documentation):
This function returns the volume serial number that the operating system assigns when a hard disk is formatted. To programmatically obtain the hard disk’s serial number that the manufacturer assigns, use the Windows Management Instrumentation (WMI) Win32_PhysicalMedia property SerialNumber.
Notice also that it recommends to use the WMI Win32_Physical Media property “SerialNumber” to obtain the manufacturer’s serial. Interestingly enough, this won’t work 100% of the time. The reason is that this property is optionally defined by the manufacturer and must be supplied by the hard disk driver.
So if we can’t use GetVolumeInformation() and we can’t rely on WMI 100% of the time, what can we do? Well, it involves querying several sources of information on a system directly. It also means we have to care if the drive is SATA, IDE, etc. Well, the smart folks at WinSim Inc., wore an open-source application called DiskId32:
DiskId32 is a Win32 console utility for reading the manufacturer’s information from your hard drives. It runs under Windows 9X, Win NT, Win 2K and Win XP (Pro/Home). DiskId32 does not run on plain old DOS and I highly doubt that it works on Windows 3.x. It does NOT require administrator rights for Win NT/2K.
I have seen this application recommended on many occasions, although there are other solutions that use similar methods.
There is an open-source application called DiskID32 that is written in C++. Looking at the source code, it takes many scenarios in mind when attempting to retrieve disk information. It also works on Vista and Windows 7. You can find full history on the application and it’s change-log here: http://www.winsim.com/diskid32/diskid32.html
Of course, I don’t expect you to convert it to Delphi. I found someone that has already done that. However, if you download the code from his website, you will have to fix 1 error in “hwid_impl.pas” on line 1504. The BROKEN CODE is:
while ((HardDriveSerialNumber[ip] <> Chr(0)) and (ip < 1024)) do begin if ('-' = HardDriveSerialNumber[ip]) then continue;
The problem is that the counter variable ip is not incremented when a dash is detected in the serial number. Result is an endless loop.. You would need to change it to:
while ((HardDriveSerialNumber[ip] <> Chr(0)) and (ip < 1024)) do begin if ('-' = HardDriveSerialNumber[ip]) then begin inc(ip); continue; end; end;