//获得硬盘序列号<br>function GetIdeSerialNumber() : PChar; stdcall;<br>const<br> IDENTIFY_BUFFER_SIZE = 512;<br>type<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><br> TSendCmdInParams = packed record<br> // Buffer size in bytes<br> cBufferSize: DWORD;<br> // Structure with drive register values.<br> irDriveRegs: TIDERegs;<br> // Physical drive number to send command to (0,1,2,3).<br> bDriveNumber: BYTE;<br> bReserved: array[0..2] of Byte;<br> dwReserved: array[0..3] of DWORD;<br> bBuffer: array[0..0] of Byte; // Input buffer.<br> end;<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: DWORD;<br> wMultSectorStuff: Word;<br> ulTotalAddressableSectors: DWORD;<br> wSingleWordDMA: Word;<br> wMultiWordDMA: Word;<br> bReserved: array[0..127] of BYTE;<br> end;<br><br> PIdSector = ^TIdSector;<br><br> TDriverStatus = packed record<br> // 驱动器返回的错误代码,无错则返回0<br> bDriverError: Byte;<br> // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效<br> bIDEStatus: Byte;<br> bReserved: array[0..1] of Byte;<br> dwReserved: array[0..1] of DWORD;<br> end;<br><br> TSendCmdOutParams = packed record<br> // bBuffer的大小<br> cBufferSize: DWORD;<br> // 驱动器状态<br> DriverStatus: TDriverStatus;<br> // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定<br> bBuffer: array[0..0] of BYTE;<br> end;<br>var<br> hDevice : THandle;<br> cbBytesReturned : DWORD;<br> SCIP : TSendCmdInParams;<br> aIdOutCmd : array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1) - 1] of Byte;<br> IdOutCmd : TSendCmdOutParams absolute aIdOutCmd;<br><br> procedure ChangeByteOrder(var Data; Size: Integer);<br> var<br> ptr : PChar;<br> i : Integer;<br> c : Char;<br> begin<br> ptr := @Data;<br><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>begin<br> Result := ''; // 如果出错则返回空串<br><br> if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000<br> begin<br> // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '//./PhysicalDrive1/'<br> hDevice := CreateFile('//./PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,<br> FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);<br> end<br> else // Version Windows 95 OSR2, Windows 98<br> hDevice := CreateFile('//./SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);<br><br> if hDevice = INVALID_HANDLE_VALUE then Exit;<br><br> try<br> FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);<br> FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);<br> cbBytesReturned := 0;<br><br> // Set up data structures for IDENTIFY command.<br> with SCIP do<br> begin<br> cBufferSize := IDENTIFY_BUFFER_SIZE;<br><br> // bDriveNumber := 0;<br> with irDriveRegs do<br> begin<br> bSectorCountReg := 1;<br> bSectorNumberReg := 1;<br><br> // if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0<br> // else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);<br> bDriveHeadReg := $A0;<br> bCommandReg := $EC;<br> end;<br> end;<br><br> if not DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) - 1,<br> @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;<br> finally<br> CloseHandle(hDevice);<br> end;<br><br> with PIdSector(@IdOutCmd.bBuffer)^ do<br> begin<br> ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));<br> (Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;<br><br> Result := Pchar(@sSerialNumber);<br><br> end;<br>end;