📄 myfunction.pas
字号:
sizeof(reg),@reg,sizeof(reg),cb,nil);
if((reg.Flags and 1)=1) then
raise exception.CreateFmt('错误代码:%.2x',[reg.EAX and $FFFF]);
end; //end of if (1)
Move(p^,Sec^,SectorCount*512); //参数分别是源地址,目标地址,需移动的数据量
//LoadFileIntoHexViewer; {把文件以16进制读入StringGrid中}
{
//写盘
LockDrive(hDeviceHandle,drive98,true); //首先对逻辑区加锁
if(hDeviceHandle<>INVALID_HANDLE_VALUE)then
begin
buffer.dwStartSector:=0;
buffer.wSectors:=1;
buffer.lpBuffer:=p;
reg.EAX:=$7305;
reg.EBX:=integer(@buffer);
reg.ECX:=-1;
reg.EDX:=drive98;
reg.ESI:=1; //1表示写
reg.Flags:=0;
DeviceIoControl(hDeviceHandle,VWIN32_DIOC_DOS_DRIVEINFO,@reg,
sizeof(reg),@reg,sizeof(reg),cb,nil);
if((reg.Flags and 1)=1)then
raise exception.CreateFmt('错误代码: %.2x',[reg.EAX and $FFFF]);
end; //end of if
LockDrive(hDeviceHandle,drive98,false); //最后要解锁
}
freemem(p,SectorCount*BytesPerSector);
end; //end of VER_PLATFORM_WIN32_WINDOWS case
end; //end of case
end;
//----------RING0权限读写磁盘
procedure Ring0ReadWriteDisk;stdcall;
procedure SendCommand; stdcall;
var
IOR:PIOR;
iorBuffer:array[0..$fc-1]of char; //$fc=$ac+$58 sizeof(IOR)=$58
buffer:array[0..512-1]of char;
begin
fillchar(iorbuffer[0],sizeof(iorBuffer),0);
ior:=PIOR(@iorBuffer[$ac]);
ior^.IOR_vol_designtr := Ring0DiskRW.Drv;
if Ring0DiskRW.ReadOrNot then
ior^.IOR_func := IOR_READ
else begin
ior^.IOR_func := IOR_WRITE;
move(Ring0DiskRW.Diskbuffer[0],buffer[0],512);
end;
ior^.IOR_flags := IORF_PHYS_CMD or IORF_VERSION_002 or IORF_SYNC_COMMAND or IORF_HIGH_PRIORITY;
ior^.IOR_buffer_ptr := longword(@buffer);
ior^.IOR_xfer_count := 1;
ior^.IOR_start_addr[0] := Ring0DiskRW.StartSecLo;
ior^.IOR_start_addr[1] := Ring0DiskRW.StartSecHi;
ior^.IOR_next := 1;
asm
push es
push ds
pushad
mov esi,ior
mov ax,ss
mov es,ax
mov ds,ax
int 20h
dd 00100004h // IOS_SendCommand(ior,NULL);
popad
pop ds
pop es
end;
Ring0DiskRW.result:=(ior^.IOR_status=0);
if Ring0DiskRW.result and Ring0DiskRW.ReadOrNot then
move(buffer[0],Ring0DiskRW.Diskbuffer[0],512);
end;
procedure Ring0ToRun; stdcall;
const
ExceptionUsed = $03; // 中断号
begin
asm
sidt IDT {读入中断描述符表}
mov ebx, dword ptr [IDT+2]
add ebx, 8*ExceptionUsed {计算中断在中断描述符表中的位置}
cli {关中断}
mov dx, word ptr [ebx+6]
shl edx, 16d {左移166位}
mov dx, word ptr [ebx]
mov [lpOldGate], edx {保存旧的中断门}
mov eax, offset @@Ring0Code{修改向量,指向Ring0级代码段}
mov word ptr [ebx], ax
shr eax, 16d
mov word ptr [ebx+6], ax
int ExceptionUsed { 发生中断}
mov ebx, dword ptr [IDT+2] {重新定位到中断描述符表中}
add ebx, 8*ExceptionUsed
mov edx, [lpOldGate]
mov word ptr [ebx], dx
shr edx, 16d
mov word ptr [ebx+6], dx {恢复被改了的向量}
ret
@@Ring0Code: {Ring0级代码段}
push es
push ds
pushad
call SendCommand
popad
pop ds
pop es
iretd {中断返回}
end; //end of asm
end;
begin
Ring0DiskRW.result:=false;
Ring0ToRun;
end;
//----------读取物理磁盘的任意扇区
procedure ReadAnyPSec(SecStart:longword; SecBuf:Pchar);
const
BytesPerSector=512;
SectorCount=1; //读写扇区数
Pdrive2000='\\.\PHYSICALDRIVE0'; //物理磁盘 0表示第一个硬盘
var
// cb:DWORD;
buf:array[0..512-1] of char; //读取WIN9X下的任一物理扇区的缓冲区
osVerInfo:TOSVersionInfo;
p:pchar; //读取WIN2000下的任一物理扇区的缓冲区
begin
osVerInfo.dwOSVersionInfoSize:=SizeOf(TOSVersionInfo);
if(GetVersionEx(osVerInfo))then
case(osVerInfo.dwPlatformId)of
//在Windows NT/2000下对磁盘读写
VER_PLATFORM_WIN32_NT://Windows NT/2000
begin
hDeviceHandle:=CreateFile(Pdrive2000,GENERIC_ALL,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if (hDeviceHandle<>INVALID_HANDLE_VALUE)then
begin //if (1)
try
p:=allocmem(SectorCount*BytesPerSector);
//p 必须为新申请的内存或全局变量,不能是局部变量,用于临时缓冲
//如"p:array[0..512-1] of char" 定义为局部变量是不能读写磁盘的。
//读盘
// showmessage(IntToStr(SecStart));
FileSeek(hDevicehandle,SecStart*BytesPerSector,0);//起始扇区
if FileRead(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then //读扇区
raise exception.Create('Read 错误');
Move(p^,SecBuf^,SectorCount*512); //参数分别是源地址,目标地址,需移动的数据量
finally
freemem(p,SectorCount*BytesPerSector);
closehandle(hDeviceHandle);
end; //end of try
end; //end of if (1)
end; //end of VER_PLATFORM_WIN32_NT case
//在WIN9X下对磁盘进行读写
VER_PLATFORM_WIN32_WINDOWS://Windows 9x/ME
begin
// try
//p:=allocmem(SectorCount*BytesPerSector);
//p 必须为新申请的内存或全局变量,不能是局部变量,用于临时缓冲
//如"p:array[0..512-1] of char" 定义为局部变量是不能读写磁盘的。
Ring0DiskRW.Drv:=$80;
Ring0DiskRW.ReadOrNot:=true; //读
Ring0DiskRW.StartSecLo:=SecStart;
Ring0DiskRW.StartSecHi:=0;
Ring0DiskRW.DiskBuffer:=@buf;
Ring0ReadWriteDisk;
if not Ring0DiskRW.result then raise exception.create('读出错');
{
s:='';
for i:=0 to 512-1 do
begin
s:=s+format('%.2X ',[integer(p[i])]) ;//
if i mod 16=15 then s:=s+#13;
end;
showmessage(s);
}
Move(buf[0],SecBuf[0],512); //参数分别是源地址,目标地址,需移动的数据量
//finally
// freemem(p,SectorCount*BytesPerSector);
// end; // end of try
end; //end of VER_PLATFORM_WIN32_WINDOWS case
end; //end of case
end;
//----------查找分区表
procedure SearchDrivers();
const
offs:integer=$1be;
var
TurnOver,temp:Boolean;
i,j:integer;
DDbuf:array[0..512-1]of char;
BootBuf:array[0..512-1]of char;
SecAddress:Cardinal;
begin
i:=1;
SecAddress:=0;
ReadAnyPSec(SecAddress,DDbuf);
ReadAnyPSec(SecAddress,Bootbuf);
mhead[0]:= 0;
mtrack[0]:= 0;
msector[0]:= 1; // offs = 0x1be;
bhead[0]:=word(DDbuf[offs+1]); // printf begin head,
btrack[0]:=word(DDbuf[offs+3]); // printf begin track
bsector[0]:=word(DDbuf[offs+2]); // printf begin sector
// showmessage(IntToStr(btrack[0])+' '+IntToStr(bhead[0])+' '+IntToStr(bsector[0]));
// totalSec[0]:=integer(Dbuf[$1cd])*16777216+integer(Dbuf[$1cc])*65536
// +integer(Dbuf[$1cb])*256+integer(Dbuf[$1ca]);
End_Sector_No:=word(DDbuf[$1cd])*16777216+word(DDbuf[$1cc])*65536
+word(DDbuf[$1cb])*256+word(DDbuf[$1ca])+63-1;
PartType[0]:=Integer(DDbuf[offs+4]);
//showmessage(IntToStr(PartType[0]));
//showmessage(IntToStr(End_Sector_No));
//计算结果
etrack[0]:=End_Sector_No div(63*255); //柱面
ehead[0]:=End_Sector_No div 63 mod 255; //磁头
esector[0]:=End_Sector_No mod 63+1 ; //扇区
etrack[0]:=etrack[0]+btrack[0];
// showmessage(IntToStr(etrack[0])+' '+IntToStr(ehead[0])+' '+IntToStr(esector[0]));
DiskTotalSecs:=(word(DDbuf[$1cd])+word(DDbuf[$1dd]))*16777216
+(word(DDbuf[$1cc])+word(DDbuf[$1dc]))*65536
+(word(DDbuf[$1cb])+word(DDbuf[$1db]))*256
+(word(DDbuf[$1ca])+word(DDbuf[$1da]))+63; //63为MBR引导磁道的扇区数
maxtracks:=DiskTotalSecs div(63*255);
//showmessage(IntToStr(Maxtracks));
temp:=true;
for j:=0 to 15 do
temp:=temp and (integer(DDbuf[$1ce+j])=0);
// if temp then showmessage('1')
// else showmessage('0');
TurnOver:=temp;
while(not TurnOver) do //464=0x1d0
begin
{if(maxtracks<1024) then //1 //没有扩展中断13 //i=1 ,464=0x1d0
begin //每个分区表长0x10=16
mhead[i] := word(DDbuf[offs+1+$10]); //dbuff[463]
mtrack[i] := (word(DDbuf[offs+2+$10])and $c0 shr 6 )*256
+word(DDbuf[offs+3+$10]); //dbuff[465]
msector[i] := word(DDbuf[offs+2+$10]) and $3f; //dbuff[464]
// showmessage(IntToStr(mtrack[1])+' '+IntToStr(mhead[1])+' '+IntToStr(msector[1]));
// SecAddress:=mtrack[i]*255*63 + mhead[i]*63 + msector[i]-1; //绝对地址从0起算
SecAddress:=(word(DDbuf[offs+2+$10])and $c0 shr 6 )*256
+word(DDbuf[offs+3+$10])*255*63
+word(DDbuf[offs+1+$10])*63
+word(DDbuf[offs+2+$10]) and $3f-1;
//showmessage(IntToStr(SecAddress));
ReadAnyPSec(SecAddress,DDbuf); //读扩展分区表
bhead[i] :=integer(DDbuf[offs+1]); //扩展分区开始磁头
btrack[i] :=(integer(DDbuf[offs+2])and $c0 shr 6 )*256
+integer(DDbuf[offs+3]); //扩展分区开始柱面
bsector[i]:=integer(DDbuf[offs+2])and $3f; //扩展分区开始扇区
// showmessage(IntToStr(btrack[1])+' '+IntToStr(bhead[1])+' '+IntToStr(bsector[1]));
end //end of then 1
else
}
//begin
if integer(DDbuf[$1be])=$80 then //2
begin
Extend_Start_No:=word(BootBuf[$1d9])*16777216+word(BootBuf[$1d8])*65536
+word(BootBuf[$1d7])*256+word(BootBuf[$1d6]); //扩展分区表绝对地址
// showmessage(IntToStr(Extend_Start_No));
// Extend_Start_No 记录扩展分区开始的绝对数
ReadAnyPSec(Extend_Start_No,DDbuf); //用绝对地址读一个扇区
mtrack[1]:=Extend_Start_No div(63*255); //柱面
mhead[1]:=Extend_Start_No div 63 mod 255; //磁头
msector[1]:=Extend_Start_No mod 63 +1; //扇区
// showmessage(IntToStr(mtrack[1])+' '+IntToStr(mhead[1])+' '+IntToStr(msector[1]));
bhead[1]:= mhead[1]+1; //磁头数加1得到DBR开始地址
btrack[1] := mtrack[1];
bsector[1] := msector[1];
// showmessage(IntToStr(btrack[1])+' '+IntToStr(bhead[1])+' '+IntToStr(bsector[1]));
// totalSec[1]:=integer(integer(Dbuf[$1cd])*16777216+integer(Dbuf[$1cc])*65536
// +integer(Dbuf[$1cb])*256+integer(Dbuf[$1ca]));
End_Sector_No:=word(BootBuf[$1cd])*16777216+word(BootBuf[$1cc])*65536
+word(BootBuf[$1cb])*256+word(BootBuf[$1ca])+63-1;
// showmessage(IntToStr(End_Sector_No));
PartType[1]:=integer(BootBuf[offs+4]);
// showmessage(IntToStr(PartType[1]));
etrack[1]:=End_Sector_No div(63*255)+btrack[1]; //柱面
ehead[1]:=End_Sector_No div 63 mod 255; //磁头
esector[1]:=End_Sector_No mod 63 +1; //扇区
temp:=true;
for j:=0 to 15 do
begin
temp:=temp and (integer(DDbuf[$1ce+j])=0);
// if temp then showmessage('1')
// else showmessage('0');
end;
TurnOver:=temp;
// showmessage(IntToStr(etrack[1])+' '+IntToStr(ehead[1])+' '+IntToStr(esector[1]));
end // end of then 2
else // integer(DDbuf[$1be])<>$80
begin //2
Sector_No:=word(DDbuf[$1d9])*16777216+word(DDbuf[$1d8])*65536
+word(DDbuf[$1d7])*256+word(DDbuf[$1d6]);
if (Integer(DDbuf[$1d2])=$05) then //指向下一个逻辑分区的标志都是0x05
Sector_No:=Sector_No+Extend_Start_No; //得到下一扇区开始地址
ReadAnyPSec(Sector_No,DDbuf);
mtrack[i]:=Sector_No div(63*255); //柱面
mhead[i]:=Sector_No div 63 mod 255; //磁头
msector[i]:=Sector_No mod 63 +1; //扇区
bhead[i] := mhead[i]+1;
btrack[i] := mtrack[i];
bsector[i] := msector[i];
// showmessage(IntToStr(btrack[i])+' '+IntToStr(bhead[i])+' '+IntToStr(bsector[i]));
// totalSec[i]:=integer(Dbuf[$1cd])*16777216+integer(Dbuf[$1cc])*65536
// +integer(Dbuf[$1cb])*256+integer(Dbuf[$1ca]);
End_Sector_No:=integer(DDbuf[$1cd])*16777216+integer(DDbuf[$1cc])*65536
+integer(DDbuf[$1cb])*256+integer(DDbuf[$1ca])+63-1;
PartType[i]:=integer(DDbuf[offs+4]);
//showmessage(IntToStr(PartType[i]));
etrack[i]:=End_Sector_No div(63*255)+btrack[i]; //柱面
ehead[i]:=End_Sector_No div 63 mod 255; //磁头
esector[i]:=End_Sector_No mod 63 +1; //扇区
temp:=true;
for j:=0 to 15 do
begin
temp:=temp and (integer(DDbuf[$1ce+j])=0);
end;
TurnOver:=temp;
// showmessage(IntToStr(etrack[i])+' '+IntToStr(ehead[i])+' '+IntToStr(esector[i]));
end; // end of else 2
//end; //end of else
i:=i+1;
if i>26 then break;
end; //end of while
MaxParts:=i;
//i:=0;
showmessage('MaxParts = '+IntToStr(MaxParts));
for j:=0 to MaxParts-1 do
showmessage(IntToStr(bTrack[j])+' '+IntToStr(bhead[j])+' '+IntToStr(bSector[j]));
end;
//------------写任意物理扇区
Procedure WriteAnyPSec(SecStart:longword;Buf:array of char);
const
BytesPerSector=512;
SectorCount=1; //读写扇区数
Pdrive2000='\\.\PHYSICALDRIVE0'; //物理磁盘 0表示第一个硬盘
var
p:pchar; //2000下使用
Mybuf:array[0..512-1]of char; //9x下使用
i:integer;
s:string;
begin
if GetWinVer=2 then //当前系统为winNT/2000
begin
p:=allocmem(SectorCount*BytesPerSector);
//p 必须为新申请的内存或全局变量,不能是局部变量,用于临时缓冲
//如"p:array[0..512-1] of char" 定义为局部变量是不能读写磁盘的。
for i:=0 to 512-1 do
p[i]:=buf[i];
{s:='';
for i:=0 to 512-1 do
begin
s:=s+format('%.2X ',[integer(p[i])]) ;//
if i mod 16=15 then s:=s+#13;
end;
showmessage(s);
}
if Messagedlg('是否对相应扇区进行写入操作',mtConfirmation,[mbYes,mbNo],0)=IdYes then //2
begin
hDeviceHandle:=CreateFile(Pdrive2000,GENERIC_ALL,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if (hDeviceHandle<>INVALID_HANDLE_VALUE)then //3
begin
//写盘
FileSeek(hDevicehandle,SecStart*BytesPerSector,0);//起始扇区
if FileWrite(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then //写扇区
raise exception.Create('Write 错误%d')
else
Messagedlg('已经成功对相应扇区的写入',mtInformation,[mbOK],0);
end; //end of if 3
freemem(p,SectorCount*BytesPerSector);
closehandle(hDeviceHandle);
end; //end of if 2
end
else //当前系统为WIN9X,或者其他
begin
for i:=0 to 512-1 do
Mybuf[i]:=buf[i];
{s:='';
for i:=0 to 512-1 do
begin
s:=s+format('%.2X ',[integer(Mybuf[i])]) ;//
if i mod 16=15 then s:=s+#13;
end;
showmessage(s);
}
if Messagedlg('是否对相应扇区进行写入操作',mtConfirmation,[mbYes,mbNo],0)=IdYes then //4
begin
Ring0DiskRW.Drv:=$80;
Ring0DiskRW.ReadOrNot:=false; //读
Ring0DiskRW.StartSecLo:=SecStart;
Ring0DiskRW.StartSecHi:=0;
Ring0DiskRW.DiskBuffer:=@Mybuf;
Ring0ReadWriteDisk;
if not Ring0DiskRW.result then
raise exception.create('读出错')
else
Messagedlg('已经成功对相应扇区的写入',mtInformation,[mbOK],0);
end; //end of if 4
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -