⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myfunction.pas

📁 界面精美
💻 PAS
📖 第 1 页 / 共 3 页
字号:
                            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 + -