unit main;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br> StdCtrls;<br>type<br> TSrbIoControl = packed record<br> HeaderLength : ULONG;<br> Signature : Array[0..7] of Char; <br> Timeout : ULONG; <br> ControlCode : ULONG; <br> ReturnCode : ULONG;<br> Length : ULONG; <br> end; <br> SRB_IO_CONTROL = TSrbIoControl; <br> PSrbIoControl = ^TSrbIoControl; <br><br> TIDERegs = packed record <br> bFeaturesReg : Byte; // Used for specifying SMART "commands". <br> bSectorCountReg : Byte; // IDE sector count register<br> bSectorNumberReg : Byte; // IDE sector number register <br> bCylLowReg : Byte; // IDE low order cylinder value <br> bCylHighReg : Byte; // IDE high order cylinder value <br> bDriveHeadReg : Byte; // IDE drive/head register <br> bCommandReg : Byte; // Actual IDE command. <br> bReserved : Byte; // reserved. Must be zero. <br> end;<br> IDEREGS = TIDERegs;<br> PIDERegs = ^TIDERegs; <br><br> TSendCmdInParams = packed record <br> cBufferSize : DWORD; <br> irDriveRegs : TIDERegs; <br> bDriveNumber : Byte; <br> bReserved : Array[0..2] of Byte; <br> dwReserved : Array[0..3] of DWORD;<br> bBuffer : Array[0..0] of Byte;<br> end;<br> SENDCMDINPARAMS = TSendCmdInParams;<br> PSendCmdInParams = ^TSendCmdInParams; <br><br> TIdSector = packed record <br> wGenConfig : Word; <br> wNumCyls : Word;<br> wReserved : Word; <br> wNumHeads : Word; <br> wBytesPerTrack : Word; <br> wBytesPerSector : Word; <br> wSectorsPerTrack : Word; <br> wVendorUnique : Array[0..2] of Word;<br> sSerialNumber : Array[0..19] of Char; <br> wBufferType : Word; <br> wBufferSize : Word; <br> wECCSize : Word; <br> sFirmwareRev : Array[0..7] of Char; <br> sModelNumber : Array[0..39] of Char;<br> wMoreVendorUnique : Word; <br> wDoubleWordIO : Word; <br> wCapabilities : Word; <br> wReserved1 : Word; <br> wPIOTiming : Word; <br> wDMATiming : Word;<br> wBS : Word; <br> wNumCurrentCyls : Word; <br> wNumCurrentHeads : Word; <br> wNumCurrentSectorsPerTrack : Word; <br> ulCurrentSectorCapacity : ULONG; <br> wMultSectorStuff : Word;<br> ulTotalAddressableSectors : ULONG; <br> wSingleWordDMA : Word; <br> wMultiWordDMA : Word; <br> bReserved : Array[0..127] of Byte; <br> end;<br> PIdSector = ^TIdSector; <br><br>const<br> IDE_ID_FUNCTION = $EC; <br> IDENTIFY_BUFFER_SIZE = 512;<br> DFP_RECEIVE_DRIVE_DATA = $0007c088;<br> IOCTL_SCSI_MINIPORT = $0004d008;<br> IOCTL_SCSI_MINIPORT_IDENTIFY = $001b0501;<br> DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;<br> BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize;<br> W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;<br>type<br> TForm1 = class(TForm)<br> Button1: TButton;<br> Edit1: TEdit;<br> procedure Button1Click(Sender: TObject);<br> private<br> { Private declarations }<br> public<br> { Public declarations }<br> end;<br><br>var<br> Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br>procedure ChangeByteOrder( var Data; Size : Integer );<br> var ptr : PChar;<br> i : Integer;<br> c : Char;<br> begin<br> ptr := @Data;<br> for i := 0 to (Size shr 1)-1 do<br> begin<br> c := ptr^;<br> ptr^ := (ptr+1)^;<br> (ptr+1)^ := c;<br> Inc(ptr,2);<br> end;<br> end;<br><br>function GetIdeDiskSerialNumber : String;<br><br>var <br> hDevice : THandle; <br> cbBytesReturned : DWORD; <br> pInData : PSendCmdInParams; <br> pOutData : Pointer; // PSendCmdOutParams <br> Buffer : Array[0..BufferSize-1] of Byte;<br> srbControl : TSrbIoControl absolute Buffer;<br>begin<br> Result := '';<br> FillChar(Buffer,BufferSize,#0);<br> if Win32Platform=VER_PLATFORM_WIN32_NT then<br> begin // Windows NT, Windows 2000<br> // Get SCSI port handle<br> hDevice := CreateFile( '//./Scsi0:',<br> GENERIC_READ or GENERIC_WRITE,<br> FILE_SHARE_READ or FILE_SHARE_WRITE,<br> nil, OPEN_EXISTING, 0, 0 );<br> if hDevice=INVALID_HANDLE_VALUE then Exit;<br> try<br> srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);<br> System.Move('SCSIDISK',srbControl.Signature,8);<br> srbControl.Timeout := 2;<br> srbControl.Length := DataSize;<br> srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;<br> pInData := PSendCmdInParams(PChar(@Buffer)<br> +SizeOf(SRB_IO_CONTROL));<br> pOutData := pInData;<br> with pInData^ do<br> begin<br> cBufferSize := IDENTIFY_BUFFER_SIZE;<br> bDriveNumber := 0;<br> with irDriveRegs do<br> begin<br> bFeaturesReg := 0;<br> bSectorCountReg := 1;<br> bSectorNumberReg := 1;<br> bCylLowReg := 0;<br> bCylHighReg := 0;<br> bDriveHeadReg := $A0;<br> bCommandReg := IDE_ID_FUNCTION;<br> end;<br> end;<br> if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT,<br> @Buffer, BufferSize, @Buffer, BufferSize,<br> cbBytesReturned, nil ) then Exit;<br> finally<br> CloseHandle(hDevice);<br> end;<br> end<br> else<br> begin // Windows 95 OSR2, Windows 98<br> hDevice := CreateFile( '//./SMARTVSD', 0, 0, nil,<br> CREATE_NEW, 0, 0 );<br> if hDevice=INVALID_HANDLE_VALUE then Exit;<br> try<br> pInData := PSendCmdInParams(@Buffer);<br> pOutData := @pInData^.bBuffer;<br> with pInData^ do<br> begin<br> cBufferSize := IDENTIFY_BUFFER_SIZE;<br> bDriveNumber := 0;<br> with irDriveRegs do<br> begin<br> bFeaturesReg := 0;<br> bSectorCountReg := 1;<br> bSectorNumberReg := 1;<br> bCylLowReg := 0;<br> bCylHighReg := 0;<br> bDriveHeadReg := $A0;<br> bCommandReg := IDE_ID_FUNCTION;<br> end;<br> end;<br> if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA,<br> pInData, SizeOf(TSendCmdInParams)-1, pOutData,<br> W9xBufferSize, cbBytesReturned, nil ) then Exit;<br> finally<br> CloseHandle(hDevice);<br> end;<br> end;<br> with PIdSector(PChar(pOutData)+16)^ do<br> begin<br> ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));<br> SetString(Result,sSerialNumber,SizeOf(sSerialNumber));<br> end;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>EDIT1.TEXT:=TRIM(GetIdeDiskSerialNumber);<br>end;<br><br>END.<br><br>//win98要 c:/windows/system/的smartvsd.vxd<br>//copy to c:/windows/system/iosubsys<br>//reboot your computer and ok<br>//2000 and nt do not need