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;
PSTORAGE_BUS_TYPE = ^STORAGE_BUS_TYPE;
STORAGE_BUS_TYPE = (BusTypeUnknown = $00, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre, BusTypeUsb, BusTypeRAID, BusTypeMaxReserved = $7F);
PSTORAGE_QUERY_TYPE = ^STORAGE_QUERY_TYPE;
STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined);
PSTORAGE_PROPERTY_ID = ^STORAGE_PROPERTY_ID;
STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty);
PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY;
STORAGE_PROPERTY_QUERY =
record
PropertyId: STORAGE_PROPERTY_ID;
QueryType: STORAGE_QUERY_TYPE;
AdditionalParameters:
array[0..0]
of UCHAR;
end;
PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR;
STORAGE_DEVICE_DESCRIPTOR =
record
Version: ULONG;
Size: ULONG;
DeviceType: UCHAR;
DeviceTypeModifier: UCHAR;
RemovableMedia: Boolean;
CommandQueueing: Boolean;
VendorIdOffset: ULONG;
ProductIdOffset: ULONG;
ProductRevisionOffset: ULONG;
SerialNumberOffset: ULONG;
BusType: STORAGE_BUS_TYPE;
RawPropertiesLength: ULONG;
RawDeviceProperties:
array[0..0]
of UCHAR;
end;
TIDERegs =
packed 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. Must be 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;
const
Method_Buffered = 0;
File_Any_Access = 0;
File_Device_Mass_Storage = $0000002D;
IOCTL_Storage_Base = File_Device_Mass_Storage;
MAX_IDE_DRIVES = 16;
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;
query : STORAGE_PROPERTY_QUERY;
IOCTL_STORAGE_QUERY_PROPERTY : cardinal;
begin
IOCTL_STORAGE_QUERY_PROPERTY := CTL_CODE(IOCTL_STORAGE_BASE, $0500, METHOD_BUFFERED, FILE_ANY_ACCESS);
Result := '
';
FillChar(Buffer,BufferSize,#0);
if Win32Platform=VER_PLATFORM_WIN32_NT
then
begin // Windows NT, Windows 2000
hDevice := CreateFile(
'
\\.\PhysicalDrive0',
0,
//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
query.PropertyId := StorageDeviceProperty;
query.QueryType := PropertyStandardQuery;
if not DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
@
query, sizeof (
query), @Buffer, BufferSize,
cbBytesReturned,
nil )
then Exit;
finally
CloseHandle(hDevice);
end;
end;
end;