98下如何获得硬盘序列号?(100分)

  • 主题发起人 主题发起人 jieson
  • 开始时间 开始时间
J

jieson

Unregistered / Unconfirmed
GUEST, unregistred user!
<br><br>我搜过以前的帖子,下面这个号称能获得,但是我在d6下编译有三处语法错误:<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br>type<br>&nbsp;TGate = record<br>&nbsp; &nbsp; &nbsp;Off2,op,seg,off1:WORD;<br>&nbsp;end;<br>&nbsp;LONGDWORD = INT64;<br>var<br>&nbsp; IDTR: LONGDWORD;<br>&nbsp; SavedGate:TGate;<br>&nbsp; OurGate: TGate;<br>&nbsp; dd: array [0..256] of word;<br>&nbsp; dsn:array [0..20] of char; //存放硬盘序列号<br><br>procedure Ring0Proc();<br>asm<br>// Wait for controller not busy<br>mov dx,01f7h<br>@1:in al,dx<br>cmp al,050h<br>jne &nbsp;@1<br><br>// Get first/second drive<br>dec dx<br>mov al,0a0h<br>out dx,al<br><br>// Get drive info data<br>inc dx<br>mov al,0ech<br>out dx,al<br>nop<br>nop<br><br>// Wait for data ready<br>@2:in al,dx<br>cmp al,058h<br>jne &nbsp;@2<br>nop<br>nop<br>// Read sector<br>xor ecx,ecx<br>mov dx,01f0h<br>@3:in ax,dx<br>mov word ptr dd[ecx*2],ax &nbsp; &nbsp;// &lt;------这里有语法错误<br>inc ecx<br>cmp ecx,256<br>jne @3<br><br>iretd &nbsp;//中断返回<br>end;<br><br>procedure Change2Ring0();<br>begin<br>&nbsp; asm<br>&nbsp; &nbsp; &nbsp; mov &nbsp; eax, offset Ring0Proc<br>&nbsp; &nbsp; &nbsp; mov &nbsp; OurGate.off2, ax &nbsp;// 将 中 断 函 数 的 地 址<br>&nbsp; &nbsp; &nbsp; shr &nbsp; eax, 16 &nbsp; // 填 入 新 造 的 中 断 门<br>&nbsp; &nbsp; &nbsp; mov &nbsp; OurGate.off1, ax // 描 述 符<br>&nbsp; &nbsp; &nbsp; mov &nbsp; OurGate.op,0028h<br>&nbsp; &nbsp; &nbsp; mov &nbsp; OurGate.seg,0ee00h &nbsp;// &lt;------这里有语法错误<br>&nbsp; &nbsp; &nbsp; mov &nbsp; ebx,offset IDTR<br>&nbsp; &nbsp; &nbsp; sidt &nbsp;[ebx]<br>&nbsp; &nbsp; &nbsp; // 将 中 断 描 述 符 表 寄 存 器(IDTR)的 内 容 取 出<br>&nbsp; &nbsp; &nbsp; mov &nbsp; ebx, dword ptr [IDTR+2]<br>&nbsp; &nbsp; &nbsp; // 取 出 中 断 描 述 符 表(IDT) 基 地 址<br>&nbsp; &nbsp; &nbsp; add &nbsp; ebx, 8*3<br>&nbsp; &nbsp; &nbsp; // 计 算Int 3 的 描 述 符 应 放 置 的 地 址 选 用<br>&nbsp; &nbsp; &nbsp; //Int3 是 因 为 它 在Win32 保 护 模 式 下 未 占 用<br>&nbsp; &nbsp; &nbsp; mov &nbsp; &nbsp; &nbsp;edi, offset SavedGate<br>&nbsp; &nbsp; &nbsp; mov &nbsp; &nbsp; &nbsp;esi, ebx<br>&nbsp; &nbsp; &nbsp; movsd &nbsp; // 保 存 原 来 的Int 9 描 述 符 到<br>&nbsp; &nbsp; &nbsp; movsd &nbsp;//SavedGate 以 便 恢 复<br><br>&nbsp; &nbsp; &nbsp; mov &nbsp; &nbsp; &nbsp;edi, ebx<br>&nbsp; &nbsp; &nbsp; mov &nbsp; &nbsp; &nbsp;esi, offset OurGate<br>&nbsp; &nbsp; &nbsp; cli<br>&nbsp; &nbsp; &nbsp; movsd &nbsp;// 替 换 原 来 的 中 断 门 描 述 符<br>&nbsp; &nbsp; &nbsp; movsd &nbsp;// 以 安 装 中 断 服 务 例 程<br>&nbsp; &nbsp; &nbsp; sti<br>&nbsp; &nbsp; &nbsp; mov &nbsp; eax,6200h<br>&nbsp; &nbsp; &nbsp;// 用 以 测 试 放 在EAX 中 的 数 据 &nbsp;能 否 正 确 传 到Ring0 中 断<br>&nbsp; &nbsp; &nbsp; mov &nbsp; ecx,0<br>&nbsp; &nbsp; &nbsp;// 用 以 测 试 放 在ECX 中 的 数 据<br>&nbsp; &nbsp; &nbsp;// &nbsp;能 否 正 确 传 到Ring0 中 断<br>&nbsp; &nbsp; &nbsp; // 因 为 很 多VxD 服 务 都 用此二 寄 存 器 传 递 参 数<br>&nbsp; &nbsp; &nbsp;int 3h<br>&nbsp; &nbsp; &nbsp;// 人 为 触 发 中 断, 平 时 会 出 现保 护 错 误 蓝 屏 或 非 法 操<br>&nbsp; &nbsp; &nbsp;// 作 对 话 框, 现 在 安 装 了<br>&nbsp; &nbsp; &nbsp;// 中 断 服 务 例 程 后, 就 会 通 过<br>&nbsp; &nbsp; &nbsp;//VMM 在Ring0 调 用 中 断 服 务 例 程Ring0Proc<br>&nbsp; &nbsp; &nbsp; mov &nbsp; &nbsp;edi, ebx<br>&nbsp; &nbsp; &nbsp; mov &nbsp; &nbsp;esi, offset SavedGate<br>&nbsp; &nbsp; &nbsp; cli<br>&nbsp; &nbsp; &nbsp; movsd // 恢 复 原 来 的 中 断 门 描 述 符<br>&nbsp; &nbsp; &nbsp; movsd<br>&nbsp; &nbsp; &nbsp; sti<br>&nbsp; end;<br>asm<br>xor ecx,ecx<br>mov ebx,offset dd[10*2] &nbsp;// &lt;------这里有语法错误<br>@4:mov ax,[ebx]<br>mov byte ptr dsn[ecx],ah<br>inc ecx<br>mov byte ptr dsn[ecx],al<br>inc ebx<br>inc ebx<br>inc ecx<br>cmp ecx,10<br>jne @4<br>end;<br>&nbsp; showmessage(dsn);<br>end;<br><br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>&nbsp; &nbsp; change2ring0;<br><br>end;<br>end.<br><br><br><br>还有另外一个办法,可以在2000和nt下获得硬盘序列号,但是98下还需要把<br>SmartVSD.VxD拷到System/IOSubSys目录下,然后重起之后才行,我不想让人重起,下面<br><br>是代码:<br><br><br>function GetIdeDiskSerialNumber : String;<br>type<br>&nbsp; TSrbIoControl = packed record<br>&nbsp; &nbsp; HeaderLength : ULONG;<br>&nbsp; &nbsp; Signature &nbsp; &nbsp;: Array[0..7] of Char;<br>&nbsp; &nbsp; Timeout &nbsp; &nbsp; &nbsp;: ULONG;<br>&nbsp; &nbsp; ControlCode &nbsp;: ULONG;<br>&nbsp; &nbsp; ReturnCode &nbsp; : ULONG;<br>&nbsp; &nbsp; Length &nbsp; &nbsp; &nbsp; : ULONG;<br>&nbsp; end;<br>&nbsp; SRB_IO_CONTROL = TSrbIoControl;<br>&nbsp; PSrbIoControl = ^TSrbIoControl;<br><br>&nbsp; TIDERegs = packed record<br>&nbsp; &nbsp; bFeaturesReg &nbsp; &nbsp; : Byte; // Used for specifying SMART "commands".<br>&nbsp; &nbsp; bSectorCountReg &nbsp;: Byte; // IDE sector count register<br>&nbsp; &nbsp; bSectorNumberReg : Byte; // IDE sector number register<br>&nbsp; &nbsp; bCylLowReg &nbsp; &nbsp; &nbsp; : Byte; // IDE low order cylinder value<br>&nbsp; &nbsp; bCylHighReg &nbsp; &nbsp; &nbsp;: Byte; // IDE high order cylinder value<br>&nbsp; &nbsp; bDriveHeadReg &nbsp; &nbsp;: Byte; // IDE drive/head register<br>&nbsp; &nbsp; bCommandReg &nbsp; &nbsp; &nbsp;: Byte; // Actual IDE command.<br>&nbsp; &nbsp; bReserved &nbsp; &nbsp; &nbsp; &nbsp;: Byte; // reserved for future use. &nbsp;Must be zero.<br>&nbsp; end;<br>&nbsp; IDEREGS &nbsp; = TIDERegs;<br>&nbsp; PIDERegs &nbsp;= ^TIDERegs;<br><br>&nbsp; TSendCmdInParams = packed record<br>&nbsp; &nbsp; cBufferSize &nbsp;: DWORD; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Buffer size in bytes<br>&nbsp; &nbsp; irDriveRegs &nbsp;: TIDERegs; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Structure with drive register <br><br>values.<br>&nbsp; &nbsp; bDriveNumber : Byte; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Physical drive number to send <br><br>command to (0,1,2,3).<br>&nbsp; &nbsp; bReserved &nbsp; &nbsp;: Array[0..2] of Byte; &nbsp;// Reserved for future expansion.<br>&nbsp; &nbsp; dwReserved &nbsp; : Array[0..3] of DWORD; // For future use.<br>&nbsp; &nbsp; bBuffer &nbsp; &nbsp; &nbsp;: Array[0..0] of Byte; &nbsp;// Input buffer.<br>&nbsp; end;<br>&nbsp; SENDCMDINPARAMS &nbsp; = TSendCmdInParams;<br>&nbsp; PSendCmdInParams &nbsp;= ^TSendCmdInParams;<br><br>&nbsp; TIdSector = packed record<br>&nbsp; &nbsp; wGenConfig &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wNumCyls &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wReserved &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wNumHeads &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wBytesPerTrack &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wBytesPerSector &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wSectorsPerTrack &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wVendorUnique &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Array[0..2] of Word;<br>&nbsp; &nbsp; sSerialNumber &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Array[0..19] of Char;<br>&nbsp; &nbsp; wBufferType &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wBufferSize &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wECCSize &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; sFirmwareRev &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Array[0..7] of Char;<br>&nbsp; &nbsp; sModelNumber &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Array[0..39] of Char;<br>&nbsp; &nbsp; wMoreVendorUnique &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wDoubleWordIO &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wCapabilities &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wReserved1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wPIOTiming &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wDMATiming &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wBS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wNumCurrentCyls &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; wNumCurrentHeads &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wNumCurrentSectorsPerTrack : Word;<br>&nbsp; &nbsp; ulCurrentSectorCapacity &nbsp; &nbsp;: ULONG;<br>&nbsp; &nbsp; wMultSectorStuff &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; ulTotalAddressableSectors &nbsp;: ULONG;<br>&nbsp; &nbsp; wSingleWordDMA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Word;<br>&nbsp; &nbsp; wMultiWordDMA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Word;<br>&nbsp; &nbsp; bReserved &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Array[0..127] of Byte;<br>&nbsp; end;<br>&nbsp; PIdSector = ^TIdSector;<br><br>const<br>&nbsp; IDE_ID_FUNCTION = $EC;<br>&nbsp; IDENTIFY_BUFFER_SIZE &nbsp; &nbsp; &nbsp; = 512;<br>&nbsp; DFP_RECEIVE_DRIVE_DATA &nbsp; &nbsp; &nbsp; &nbsp;= $0007c088;<br>&nbsp; IOCTL_SCSI_MINIPORT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = $0004d008;<br>&nbsp; IOCTL_SCSI_MINIPORT_IDENTIFY &nbsp;= $001b0501;<br>&nbsp; DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;<br>&nbsp; BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize;<br>&nbsp; W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;<br>var<br>&nbsp; hDevice : THandle;<br>&nbsp; cbBytesReturned : DWORD;<br>&nbsp; pInData : PSendCmdInParams;<br>&nbsp; pOutData : Pointer; // PSendCmdInParams;<br>&nbsp; Buffer : Array[0..BufferSize-1] of Byte;<br>&nbsp; srbControl : TSrbIoControl absolute Buffer;<br><br>&nbsp; procedure ChangeByteOrder( var Data; Size : Integer );<br>&nbsp; var ptr : PChar;<br>&nbsp; &nbsp; &nbsp; i : Integer;<br>&nbsp; &nbsp; &nbsp; c : Char;<br>&nbsp; begin<br>&nbsp; &nbsp; ptr := @Data;<br>&nbsp; &nbsp; for i := 0 to (Size shr 1)-1 do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; c := ptr^;<br>&nbsp; &nbsp; &nbsp; ptr^ := (ptr+1)^;<br>&nbsp; &nbsp; &nbsp; (ptr+1)^ := c;<br>&nbsp; &nbsp; &nbsp; Inc(ptr,2);<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br><br>begin<br>&nbsp; Result := '';<br>&nbsp; FillChar(Buffer,BufferSize,#0);<br>&nbsp; if Win32Platform=VER_PLATFORM_WIN32_NT then<br>&nbsp; &nbsp; begin // Windows NT, Windows 2000<br>&nbsp; &nbsp; &nbsp; // Get SCSI port handle<br>&nbsp; &nbsp; &nbsp; hDevice := CreateFile( '//./Scsi0:', GENERIC_READ or GENERIC_WRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );<br>&nbsp; &nbsp; &nbsp; if hDevice=INVALID_HANDLE_VALUE then Exit;<br>&nbsp; &nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; &nbsp; srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);<br>&nbsp; &nbsp; &nbsp; &nbsp; System.Move('SCSIDISK',srbControl.Signature,8);<br>&nbsp; &nbsp; &nbsp; &nbsp; srbControl.Timeout &nbsp; &nbsp; &nbsp;:= 2;<br>&nbsp; &nbsp; &nbsp; &nbsp; srbControl.Length &nbsp; &nbsp; &nbsp; := DataSize;<br>&nbsp; &nbsp; &nbsp; &nbsp; srbControl.ControlCode &nbsp;:= IOCTL_SCSI_MINIPORT_IDENTIFY;<br>&nbsp; &nbsp; &nbsp; &nbsp; pInData := PSendCmdInParams(PChar(@Buffer)+SizeOf(SRB_IO_CONTROL));<br>pOutData := pInData;<br>&nbsp; &nbsp; &nbsp; &nbsp; with pInData^ do<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cBufferSize &nbsp;:= IDENTIFY_BUFFER_SIZE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bDriveNumber := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; with irDriveRegs do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bFeaturesReg &nbsp; &nbsp; := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bSectorCountReg &nbsp;:= 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bSectorNumberReg := 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bCylLowReg &nbsp; &nbsp; &nbsp; := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bCylHighReg &nbsp; &nbsp; &nbsp;:= 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bDriveHeadReg &nbsp; &nbsp;:= $A0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bCommandReg &nbsp; &nbsp; &nbsp;:= IDE_ID_FUNCTION;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT, @Buffer, <br><br>BufferSize, @Buffer, BufferSize, cbBytesReturned, nil ) then Exit;<br>&nbsp; &nbsp; &nbsp; finally<br>&nbsp; &nbsp; &nbsp; &nbsp; CloseHandle(hDevice);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end<br>&nbsp; else<br>&nbsp; &nbsp; begin // Windows 95 OSR2, Windows 98<br>&nbsp; &nbsp; &nbsp; hDevice := CreateFile( '//./SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );<br>&nbsp; &nbsp; &nbsp; if hDevice=INVALID_HANDLE_VALUE then Exit;<br>try<br>&nbsp; &nbsp; &nbsp; &nbsp;pInData := PSendCmdInParams(@Buffer);<br>pOutData := PChar(@pInData^.bBuffer);<br>&nbsp; &nbsp; &nbsp; &nbsp;with pInData^ do<br>&nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cBufferSize &nbsp;:= IDENTIFY_BUFFER_SIZE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bDriveNumber := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;with irDriveRegs do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bFeaturesReg &nbsp; &nbsp; := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bSectorCountReg &nbsp;:= 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bSectorNumberReg := 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bCylLowReg &nbsp; &nbsp; &nbsp; := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bCylHighReg &nbsp; &nbsp; &nbsp;:= 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bDriveHeadReg &nbsp; &nbsp;:= $A0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bCommandReg &nbsp; &nbsp; &nbsp;:= IDE_ID_FUNCTION;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp; &nbsp;if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA, pInData, <br><br>SizeOf(TSendCmdInParams)-1, pOutData, W9xBufferSize, cbBytesReturned, nil ) <br><br>then Exit;<br>finally<br>&nbsp; &nbsp; &nbsp; &nbsp; CloseHandle(hDevice);<br>end;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; with PIdSector(PChar(pOutData)+16)^ do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));<br>&nbsp; &nbsp; &nbsp; SetString(Result,sSerialNumber,SizeOf(sSerialNumber));<br>&nbsp; &nbsp; end;<br>end;<br><br>谁有办法在98下读硬盘序列号而不用重起的?有控件也行啊!调试通过了就给分,谢谢大<br><br>家!
 
程序1:<br>unit Unit_Main;<br><br>interface<br><br>uses<br><br>Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br><br>Dialogs, StdCtrls;<br><br>type<br><br>TSrbIoControl = packed record<br><br>HeaderLength: ULONG;<br><br>Signature: array[0..7] of Char;<br><br>Timeout: ULONG;<br><br>ControlCode: ULONG;<br><br>ReturnCode: ULONG;<br><br>Length: ULONG;<br><br>end;<br><br>SRB_IO_CONTROL = TSrbIoControl;<br><br>PSrbIoControl = ^TSrbIoControl;<br><br>TIDERegs = packed record<br><br>bFeaturesReg: Byte; // Used for specifying SMART "commands".<br><br>bSectorCountReg: Byte; // IDE sector count register<br><br>bSectorNumberReg: Byte; // IDE sector number register<br><br>bCylLowReg: Byte; // IDE low order cylinder value<br><br>bCylHighReg: Byte; // IDE high order cylinder value<br><br>bDriveHeadReg: Byte; // IDE drive/head register<br><br>bCommandReg: Byte; // Actual IDE command.<br><br>bReserved: Byte; // reserved. Must be zero.<br><br>end;<br><br>IDEREGS = TIDERegs;<br><br>PIDERegs = ^TIDERegs;<br><br>TSendCmdInParams = packed record<br><br>cBufferSize: DWORD;<br><br>irDriveRegs: TIDERegs;<br><br>bDriveNumber: Byte;<br><br>bReserved: array[0..2] of Byte;<br><br>dwReserved: array[0..3] of DWORD;<br><br>bBuffer: array[0..0] of Byte;<br><br>end;<br><br>SENDCMDINPARAMS = TSendCmdInParams;<br><br>PSendCmdInParams = ^TSendCmdInParams;<br><br>TIdSector = packed record<br><br>wGenConfig: Word;<br><br>wNumCyls: Word;<br><br>wReserved: Word;<br><br>wNumHeads: Word;<br><br>wBytesPerTrack: Word;<br><br>wBytesPerSector: Word;<br><br>wSectorsPerTrack: Word;<br><br>wVendorUnique: array[0..2] of Word;<br><br>sSerialNumber: array[0..19] of Char;<br><br>wBufferType: Word;<br><br>wBufferSize: Word;<br><br>wECCSize: Word;<br><br>sFirmwareRev: array[0..7] of Char;<br><br>sModelNumber: array[0..39] of Char;<br><br>wMoreVendorUnique: Word;<br><br>wDoubleWordIO: Word;<br><br>wCapabilities: Word;<br><br>wReserved1: Word;<br><br>wPIOTiming: Word;<br><br>wDMATiming: Word;<br><br>wBS: Word;<br><br>wNumCurrentCyls: Word;<br><br>wNumCurrentHeads: Word;<br><br>wNumCurrentSectorsPerTrack: Word;<br><br>ulCurrentSectorCapacity: ULONG;<br><br>wMultSectorStuff: Word;<br><br>ulTotalAddressableSectors: ULONG;<br><br>wSingleWordDMA: Word;<br><br>wMultiWordDMA: Word;<br><br>bReserved: array[0..127] of Byte;<br><br>end;<br><br>PIdSector = ^TIdSector;<br><br>const<br><br>IDE_ID_FUNCTION = $EC;<br><br>IDENTIFY_BUFFER_SIZE = 512;<br><br>DFP_RECEIVE_DRIVE_DATA = $0007C088;<br><br>IOCTL_SCSI_MINIPORT = $0004D008;<br><br>IOCTL_SCSI_MINIPORT_IDENTIFY = $001B0501;<br><br>DataSize = sizeof(TSendCmdInParams) - 1 + IDENTIFY_BUFFER_SIZE;<br><br>BufferSize = SizeOf(SRB_IO_CONTROL) + DataSize;<br><br>W9xBufferSize = IDENTIFY_BUFFER_SIZE + 16;<br><br>type<br><br>TForm_Main = class(TForm)<br><br>Edit_HardDiskNumber: TEdit;<br><br>Label1: TLabel;<br><br>Button_Get: TButton;<br><br>procedure Button_GetClick(Sender: TObject);<br><br>private<br><br>{ Private declarations }<br><br>public<br><br>{ Public declarations }<br><br>end;<br><br>var<br><br>Form_Main: TForm_Main;<br><br>implementation<br><br>{$R *.dfm}<br><br>function GetIdeDiskSerialNumber: string;<br><br>type<br><br>TSrbIoControl = packed record<br><br>HeaderLength: ULONG;<br><br>Signature: array[0..7] of Char;<br><br>Timeout: ULONG;<br><br>ControlCode: ULONG;<br><br>ReturnCode: ULONG;<br><br>Length: ULONG;<br><br>end;<br><br>SRB_IO_CONTROL = TSrbIoControl;<br><br>PSrbIoControl = ^TSrbIoControl;<br><br>TIDERegs = packed record<br><br>bFeaturesReg: Byte; // Used for specifying SMART "commands".<br><br>bSectorCountReg: Byte; // IDE sector count register<br><br>bSectorNumberReg: Byte; // IDE sector number register<br><br>bCylLowReg: Byte; // IDE low order cylinder value<br><br>bCylHighReg: Byte; // IDE high order cylinder value<br><br>bDriveHeadReg: Byte; // IDE drive/head register<br><br>bCommandReg: Byte; // Actual IDE command.<br><br>bReserved: Byte; // reserved for future use. Must be zero.<br><br>end;<br><br>IDEREGS = TIDERegs;<br><br>PIDERegs = ^TIDERegs;<br><br>TSendCmdInParams = packed record<br><br>cBufferSize: DWORD; // Buffer size in bytes<br><br>irDriveRegs: TIDERegs; // Structure with drive register values.<br><br>bDriveNumber: Byte; // Physical drive number to send command to (0,1,2,3).<br><br>bReserved: array[0..2] of Byte; // Reserved for future expansion.<br><br>dwReserved: array[0..3] of DWORD; // For future use.<br><br>bBuffer: array[0..0] of Byte; // Input buffer.<br><br>end;<br><br>SENDCMDINPARAMS = TSendCmdInParams;<br><br>PSendCmdInParams = ^TSendCmdInParams;<br><br>TIdSector = packed record<br><br>wGenConfig: Word;<br><br>wNumCyls: Word;<br><br>wReserved: Word;<br><br>wNumHeads: Word;<br><br>wBytesPerTrack: Word;<br><br>wBytesPerSector: Word;<br><br>wSectorsPerTrack: Word;<br><br>wVendorUnique: array[0..2] of Word;<br><br>sSerialNumber: array[0..19] of Char;<br><br>wBufferType: Word;<br><br>wBufferSize: Word;<br><br>wECCSize: Word;<br><br>sFirmwareRev: array[0..7] of Char;<br><br>sModelNumber: array[0..39] of Char;<br><br>wMoreVendorUnique: Word;<br><br>wDoubleWordIO: Word;<br><br>wCapabilities: Word;<br><br>wReserved1: Word;<br><br>wPIOTiming: Word;<br><br>wDMATiming: Word;<br><br>wBS: Word;<br><br>wNumCurrentCyls: Word;<br><br>wNumCurrentHeads: Word;<br><br>wNumCurrentSectorsPerTrack: Word;<br><br>ulCurrentSectorCapacity: ULONG;<br><br>wMultSectorStuff: Word;<br><br>ulTotalAddressableSectors: ULONG;<br><br>wSingleWordDMA: Word;<br><br>wMultiWordDMA: Word;<br><br>bReserved: array[0..127] of Byte;<br><br>end;<br><br>PIdSector = ^TIdSector;<br><br>const<br><br>IDE_ID_FUNCTION = $EC;<br><br>IDENTIFY_BUFFER_SIZE = 512;<br><br>DFP_RECEIVE_DRIVE_DATA = $0007C088;<br><br>IOCTL_SCSI_MINIPORT = $0004D008;<br><br>IOCTL_SCSI_MINIPORT_IDENTIFY = $001B0501;<br><br>DataSize = sizeof(TSendCmdInParams) - 1 + IDENTIFY_BUFFER_SIZE;<br><br>BufferSize = SizeOf(SRB_IO_CONTROL) + DataSize;<br><br>W9xBufferSize = IDENTIFY_BUFFER_SIZE + 16;<br><br>var<br><br>hDevice: THandle;<br><br>cbBytesReturned: DWORD;<br><br>pInData: PSendCmdInParams;<br><br>pOutData: Pointer; // PSendCmdInParams;<br><br>Buffer: array[0..BufferSize - 1] of Byte;<br><br>srbControl: TSrbIoControl absolute Buffer;<br><br>procedure ChangeByteOrder(var Data; Size: Integer);<br><br>var ptr: PChar;<br><br>i: Integer;<br><br>c: Char;<br><br>begin<br><br>ptr := @Data;<br><br>for i := 0 to (Size shr 1) - 1 do<br><br>begin<br><br>c := ptr^;<br><br>ptr^ := (ptr + 1)^;<br><br>(ptr + 1)^ := c;<br><br>Inc(ptr, 2);<br><br>end;<br><br>end;<br><br>begin<br><br>Result := '';<br><br>FillChar(Buffer, BufferSize, #0);<br><br>if Win32Platform = VER_PLATFORM_WIN32_NT then<br><br>begin // Windows NT, Windows 2000<br><br>// Get SCSI port handle<br><br>hDevice := CreateFile('/.:', GENERIC_READ or GENERIC_WRITE,<br><br>FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);<br><br>if hDevice = INVALID_HANDLE_VALUE then Exit;<br><br>try<br><br>srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);<br><br>System.Move('SCSIDISK', srbControl.Signature, 8);<br><br>srbControl.Timeout := 2;<br><br>srbControl.Length := DataSize;<br><br>srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;<br><br>pInData := PSendCmdInParams(PChar(@Buffer) + SizeOf(SRB_IO_CONTROL));<br><br>pOutData := pInData;<br><br>with pInData^ do<br><br>begin<br><br>cBufferSize := IDENTIFY_BUFFER_SIZE;<br><br>bDriveNumber := 0;<br><br>with irDriveRegs do<br><br>begin<br><br>bFeaturesReg := 0;<br><br>bSectorCountReg := 1;<br><br>bSectorNumberReg := 1;<br><br>bCylLowReg := 0;<br><br>bCylHighReg := 0;<br><br>bDriveHeadReg := $A0;<br><br>bCommandReg := IDE_ID_FUNCTION;<br><br>end;<br><br>end;<br><br>if not DeviceIoControl(hDevice, IOCTL_SCSI_MINIPORT, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil) then Exit;<br>finally<br><br>CloseHandle(hDevice);<br><br>end;<br><br>end<br><br>else<br><br>begin // Windows 95 OSR2, Windows 98<br><br>hDevice := CreateFile('/.', 0, 0, nil, CREATE_NEW, 0, 0);<br><br>if hDevice = INVALID_HANDLE_VALUE then Exit;<br><br>try<br><br>pInData := PSendCmdInParams(@Buffer);<br><br>pOutData := PChar(@pInData^.bBuffer);<br><br>with pInData^ do<br><br>begin<br><br>cBufferSize := IDENTIFY_BUFFER_SIZE;<br><br>bDriveNumber := 0;<br><br>with irDriveRegs do<br><br>begin<br><br>bFeaturesReg := 0;<br><br>bSectorCountReg := 1;<br><br>bSectorNumberReg := 1;<br><br>bCylLowReg := 0;<br><br>bCylHighReg := 0;<br><br>bDriveHeadReg := $A0;<br><br>bCommandReg := IDE_ID_FUNCTION;<br><br>end;<br><br>end;<br><br>if not DeviceIoControl(hDevice, DFP_RECEIVE_DRIVE_DATA, pInData, SizeOf(TSendCmdInParams) - 1, <br>pOutData, W9xBufferSize, cbBytesReturned, nil) then Exit;<br><br>finally<br><br>CloseHandle(hDevice);<br><br>end;<br><br>end;<br><br>with PIdSector(PChar(pOutData) + 16)^ do<br><br>begin<br><br>ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));<br><br>SetString(Result, sSerialNumber, SizeOf(sSerialNumber));<br><br>end;<br><br>end;<br><br>procedure TForm_Main.Button_GetClick(Sender: TObject);<br><br>begin<br><br>Edit_HardDiskNumber.Text := GetIdeDiskSerialNumber;<br><br>end;<br><br>end.<br><br>程序2:<br>获取主板的工业序列号完全可以实现,注意是硬盘外壳上的序列号,不是格式化后的序列 <br>号,C语言源程序如下(注:该程序由顶尖高手丁凯所写):<br><br>#include &lt;windows.h&gt;<br><br>#include &lt;stdio.h&gt;<br><br>WORD pw[256];<br><br>static DWORD idt, int_idt;<br><br>static DWORD Base;<br><br>static WORD Entry;<br><br>#pragma warning (disable:4035)<br><br>static int inp(WORD rdx)<br><br>{<br><br>_asm xor eax, eax<br><br>_asm mov dx, rdx<br><br>_asm in al, dx<br><br>}<br><br>static WORD inpw(WORD rdx)<br><br>{<br><br>_asm xor eax, eax<br><br>_asm mov dx, rdx<br><br>_asm in ax, dx<br><br>}<br><br>static void outp(WORD rdx, int ral)<br><br>{<br><br>_asm mov dx, rdx<br><br>_asm mov eax, ral<br><br>_asm out dx, al<br><br>}<br><br>static int WaitIde()<br><br>{<br><br>int al;<br><br>while ((al=inp(0x1F7))&gt;=0x80) ;<br><br>return al;<br><br>}<br><br>static void ReadIDE()<br><br>{<br><br>int al;<br><br>int i;<br><br>WaitIde();<br><br>outp(0x1F6,0xA0);<br><br>al = WaitIde();<br><br>if ((al&amp;0x50)!=0x50) return;<br><br>outp(0x1F6,0xA0);<br><br>outp(0x1F7,0xEC);<br><br>al = WaitIde();<br><br>if ((al&amp;0x58)!=0x58) return;<br><br>for (i=0;i&lt;256;i++) {<br><br>pw = inpw(0x1F0);<br><br>}<br><br>}<br><br>static void __declspec( naked ) NowInRing0()<br><br>{<br><br>_asm {<br><br>push ebp<br><br>mov ebp,esp<br><br>call ReadIDE<br><br>cli<br><br>mov ebx, int_idt<br><br>mov ax, Entry<br><br>mov word ptr [ebx-4], ax<br><br>mov eax, Base<br><br>shr eax, 16<br><br>mov [ebx+2], ax<br><br>sti<br><br>leave<br><br>iretd<br><br>}<br><br>}<br><br>void GetIDEInfo()<br><br>{<br><br>DWORD dwExcept;<br><br>dwExcept = (DWORD)NowInRing0;<br><br>_asm {<br><br>mov eax, fs:[0]<br><br>push eax<br><br>sidt [esp-02h]<br><br>pop ebx<br><br>mov idt, ebx<br><br>add ebx, 0x1C<br><br>mov int_idt, ebx<br><br>mov eax, [ebx]<br><br>mov [Base], eax<br><br>mov ax, [ebx-4]<br><br>mov [Entry], ax<br><br>cli<br><br>mov esi, dwExcept<br><br>push esi<br><br>mov [ebx-4], si<br><br>shr esi, 16<br><br>mov [ebx+2], si<br><br>pop esi<br><br>sti<br><br>int 3<br><br>}<br><br>}<br><br>main()<br><br>{<br><br>char s[80];<br><br>register i,j;<br><br>GetIDEInfo();<br><br>for (i=0,j=0;i&lt;10;i++) {<br><br>s[j++]=pw[10+i]&gt;&gt;8;<br><br>s[j++]=pw[10+i]&amp;0xFF;<br><br>}<br><br>s[j] = 0;<br><br>printf("Serial=%s", s);<br><br>return 0;<br><br>}<br><br> <br>
 
