网上关于此问题的帖子满天飞,可没发现一个能在98下取到硬盘序列号的,请您测试一下再发表言论
解决方案 »
- 谁用过Wise Solutions打包软件啊,在线等,急
- odbc方式连接数据库的问题
- dbchart中横坐标不是数值的情况怎么办
- ☆☆☆晕死的问题,有谁告诉我怎么办呀!!简单的要死的问题☆☆☆☆☆
- 自动计划(autoplan)源代码***强烈推荐
- 555分没有了,诚心问个问题,给DBGrid1.Columns[4].PickList赋值时为什么不分行显示?
- SQL的问题?ADO的问题?
- ----如何调用dll?等候----
- 请发给我一个DELPHI5开发环境的启动程序给我吧!
- 强烈建议CSDN提供对以前问题贴子的模糊查找功能,这样可以避免一些重复的提问。
- OpenDialog中如何设定过滤出一系列后缀名的文件,而不是一个。
- 那位可以帮帮忙,简单问题(在线)
library ReadDiskSrNo;
uses
sharemem, //这个必须加上
dialogs,
ReadDskSNo in ‘ReadDskSNo.pas‘,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
StdCtrls;//function GetIdeDiskSerialNumber : String; export;改成
function GetIdeDiskSerialNumber:pchar; stdcall;
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
cBufferSize : DWORD;
irDriveRegs : 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;
wBufferType : Word;
wBufferSize : Word;
wECCSize : Word;
sFirmwareRev : Array[0..7] of Char;
sModelNumber : Array[0..39] of Char;
wMoreVendorUnique : Word;
wDoubleWordIO : Word;
wCapabilities : Word;
wReserved1 : Word;
wPIOTiming : Word;
wDMATiming : Word;
wBS : Word;
wNumCurrentCyls : Word;
wNumCurrentHeads : Word;
wNumCurrentSectorsPerTrack : 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;
var
hDevice : THandle;
cbBytesReturned : DWORD;
pInData : PSendCmdInParams;
pOutData : Pointer; // PSendCmdOutParams
Buffer : Array[0..BufferSize-1] of Byte;
srbControl : TSrbIoControl absolute Buffer; procedure ChangeByteOrder( var Data; Size : Integer );
var ptr : 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;
end; begin
Result := allocMem(254);
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 ) then Exit;
finally
CloseHandle(hDevice);
end;
end
else
begin // Windows 95 OSR2, Windows 98
hDevice := CreateFile( ‘.SMARTVSD‘, 0, 0, nil,
CREATE_NEW, 0, 0 );
if hDevice=INVALID_HANDLE_VALUE then 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));
result:=sSerialNumber;
end;
end;exports
GetIdeDiskSerialNumber index 1;
begin
end.
————————unit ReadDskSNo;
interface
function GetIdeDiskSerialNumber:[gold]pchar[/gold];implementation
function GetIdeDiskSerialNumber:[red]pchar[/red]; external ‘ReadDiskSrNo‘ index 1;
end.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;{*******Use in Win2k ****************}
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
cBufferSize : DWORD;
irDriveRegs : 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;
wBufferType : Word;
wBufferSize : Word;
wECCSize : Word;
sFirmwareRev : Array[0..7] of Char;
sModelNumber : Array[0..39] of Char;
wMoreVendorUnique : Word;
wDoubleWordIO : Word;
wCapabilities : Word;
wReserved1 : Word;
wPIOTiming : Word;
wDMATiming : Word;
wBS : Word;
wNumCurrentCyls : Word;
wNumCurrentHeads : Word;
wNumCurrentSectorsPerTrack : Word;
ulCurrentSectorCapacity : ULONG;
wMultSectorStuff : Word;
ulTotalAddressableSectors : ULONG;
wSingleWordDMA : Word;
wMultiWordDMA : Word;
bReserved : Array[0..127] of Byte;
end;
PIdSector = ^TIdSector;{************end Win2k*****************}const
{********** Use in Win2k **********}
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;
{********* End Win2k***************}{********* Use in Win9x ***********}
hookexceptionno = 5;
{********* End in Win9x************}var
Form1: TForm1;{********* Use in Win9x ***********}
pw : array [0..255] of Word;// pw[256];
idtr_1 : array [0..5] of Byte; //保存中断描述符表寄存器
oldexceptionhook : DWord; //保存原先的中断入口地址
IdeBase : Word;
SelectDisk: Integer;
ErrNo : Integer = 0;
{********* End in Win9x************}implementation{$R *.dfm}{********* Use in Win9x ***********}
function inp(rdx:Word) : Byte;
asm
mov dx, rdx
in al, dx
end;function inpw(rdx: Word) : Word;
asm
mov dx, rdx
in ax, dx
end;procedure outp(ral : Byte; rdx : Word);
asm
mov dx, rdx
mov al, ral
out dx, al
end;function WaitIde:Byte;
var
al: Byte;
begin
repeat
al:=inp(IdeBase+7);
until (al<$80) or (al=$a0); //$a0可能就没有硬盘
WaitIde := al;
end;procedure ReadIDE;
var
al: Byte;
i: Integer;
begin
WaitIde;
outp(SelectDisk,IdeBase+6);
al := WaitIde;
if ((al and $50) <>$50) then
begin
ErrNo := 1;
exit;
end;
outp(SelectDisk,IdeBase+6);
outp($EC,IdeBase+7);
al := WaitIde;
if ((al and $58)<>$58) then
begin
ErrNo := 2;
exit;
end;
for i := 0 to 255 do
begin
pw[i] := inpw(IdeBase);
end;
end;// 新的中断处理程序
procedure ReadIt; assembler;
asm
push eax
push ebx
push ecx
push edx
push esi
push edi
// 在这里写读程序
call ReadIDE
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
end;procedure GetSerialNo; assembler;
asm
push eax
// 获取修改的中断的中断描述符(中断门)地址
sidt idtr_1
mov eax,dword ptr idtr_1+02h
add eax,hookexceptionno*08h+04h
// 保存原先的中断入口地址
cli
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-04h]
mov dword ptr oldexceptionhook,ecx
pop ecx
// 设置修改的中断入口地址为新的中断处理程序入口地址
push ebx
lea ebx,ReadIt
mov word ptr [eax-04h],bx
shr ebx,10h
mov word ptr [eax+02h],bx
pop ebx
// 执行中断,转到ring 0(与cih 病毒原理相似!)
push ebx
int hookexceptionno
pop ebx
// 恢复原先的中断入口地址
push ecx
mov ecx,dword ptr oldexceptionhook
mov word ptr [eax-04h],cx
shr ecx,10h
mov word ptr [eax+02h],cx
pop ecx
// 结束
sti
pop eax
ret
end;procedure GetIdeDiskSN9X(DriverNo: integer; var s:string);
var
i: Integer;
begin
{如果有多硬盘一般可能有4个硬盘,也可能多至8个硬盘}
ErrNo:=0;
fillchar(pw,sizeof(pw),0);
s:='';{设置基址,
4,5:IdeBase := $1e8;
6,7:IdeBase := $168;}
case DriverNo of
0,1: IdeBase := $1f0;
2,3: IdeBase := $170;
end;{ 指定主从,Driver No 是奇数为$B0,偶数为$A0}
case DriverNo of
0,2: SelectDisk:=$A0;
1,3: SelectDisk:=$B0;
end;GetSerialNo;
if ErrNo<>0 then
Exit; //读错误
if (pw[0]=0) then
s := ''
else
for i := 10 to 20 do
begin
s := s+ char(pw[i] shr 8) + char(pw[i] and $ff);
end;
end;
{********* End in Win9x************}{*******Use in Win2k ****************}
procedure ChangeByteOrder(var Data; Size : Integer);
var
ptr: 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;
end;
{ Windows NT, Windows 2000
通过MS的S.M.A.R.T.接口,直接从RING3调用
API DeviceIoControl()来获取硬盘信息
Get SCSI port handle}
function GetIdeDiskSNNT : 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);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 ) then
Exit;
finally
CloseHandle(hDevice);
end;with PIdSector(PChar(pOutData)+16)^ do
begin
ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
SetString(Result,sSerialNumber,SizeOf(sSerialNumber));
end;
Result := Trim(Result);
end;
{********* End in Win2k************}function getIDEHardDiskSN: String;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
Result := getIDEDiskSNNT
else if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
getIDEDiskSN9x(0,Result)
else
Result := '';
end;procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text := getIDEHardDiskSN;
end;end.
以上代码在 Delphi 6+Win98,Delphi 6 + Win2000 下调试通过(2000下不需要ADMIN权限)。
只适用于IDE硬盘,还有好象三星的某种硬盘无出厂序列号,当然也搞不定了:)
{$IFDEF WIN32}
var
pdw : pDWord;
mc, fl : dword;
{$ENDIF}
begin
{$IfDef WIN32}
New(pdw);
GetVolumeInformation('c:\',nil,0,pdw,mc,fl,nil,0);
Result := pdw^;
dispose(pdw);
{$ELSE}
Result := GetWinFlags;
{$ENDIF}
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
edit1.Text:=inttostr(gethdserialnumber);
end;
---------------------------------------------
function GetHDSerialNumber: LongInt;
我要的是硬盘序列号,不是分区号
函数以及定义:
function ReadPhysicalDrive(driveID:integer;buffer:Pointer;bufLen:integer):integer; stdcall; external 'DiskID.dll' name 'ReadPhysicalDriveInNT';
获得WinNT下的硬盘型号以及序列号。参数driveID为硬盘的位置,IDE1上的主盘为0,类推到IDE2上的从盘的driveID为3。
function ReadPhysicalDrive9X(driveID:integer;buffer:Pointer;bufLen:integer):integer; stdcall; external 'DiskID.dll' name 'ReadDrivePortsInWin9X';
获得Win9X下的硬盘型号以及序列号。参数同上
function getHardDriveComputerID:int64; stdcall; external 'DiskID.dll' name 'getHardDriveComputerID';
获得计算机的ID http://www.applevb.com/lib/diskio.rar