Unit HDID;
Interface
uses Windows, Controls, SysUtils, Forms; //, Graphics, Dialogs, Classes, Messages, StdCtrls; 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; // 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 CBuffers: 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; WORCSIZE: WORD; Sfirmwarerev: Array [0..7] of char; smodelnumber: array [0..39] of char; wmorevendorunique: Word; WDOUBLORDIO: WORD; Word; word; word; word; word; word; word; word; word; 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 ; THDIDIDFORM = Class (TFORM) private {private declarations} end;
Var HDIDM: THDIDIDIDISKSERIALNUMBER: STRING
IMPLEMENTATION
{$ R * .dfm} Procedure ChangeByteorder (var data; size: 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;
Function GetidiskSerialNumber: String;
var hDevice: THandle; cbBytesReturned: DWORD; pInData: PSendCmdInParams; pOutData: Pointer; // PSendCmdOutParams Buffer: Array [0..BufferSize-1] of Byte; srbControl: TSrbIoControl absolute Buffer; begin Result: = ''; FillChar (Buffer , BufferSize, # 0); if Win32Platform = VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000 // Get SCSI port handle hDevice: = CreateFile ( '//./Scsi0:', 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)...
Else Begin // Windows 95 OSR2, Windows 98 HDevice: = Createfile ('//./smartvsd', 0, 0); if HDevice = Invalid_Handle_Value The 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; end.
// Win98 to be c: / windows / system / smartvsd.vxd // copy to c: // reboot your computer and ok // 2000 and nt do not need get the hard disk physical serial number:
Uses HDID;
HDSN: = Trim (getidediskSerialNumber);