使用S.M.A.R.T. Ioctl API获取IDE硬盘序列号 <br>(http://www.tommstudio.com)<br><br>--------------------------------------------------------------------------------<br><br>通过它你可以获取型号名称, firmware revision,序列号以及其它有关IDE硬盘的信息.<br><br> <br><br>回答:<br><br>相关构件:<br><br>IdeInfo.zip<br><br>许多FAQ中推荐使用GetVolumeInformation来获取硬盘序列号。但是那获取的是卷的序列号,而不是硬盘的序列号。卷 的序列号是在分区格式化时生成或修改。一些公司使用复制工具来为全部新计算机安装软件----通过将一个硬盘复制到 其它硬盘,当然,所有这些计算机上卷的信息(包括序列号)都是相同的。<br><br>我建议另外的一个方法:获取真正硬盘的序列号。<br><br>不幸的是,下列代码只能工作在IDE硬盘上。<br><br> <br><br>//获取第一个IDE硬盘的序列号<br><br>function GetIdeSerialNumber : SerialNumber;<br><br>const IDENTIFY_BUFFER_SIZE = 512;<br><br>type<br><br>TIDERegs = packed record<br><br>bFeaturesReg : BYTE; // Used for specifying SMART "commands".<br><br>bSectorCountReg : BYTE; // IDE sector count register<br><br>bSectorNumberReg : BYTE; // IDE sector number register<br><br>bCylLowReg : BYTE; // IDE low order cylinder value<br><br>bCylHighReg : BYTE; // IDE high order cylinder value<br><br>bDriveHeadReg : BYTE; // IDE drive/head register<br><br>bCommandReg : BYTE; // Actual IDE command.<br><br>bReserved : BYTE; // reserved for future use. Must be zero.<br><br>end;<br><br>TSendCmdInParams = packed record<br><br>// Buffer size in bytes<br><br>cBufferSize : DWORD;<br><br>// Structure with drive register values.<br><br>irDriveRegs : TIDERegs;<br><br>// Physical drive number to send command to (0,1,2,3).<br><br>bDriveNumber : BYTE;<br><br>bReserved : Array[0..2] of Byte;<br><br>dwReserved : Array[0..3] of DWORD;<br><br>bBuffer : Array[0..0] of Byte; // Input buffer.<br><br>end;<br><br>TIdSector = packed record<br><br>wGenConfig : Word;<br><br>wNumCyls : Word;<br><br>wReserved : Word;<br><br>wNumHeads : Word;<br><br>wBytesPerTrack : Word;<br><br>wBytesPerSector : Word;<br><br>wSectorsPerTrack : Word;<br><br>wVendorUnique : Array[0..2] of Word;<br><br>sSerialNumber : Array[0..19] of CHAR;<br><br>wBufferType : Word;<br><br>wBufferSize : Word;<br><br>wECCSize : Word;<br><br>sFirmwareRev : Array[0..7] of Char;<br><br>sModelNumber : Array[0..39] of Char;<br><br>wMoreVendorUnique : Word;<br><br>wDoubleWordIO : Word;<br><br>wCapabilities : Word;<br><br>wReserved1 : Word;<br><br>wPIOTiming : Word;<br><br>wDMATiming : Word;<br><br>wBS : Word;<br><br>wNumCurrentCyls : Word;<br><br>wNumCurrentHeads : Word;<br><br>wNumCurrentSectorsPerTrack : Word;<br><br>ulCurrentSectorCapacity : DWORD;<br><br>wMultSectorStuff : Word;<br><br>ulTotalAddressableSectors : DWORD;<br><br>wSingleWordDMA : Word;<br><br>wMultiWordDMA : Word;<br><br>bReserved : Array[0..127] of BYTE;<br><br>end;<br><br>PIdSector = ^TIdSector;<br><br>TDriverStatus = packed record<br><br>// 驱动器返回的错误代码,无错则返回0<br><br>bDriverError : Byte;<br><br>// IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效<br><br>bIDEStatus : Byte;<br><br>bReserved : Array[0..1] of Byte;<br><br>dwReserved : Array[0..1] of DWORD;<br><br>end;<br><br>TSendCmdOutParams = packed record<br><br>// bBuffer的大小<br><br>cBufferSize : DWORD;<br><br>// 驱动器状态<br><br>DriverStatus : TDriverStatus;<br><br>// 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定<br><br>bBuffer : Array[0..0] of BYTE;<br><br>end;<br><br>var hDevice : THandle;<br><br>cbBytesReturned : DWORD;<br><br>ptr : PChar;<br><br>SCIP : TSendCmdInParams;<br><br>aIdOutCmd : Array [0..(SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1)-1] of Byte;<br><br>IdOutCmd : TSendCmdOutParams absolute aIdOutCmd;<br><br>procedure ChangeByteOrder( var Data; Size : Integer );<br><br>var ptr : PChar;<br><br>i : Integer;<br><br>c : Char;<br><br>begin<br><br>ptr := @Data;<br><br>for i := 0 to (Size shr 1)-1 do<br><br>begin<br><br>c := ptr^;<br><br>ptr^ := (ptr+1)^;<br><br>(ptr+1)^ := c;<br><br>Inc(ptr,2);<br><br>end;<br><br>end;<br><br>begin<br><br>Result := ''; // 如果出错则返回空串<br><br>if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000<br><br>begin<br><br>// 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '/.<br><br>hDevice := CreateFile( '/.', GENERIC_READ or GENERIC_WRITE,<br><br>FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );<br><br>end<br><br>else // Version Windows 95 OSR2, Windows 98<br><br>hDevice := CreateFile( '/.', 0, 0, nil, CREATE_NEW, 0, 0 );<br><br>if hDevice=INVALID_HANDLE_VALUE then Exit;<br><br>try<br><br>FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0);<br><br>FillChar(aIdOutCmd,SizeOf(aIdOutCmd),#0);<br><br>cbBytesReturned := 0;<br><br>// Set up data structures for IDENTIFY command.<br><br>with SCIP do<br><br>begin<br><br>cBufferSize := IDENTIFY_BUFFER_SIZE;<br><br>// bDriveNumber := 0;<br><br>with irDriveRegs do<br><br>begin<br><br>bSectorCountReg := 1;<br><br>bSectorNumberReg := 1;<br><br>// if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0<br><br>// else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);<br><br>bDriveHeadReg := $A0;<br><br>bCommandReg := $EC;<br><br>end;<br><br>end;<br><br>if not DeviceIoControl( hDevice, $0007c088, @SCIP, SizeOf(TSendCmdInParams)-1,<br><br>@aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil ) then Exit;<br><br>finally<br><br>CloseHandle(hDevice);<br><br>end;<br><br>with PIdSector(@IdOutCmd.bBuffer)^ do<br><br>begin<br><br>ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) );<br><br>(PChar(@sSerialNumber)+SizeOf(sSerialNumber))^ := #0;<br><br>Result := PChar(@sSerialNumber);<br><br>end;<br><br>end;<br><br>// 更多关于 S.M.A.R.T. ioctl 的信息可查看:<br><br>// http://www.microsoft.com/hwdev/download/respec/iocltapi.rtf<br><br>// MSDN库中也有一些简单的例子<br><br>// Windows Development -&gt; Win32 Device Driver Kit -&gt;<br><br>// SAMPLE: SmartApp.exe Accesses SMART stats in IDE drives<br><br>// 还可以查看 http://www.mtgroup.ru/~alexk<br><br>// IdeInfo.zip - 一个简单的使用了S.M.A.R.T. Ioctl API的Delphi应用程序<br><br>// 注意:<br><br>// WinNT/Win2000 - 你必须拥有对硬盘的读/写访问权限<br><br>// Win98<br><br>// SMARTVSD.VXD 必须安装到<br><br>// (不要忘记在复制后重新启动系统)<br>
 
http://www.delphibbs.com/delphibbs/dispq.asp?LID=339210
 
以下是全套源码:<br>http://lsqcom.xiloo.com/DISK.rar
 
c语言我看不懂,拜托给个delphi的,2楼,控件在哪?
 
我也没调试过,但是“玩命”的源码是可以用的,你看看
 
to 玩命:<br>我晕~~程序还没打开就弹出无数的错误<br>难道我系统有问题??
 
拜托大家看看我的问题先,我需要的是98下不需要重起的!
 
好像只能取得某个分区的序列号吧
 
unit Unit_Main;<br><br>interface<br><br>uses<br><br>Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br><br>Dialogs, StdCtrls;<br><br>type<br><br>TSrbIoControl = packed record<br><br>HeaderLength: ULONG;<br><br>Signature: array[0..7] of Char;<br><br>Timeout: ULONG;<br><br>ControlCode: ULONG;<br><br>ReturnCode: ULONG;<br><br>Length: ULONG;<br><br>end;<br><br>SRB_IO_CONTROL = TSrbIoControl;<br><br>PSrbIoControl = ^TSrbIoControl;<br><br>TIDERegs = packed record<br><br>bFeaturesReg: Byte; // Used for specifying SMART "commands".<br><br>bSectorCountReg: Byte; // IDE sector count register<br><br>bSectorNumberReg: Byte; // IDE sector number register<br><br>bCylLowReg: Byte; // IDE low order cylinder value<br><br>bCylHighReg: Byte; // IDE high order cylinder value<br><br>bDriveHeadReg: Byte; // IDE drive/head register<br><br>bCommandReg: Byte; // Actual IDE command.<br><br>bReserved: Byte; // reserved. Must be zero.<br><br>end;<br><br>IDEREGS = TIDERegs;<br><br>PIDERegs = ^TIDERegs;<br><br>TSendCmdInParams = packed record<br><br>cBufferSize: DWORD;<br><br>irDriveRegs: TIDERegs;<br><br>bDriveNumber: Byte;<br><br>bReserved: array[0..2] of Byte;<br><br>dwReserved: array[0..3] of DWORD;<br><br>bBuffer: array[0..0] of Byte;<br><br>end;<br><br>SENDCMDINPARAMS = TSendCmdInParams;<br><br>PSendCmdInParams = ^TSendCmdInParams;<br><br>TIdSector = packed record<br><br>wGenConfig: Word;<br><br>wNumCyls: Word;<br><br>wReserved: Word;<br><br>wNumHeads: Word;<br><br>wBytesPerTrack: Word;<br><br>wBytesPerSector: Word;<br><br>wSectorsPerTrack: Word;<br><br>wVendorUnique: array[0..2] of Word;<br><br>sSerialNumber: array[0..19] of Char;<br><br>wBufferType: Word;<br><br>wBufferSize: Word;<br><br>wECCSize: Word;<br><br>sFirmwareRev: array[0..7] of Char;<br><br>sModelNumber: array[0..39] of Char;<br><br>wMoreVendorUnique: Word;<br><br>wDoubleWordIO: Word;<br><br>wCapabilities: Word;<br><br>wReserved1: Word;<br><br>wPIOTiming: Word;<br><br>wDMATiming: Word;<br><br>wBS: Word;<br><br>wNumCurrentCyls: Word;<br><br>wNumCurrentHeads: Word;<br><br>wNumCurrentSectorsPerTrack: Word;<br><br>ulCurrentSectorCapacity: ULONG;<br><br>wMultSectorStuff: Word;<br><br>ulTotalAddressableSectors: ULONG;<br><br>wSingleWordDMA: Word;<br><br>wMultiWordDMA: Word;<br><br>bReserved: array[0..127] of Byte;<br><br>end;<br><br>PIdSector = ^TIdSector;<br><br>const<br><br>IDE_ID_FUNCTION = $EC;<br><br>IDENTIFY_BUFFER_SIZE = 512;<br><br>DFP_RECEIVE_DRIVE_DATA = $0007C088;<br><br>IOCTL_SCSI_MINIPORT = $0004D008;<br><br>IOCTL_SCSI_MINIPORT_IDENTIFY = $001B0501;<br><br>DataSize = sizeof(TSendCmdInParams) - 1 + IDENTIFY_BUFFER_SIZE;<br><br>BufferSize = SizeOf(SRB_IO_CONTROL) + DataSize;<br><br>W9xBufferSize = IDENTIFY_BUFFER_SIZE + 16;<br><br>type<br><br>TForm_Main = class(TForm)<br><br>Edit_HardDiskNumber: TEdit;<br><br>Label1: TLabel;<br><br>Button_Get: TButton;<br><br>procedure Button_GetClick(Sender: TObject);<br><br>private<br><br>{ Private declarations }<br><br>public<br><br>{ Public declarations }<br><br>end;<br><br>var<br><br>Form_Main: TForm_Main;<br><br>implementation<br><br>{$R *.dfm}<br><br>function GetIdeDiskSerialNumber: string;<br><br>type<br><br>TSrbIoControl = packed record<br><br>HeaderLength: ULONG;<br><br>Signature: array[0..7] of Char;<br><br>Timeout: ULONG;<br><br>ControlCode: ULONG;<br><br>ReturnCode: ULONG;<br><br>Length: ULONG;<br><br>end;<br><br>SRB_IO_CONTROL = TSrbIoControl;<br><br>PSrbIoControl = ^TSrbIoControl;<br><br>TIDERegs = packed record<br><br>bFeaturesReg: Byte; // Used for specifying SMART "commands".<br><br>bSectorCountReg: Byte; // IDE sector count register<br><br>bSectorNumberReg: Byte; // IDE sector number register<br><br>bCylLowReg: Byte; // IDE low order cylinder value<br><br>bCylHighReg: Byte; // IDE high order cylinder value<br><br>bDriveHeadReg: Byte; // IDE drive/head register<br><br>bCommandReg: Byte; // Actual IDE command.<br><br>bReserved: Byte; // reserved for future use. Must be zero.<br><br>end;<br><br>IDEREGS = TIDERegs;<br><br>PIDERegs = ^TIDERegs;<br><br>TSendCmdInParams = packed record<br><br>cBufferSize: DWORD; // Buffer size in bytes<br><br>irDriveRegs: TIDERegs; // Structure with drive register values.<br><br>bDriveNumber: Byte; // Physical drive number to send command to (0,1,2,3).<br><br>bReserved: array[0..2] of Byte; // Reserved for future expansion.<br><br>dwReserved: array[0..3] of DWORD; // For future use.<br><br>bBuffer: array[0..0] of Byte; // Input buffer.<br><br>end;<br><br>SENDCMDINPARAMS = TSendCmdInParams;<br><br>PSendCmdInParams = ^TSendCmdInParams;<br><br>TIdSector = packed record<br><br>wGenConfig: Word;<br><br>wNumCyls: Word;<br><br>wReserved: Word;<br><br>wNumHeads: Word;<br><br>wBytesPerTrack: Word;<br><br>wBytesPerSector: Word;<br><br>wSectorsPerTrack: Word;<br><br>wVendorUnique: array[0..2] of Word;<br><br>sSerialNumber: array[0..19] of Char;<br><br>wBufferType: Word;<br><br>wBufferSize: Word;<br><br>wECCSize: Word;<br><br>sFirmwareRev: array[0..7] of Char;<br><br>sModelNumber: array[0..39] of Char;<br><br>wMoreVendorUnique: Word;<br><br>wDoubleWordIO: Word;<br><br>wCapabilities: Word;<br><br>wReserved1: Word;<br><br>wPIOTiming: Word;<br><br>wDMATiming: Word;<br><br>wBS: Word;<br><br>wNumCurrentCyls: Word;<br><br>wNumCurrentHeads: Word;<br><br>wNumCurrentSectorsPerTrack: Word;<br><br>ulCurrentSectorCapacity: ULONG;<br><br>wMultSectorStuff: Word;<br><br>ulTotalAddressableSectors: ULONG;<br><br>wSingleWordDMA: Word;<br><br>wMultiWordDMA: Word;<br><br>bReserved: array[0..127] of Byte;<br><br>end;<br><br>PIdSector = ^TIdSector;<br><br>const<br><br>IDE_ID_FUNCTION = $EC;<br><br>IDENTIFY_BUFFER_SIZE = 512;<br><br>DFP_RECEIVE_DRIVE_DATA = $0007C088;<br><br>IOCTL_SCSI_MINIPORT = $0004D008;<br><br>IOCTL_SCSI_MINIPORT_IDENTIFY = $001B0501;<br><br>DataSize = sizeof(TSendCmdInParams) - 1 + IDENTIFY_BUFFER_SIZE;<br><br>BufferSize = SizeOf(SRB_IO_CONTROL) + DataSize;<br><br>W9xBufferSize = IDENTIFY_BUFFER_SIZE + 16;<br><br>var<br><br>hDevice: THandle;<br><br>cbBytesReturned: DWORD;<br><br>pInData: PSendCmdInParams;<br><br>pOutData: Pointer; // PSendCmdInParams;<br><br>Buffer: array[0..BufferSize - 1] of Byte;<br><br>srbControl: TSrbIoControl absolute Buffer;<br><br>procedure ChangeByteOrder(var Data; Size: Integer);<br><br>var ptr: PChar;<br><br>i: Integer;<br><br>c: Char;<br><br>begin<br><br>ptr := @Data;<br><br>for i := 0 to (Size shr 1) - 1 do<br><br>begin<br><br>c := ptr^;<br><br>ptr^ := (ptr + 1)^;<br><br>(ptr + 1)^ := c;<br><br>Inc(ptr, 2);<br><br>end;<br><br>end;<br><br>begin<br><br>Result := '';<br><br>FillChar(Buffer, BufferSize, #0);<br><br>if Win32Platform = VER_PLATFORM_WIN32_NT then<br><br>begin // Windows NT, Windows 2000<br><br>// Get SCSI port handle<br><br>hDevice := CreateFile('/.:', GENERIC_READ or GENERIC_WRITE,<br><br>FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);<br><br>if hDevice = INVALID_HANDLE_VALUE then Exit;<br><br>try<br><br>srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);<br><br>System.Move('SCSIDISK', srbControl.Signature, 8);<br><br>srbControl.Timeout := 2;<br><br>srbControl.Length := DataSize;<br><br>srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;<br><br>pInData := PSendCmdInParams(PChar(@Buffer) + SizeOf(SRB_IO_CONTROL));<br><br>pOutData := pInData;<br><br>with pInData^ do<br><br>begin<br><br>cBufferSize := IDENTIFY_BUFFER_SIZE;<br><br>bDriveNumber := 0;<br><br>with irDriveRegs do<br><br>begin<br><br>bFeaturesReg := 0;<br><br>bSectorCountReg := 1;<br><br>bSectorNumberReg := 1;<br><br>bCylLowReg := 0;<br><br>bCylHighReg := 0;<br><br>bDriveHeadReg := $A0;<br><br>bCommandReg := IDE_ID_FUNCTION;<br><br>end;<br><br>end;<br><br>if not DeviceIoControl(hDevice, IOCTL_SCSI_MINIPORT, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil) then Exit;<br><br>finally<br><br>CloseHandle(hDevice);<br><br>end;<br><br>end<br><br>else<br><br>begin // Windows 95 OSR2, Windows 98<br><br>hDevice := CreateFile('/.', 0, 0, nil, CREATE_NEW, 0, 0);<br><br>if hDevice = INVALID_HANDLE_VALUE then Exit;<br><br>try<br><br>pInData := PSendCmdInParams(@Buffer);<br><br>pOutData := PChar(@pInData^.bBuffer);<br><br>with pInData^ do<br><br>begin<br><br>cBufferSize := IDENTIFY_BUFFER_SIZE;<br><br>bDriveNumber := 0;<br><br>with irDriveRegs do<br><br>begin<br><br>bFeaturesReg := 0;<br><br>bSectorCountReg := 1;<br><br>bSectorNumberReg := 1;<br><br>bCylLowReg := 0;<br><br>bCylHighReg := 0;<br><br>bDriveHeadReg := $A0;<br><br>bCommandReg := IDE_ID_FUNCTION;<br><br>end;<br><br>end;<br><br>if not DeviceIoControl(hDevice, DFP_RECEIVE_DRIVE_DATA, pInData, SizeOf(TSendCmdInParams) - 1, pOutData, W9xBufferSize, cbBytesReturned, nil) then Exit;<br><br>finally<br><br>CloseHandle(hDevice);<br><br>end;<br><br>end;<br><br>with PIdSector(PChar(pOutData) + 16)^ do<br><br>begin<br><br>ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));<br><br>SetString(Result, sSerialNumber, SizeOf(sSerialNumber));<br><br>end;<br><br>end;<br><br>procedure TForm_Main.Button_GetClick(Sender: TObject);<br><br>begin<br><br>Edit_HardDiskNumber.Text := GetIdeDiskSerialNumber;<br><br>end;<br><br>end.<br><br> <br>
 
function TPanelX.GetSerial: string;<br>const IDENTIFY_BUFFER_SIZE = 512;<br>type<br>&nbsp; &nbsp;TIDERegs = packed record<br>&nbsp; &nbsp; &nbsp;bFeaturesReg: BYTE; // Used for specifying SMART "commands".<br>&nbsp; &nbsp; &nbsp;bSectorCountReg: BYTE; // IDE sector count register<br>&nbsp; &nbsp; &nbsp;bSectorNumberReg: BYTE; // IDE sector number register<br>&nbsp; &nbsp; &nbsp;bCylLowReg: BYTE; // IDE low order cylinder value<br>&nbsp; &nbsp; &nbsp;bCylHighReg: BYTE; // IDE high order cylinder value<br>&nbsp; &nbsp; &nbsp;bDriveHeadReg: BYTE; // IDE drive/head register<br>&nbsp; &nbsp; &nbsp;bCommandReg: BYTE; // Actual IDE command.<br>&nbsp; &nbsp; &nbsp;bReserved: BYTE; // reserved for future use. Must be zero.<br>&nbsp; end;<br>&nbsp; TSendCmdInParams = packed record<br>&nbsp; &nbsp; // Buffer size in bytes<br>&nbsp; &nbsp; cBufferSize: DWORD;<br>&nbsp; &nbsp; // Structure with drive register values.<br>&nbsp; &nbsp; irDriveRegs: TIDERegs;<br>&nbsp; &nbsp; // Physical drive number to send command to (0,1,2,3).<br>&nbsp; &nbsp; bDriveNumber: BYTE;<br>&nbsp; &nbsp; bReserved: array[0..2] of Byte;<br>&nbsp; &nbsp; dwReserved: array[0..3] of DWORD;<br>&nbsp; &nbsp; bBuffer: array[0..0] of Byte; // Input buffer.<br>&nbsp; end;<br>&nbsp; TIdSector = packed record<br>&nbsp; &nbsp; wGenConfig: Word;<br>&nbsp; &nbsp; wNumCyls: Word;<br>&nbsp; &nbsp; wReserved: Word;<br>&nbsp; &nbsp; wNumHeads: Word;<br>&nbsp; &nbsp; wBytesPerTrack: Word;<br>&nbsp; &nbsp; wBytesPerSector: Word;<br>&nbsp; &nbsp; wSectorsPerTrack: Word;<br>&nbsp; &nbsp; wVendorUnique: array[0..2] of Word;<br>&nbsp; &nbsp; sSerialNumber: array[0..19] of CHAR;<br>&nbsp; &nbsp; wBufferType: Word;<br>&nbsp; &nbsp; wBufferSize: Word;<br>&nbsp; &nbsp; wECCSize: Word;<br>&nbsp; &nbsp; sFirmwareRev: array[0..7] of Char;<br>&nbsp; &nbsp; sModelNumber: array[0..39] of Char;<br>&nbsp; &nbsp; wMoreVendorUnique: Word;<br>&nbsp; &nbsp; wDoubleWordIO: Word;<br>&nbsp; &nbsp; wCapabilities: Word;<br>&nbsp; &nbsp; wReserved1: Word;<br>&nbsp; &nbsp; wPIOTiming: Word;<br>&nbsp; &nbsp; wDMATiming: Word;<br>&nbsp; &nbsp; wBS: Word;<br>&nbsp; &nbsp; wNumCurrentCyls: Word;<br>&nbsp; &nbsp; wNumCurrentHeads: Word;<br>&nbsp; &nbsp; wNumCurrentSectorsPerTrack: Word;<br>&nbsp; &nbsp; ulCurrentSectorCapacity: DWORD;<br>&nbsp; &nbsp; wMultSectorStuff: Word;<br>&nbsp; &nbsp; ulTotalAddressableSectors: DWORD;<br>&nbsp; &nbsp; wSingleWordDMA: Word;<br>&nbsp; &nbsp; wMultiWordDMA: Word;<br>&nbsp; &nbsp; bReserved: array[0..127] of BYTE;<br>&nbsp; end;<br>&nbsp; PIdSector = ^TIdSector;<br>&nbsp; TDriverStatus = packed record<br>&nbsp; &nbsp; // 驱动器返回的错误代码,无错则返回0<br>&nbsp; &nbsp; bDriverError: Byte;<br>&nbsp; &nbsp; // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效<br>&nbsp; &nbsp; bIDEStatus: Byte;<br>&nbsp; &nbsp; bReserved: array[0..1] of Byte;<br>&nbsp; &nbsp; dwReserved: array[0..1] of DWORD;<br>&nbsp; end;<br>&nbsp; TSendCmdOutParams = packed record<br>&nbsp; &nbsp; // bBuffer的大小<br>&nbsp; &nbsp; cBufferSize: DWORD;<br>&nbsp; &nbsp; // 驱动器状态<br>&nbsp; &nbsp; DriverStatus: TDriverStatus;<br>&nbsp; &nbsp; // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定<br>&nbsp; &nbsp; bBuffer: array[0..0] of BYTE;<br>&nbsp; end;<br>var<br>&nbsp; hDevice: Thandle;<br>&nbsp; cbBytesReturned: DWORD;<br>&nbsp; SCIP: TSendCmdInParams;<br>&nbsp; aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1) - 1] of Byte;<br>&nbsp; IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;<br>procedure ChangeByteOrder(var Data; Size: Integer);<br>var<br>&nbsp; ptr: Pchar;<br>&nbsp; i: Integer;<br>&nbsp; c: Char;<br>begin<br>&nbsp; ptr := @Data;<br>&nbsp; for I := 0 to (Size shr 1) - 1 do begin<br>&nbsp; &nbsp; c := ptr^;<br>&nbsp; &nbsp; ptr^ := (ptr + 1)^;<br>&nbsp; &nbsp; (ptr + 1)^ := c;<br>&nbsp; &nbsp; Inc(ptr, 2);<br>&nbsp; end;<br>end;<br>begin<br>Result := ''; // 如果出错则返回空串<br>if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000<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 else // Version 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>FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);<br>FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);<br>cbBytesReturned := 0;<br>// Set up data structures for IDENTIFY command.<br>with SCIP do begin<br>cBufferSize := IDENTIFY_BUFFER_SIZE;<br>// bDriveNumber := 0;<br>with irDriveRegs do begin<br>bSectorCountReg := 1;<br>bSectorNumberReg := 1;<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>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>with PIdSector(@IdOutCmd.bBuffer)^ do begin<br>ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));<br>(Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;<br>Result := string(sSerialNumber);<br>end;<br>end;
 
应该是我在2K下,你在98下结果不同。
 
我申请的破网站可能不太好
 
希望是吧!
 
几乎所有人贴的都和我贴的差不多,大家怎么就不仔细看看我的问题呢,不过1楼的贴的c++版的到是真的解决了问题,给分了。
 
多人接受答案了。
 

Similar threads

I
回复
0
查看
738
import
I
I
回复
0
查看
691
import
I
I
回复
0
查看
865
import
I
I
回复
0
查看
666
import
I
后退
顶部