读硬盘序列号,现成的函数<br><br>function GetIdeDiskSerialNumber : String;<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 for future use. Must be zero.<br> end;<br> IDEREGS = TIDERegs;<br> PIDERegs = ^TIDERegs;<br><br> TSendCmdInParams = packed record<br> cBufferSize : DWORD; // Buffer size in bytes<br> irDriveRegs : TIDERegs; // Structure with drive register values.<br> bDriveNumber : Byte; // Physical drive number to send command to (0,1,2,3).<br> bReserved : Array[0..2] of Byte; // Reserved for future expansion.<br> dwReserved : Array[0..3] of DWORD; // For future use.<br> bBuffer : Array[0..0] of Byte; // Input buffer.<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>var<br> hDevice : THandle;<br> cbBytesReturned : DWORD;<br> pInData : PSendCmdInParams;<br> pOutData : Pointer; // PSendCmdInParams;<br> Buffer : Array[0..BufferSize-1] of Byte;<br> srbControl : TSrbIoControl absolute Buffer;<br><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>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:', GENERIC_READ or GENERIC_WRITE,<br> FILE_SHARE_READ or FILE_SHARE_WRITE, 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)+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, @Buffer, BufferSize, @Buffer, BufferSize, 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, CREATE_NEW, 0, 0 );<br> if hDevice=INVALID_HANDLE_VALUE then Exit;<br> try<br> pInData := PSendCmdInParams(@Buffer);<br> pOutData := PChar(@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, pInData, SizeOf(TSendCmdInParams)-1, pOutData, 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>