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

📄 ldiskio.pas

📁 一个磁盘文件被删除后恢复的源程序! 内嵌汇编代码~!
💻 PAS
📖 第 1 页 / 共 2 页
字号:

     bDrive
        The MS-DOS logical drive number. 0 = default, 1 = A, 2 = B,
        3 = C, etc.

     dwStartSector
        The first sector to read.

     wSectors
        The number of sectors to read.

     lpSectBuff
        The caller-supplied buffer to read into.

   Return Value:
     Returns TRUE if successful, or FALSE if failure.

   Comments:
     This function does not validate its parameters.  It assumes that
     lpSectBuff is allocated by the caller and is large enough to
     hold all of the data from all of the sectors being read.
   ------------------------------------------------------------------*)
   function NewReadSectors (bDrive: BYTE;
                            dwStartSector: LONGWORD;
                            wSectors: WORD;
                            lpSectBuff: pointer): BOOLEAN;

   var
     fResult: BOOL;
     cb     : DWORD;
     reg    : DIOC_REGISTERS;
     dio    : DISKIO;

   begin
     fillchar(reg, sizeof(DIOC_REGISTERS), 0);
     fillchar(dio, sizeof(DISKIO), 0);

     dio.dwStartSector := dwStartSector;
     dio.wSectors      := wSectors;
     dio.lpBuffer      := lpSectBuff;

     reg.reg_EAX := $7305;   // Ext_ABSDiskReadWrite
     reg.reg_EBX := DWORD(@dio);
     reg.reg_ECX := DWORD(-1);
     reg.reg_EDX := bDrive;  // Int 21h, fn 7305h drive numbers are 1-based

     fResult := DeviceIoControl(W95Handle, VWIN32_DIOC_DOS_DRIVEINFO,
                               @reg, sizeof(reg),
                               @reg, sizeof(reg), cb, 0);

     // Determine if the DeviceIoControl call and the read succeeded.
     fResult := fResult AND (reg.reg_Flags AND CARRY_FLAG=0);

     result:=fResult;
   end;


   (*------------------------------------------------------------------
   NewWriteSectors(hDev, bDrive, dwStartSector, wSectors, lpSectBuff)

   Purpose:
     Writes the specified number of sectors from a caller-supplied
     buffer. Uses Int 21h function 7305h

   Parameters:
     hDev
        Handle of VWIN32

     bDrive
        The MS-DOS logical drive number. 0 = default, 1 = A, 2 = B,
        3 = C, etc.

     dwStartSector
        The first sector to write.

     wSectors
        The number of sectors to write.

     lpSectBuff
        The caller-supplied buffer from which to write.

   Return Value:
     Returns TRUE if successful, or FALSE if failure.

   Comments:
     This function does not validate its parameters.  It assumes that
     lpSectBuff is allocated by the caller and is large enough to
     hold all of the data to be written.
   ------------------------------------------------------------------*)
  function NewWriteSectors (bDrive: BYTE; 
                             dwStartSector: LONGWORD;
                             wSectors: WORD;
                             lpSectBuff: pointer): BOOLEAN;
    var
     fResult: BOOL;
     cb     : DWORD;
     reg    : DIOC_REGISTERS;
     dio    : DISKIO;

   begin
     fillchar(reg, sizeof(DIOC_REGISTERS), 0);
     fillchar(dio, sizeof(DISKIO), 0);

     dio.dwStartSector := dwStartSector;
     dio.wSectors      := wSectors;
     dio.lpBuffer      := lpSectBuff;

     reg.reg_EAX := $7305;   // Ext_ABSDiskReadWrite
     reg.reg_EBX := DWORD(@dio);
     reg.reg_ECX := DWORD(-1);
     reg.reg_EDX := bDrive;  // Int 21h, fn 7305h drive numbers are 1-based

     reg.reg_ESI := $6001;   // Normal file data (See function
                             // documentation for other values)


     fResult := DeviceIoControl(W95Handle, VWIN32_DIOC_DOS_DRIVEINFO,
                               @reg, sizeof(reg),
                               @reg, sizeof(reg), cb, 0);

     // Determine if the DeviceIoControl call and the write succeeded.
     fResult := fResult AND (reg.reg_Flags AND CARRY_FLAG=0);

     result:=fResult;
   end;



   // Get Logical Drive Parameters
   function GetLogDriveParams(bDrive: BYTE; params: PLogDriveParams): boolean;
   var
     h:   tHANDLE;
     reg:  DIOC_REGISTERS;
     cb:   DWORD;
     res:  boolean;
     dpb:  DOSDPB;
     hDevice: thandle;
     dg:   TDISK_GEOMETRY;
   begin
      res:=false;
      if (fWinNT) then
      begin
        // ---------- Windows NT... ----------------------------------------------
        hDevice := CreateFile(pchar('\\.\'+chr(ord('A')+bDrive-1)+':'), 0, FILE_SHARE_WRITE,
          nil, OPEN_EXISTING, 0, 0);
        if hDevice <> INVALID_HANDLE_VALUE then
        begin
          { if NT CD-ROM }
          if GetDriveType(pchar(chr(ord('A')+bDrive-1)+':\'))=DRIVE_CDROM then
          begin
            fillchar(params^, sizeof(TLogDriveParams), 0);
            params^.MediaType:=LMEDIA_TYPE_CDROM;
            params^.MediaAttr:=LMEDIA_ATTR_REMOVABLE;
            params^.BytesPerSector:=2048;
            result:=true;
            exit;
          end;
          { if NT Floppy, Harddisk, etc. } 
          res := DeviceIoControl(hDevice,
             IOCTL_DISK_GET_DRIVE_GEOMETRY, nil, 0,
             @dg, sizeof(TDISK_GEOMETRY), cb, nil);
          CloseHandle(hDevice);
          if res then
          begin
            params^.MediaAttr:=0;
            params^.Heads:=dg.cylinders.lowpart;
            params^.TracksPerHead:=dg.trackspercylinder;
            params^.SectorsPerTrack:=dg.sectorspertrack;
            params^.BytesPerSector:=dg.bytespersector;
            params^.TotalPhysSec:=dg.cylinders.lowpart * dg.TracksPerCylinder * dg.SectorsPerTrack;
            case dg.MediaType of
              0:             params^.MediaType:=LMEDIA_TYPE_UNKNOWN;
              1..10, 13..22: begin
                               params^.MediaType:=LMEDIA_TYPE_FLOPPY;
                               params^.MediaAttr:=LMEDIA_ATTR_REMOVABLE;
                             end;
              11:            begin
                               params^.MediaType:=LMEDIA_TYPE_REMOVABLE;
                               params^.MediaAttr:=LMEDIA_ATTR_REMOVABLE;
                             end;
              12:            params^.MediaType:=LMEDIA_TYPE_FIXED;
            end;
          end;
        end;
      end else
      begin
        //  --------- Windows 9X... --------------------------------------------
        if IsCDROM(bDrive) then
        begin
          fillchar(params^, sizeof(TLogDriveParams), 0);
          params^.MediaType:=LMEDIA_TYPE_CDROM;
          params^.MediaAttr:=LMEDIA_ATTR_REMOVABLE;
          params^.BytesPerSector:=2048;
          result:=true;
          exit;
        end;

        if optUseINT25 then
        begin
          dpb.specialFunc := 0;  // return default type; do not hit disk

          reg.reg_EBX   := bDrive;       // BL = drive number (1-based)
          reg.reg_EDX   := DWORD(@dpb);  // DS:EDX -> DPB
          reg.reg_ECX   := $0860;        // CX = Get DPB
          reg.reg_EAX   := $440D;        // AX = Ioctl
          reg.reg_Flags := CARRY_FLAG;   // assume failure

          // Make sure both DeviceIoControl and Int 21h succeeded.
          res:=(DeviceIoControl (W95handle, VWIN32_DIOC_DOS_IOCTL, @reg,
                               sizeof(reg), @reg, sizeof(reg), cb, 0)
                               AND (reg.reg_Flags AND CARRY_FLAG=0));
          if res then
          begin
            params^.MediaAttr:=0;
            params^.Heads:=dpb.cHead;
            params^.TracksPerHead:=dpb.cCyl;
            params^.SectorsPerTrack:=dpb.secPerTrack;
            params^.BytesPerSector:=dpb.cbSec;
            params^.TotalPhysSec:=dpb.cCyl * dpb.cHead * dpb.secPerTrack;
            case dpb.devType of
              0..4, 7,8: params^.MediaType:=LMEDIA_TYPE_FLOPPY;
              5:         params^.MediaType:=LMEDIA_TYPE_FIXED;
              6,9:       if (dpb.devAttr AND 1) = 0 then params^.MediaType:=LMEDIA_TYPE_REMOVABLE
                          else params^.MediaType:=LMEDIA_TYPE_UNKNOWN;
            end;
            if (dpb.devAttr AND 1) = 0 then params^.MediaAttr:=LMEDIA_ATTR_REMOVABLE;
          end;
        end;
       end;
      result:=res;
   end;



  // -----------------------------------------------------------------------------------
  //     MSCDEX  /  CDFS (INT2F.VXD) ...
  // -----------------------------------------------------------------------------------


  function IsCDROM(drv: byte):Boolean;
  var
    res: boolean;
    inbuf: byte;
    outbuf: byte;
    cb: dword;
  begin
    inbuf:=drv-1;
    res:=DeviceIoControl(CDhandle, DIOC_ISCDROM,
        @inbuf, 1,
        @outbuf, 1, cb, nil);

    result:=res AND (outbuf=1);
  end;


  function ReadCDROMSectors(drv: byte; LBA: longword; blocks: byte; buf: pointer;
    ErrorDlg: boolean): boolean;
  var
    res: boolean;
    struc: cdromstruc;
    cb: dword;
    tempbuf: array[0..2047] of byte;
    count: integer;
    msgRes: integer;

  begin
    count:=0;

    struc.Drv    := drv-1;
    struc.LBA    := LBA;
    struc.blocks := 1; //blocks;
    struc.buf    := {buf;} @tempbuf;
    repeat
      repeat
        res:=DeviceIoControl(CDhandle, DIOC_READSECTORS,
            @struc, sizeof(cdromstruc),
            nil, 0, cb, nil);
        msgRes := id_abort;
        if (NOT res) AND (ErrorDlg) then
        begin
          msgRes:=messagebox(0, pchar('Error reading sector, '+#13#10+'drv:'+inttostr(drv)+' LBA:'+inttostr(LBA)
            +' blocks:'+inttostr(blocks) +#13#10#13#10
            +' Abort, Retry or Ignore?'), pchar('MSCDEX/CDFS CD-ROM read error '+inttostr(windows.GetLastError)),
               mb_applmodal or mb_iconwarning or mb_abortretryignore);

        end;
      until NOT ((ErrorDlg) AND (msgRes = id_Retry));
      if (NOT res) AND (ErrorDlg) AND (msgRes = id_ignore) then res:=true;
      if res then move(tempbuf, buf^, 2048);

      inc(longword(buf),2048);
      inc(count);
      inc(struc.LBA);
    until (NOT res) OR (count >= blocks);

    result:=res;
  end;


   // -------------------------------------------------------------------------

   //        same stuff for Windows NT . . .

   // -------------------------------------------------------------------------


  (* -- open / close drive handle ------------------------------------------ *)

  function NT_changeDrive(bDrive: BYTE; ReadOnly: boolean): boolean;
  var
    hDevice: thandle;
  begin
    // notice: under WinNT each drive has to be opened - under Win9X/ME one handle is for all drives
    if (NThandle <> INVALID_HANDLE_VALUE) then
    begin
      if NTdrive = bDrive then
      begin
        result:=true;
        exit;
      end else
      begin
        CloseHandle(NThandle);
      end;
    end;

    if ReadOnly then
      hDevice := CreateFile(pchar('\\.\'+chr(ord('A')+bDrive-1)+':'), GENERIC_READ, FILE_SHARE_READ OR FILE_SHARE_WRITE,
       nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0)
    else
      hDevice := CreateFile(pchar('\\.\'+chr(ord('A')+bDrive-1)+':'), GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE,
       nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0);
    NThandle:=hDevice;
    NTdrive:=bDrive;

    GetLogDriveParams(bDrive, @nt_drv_params);
    NT_ShiftBase:=round(log2(nt_drv_params.bytespersector));

    result:=(hDevice <> INVALID_HANDLE_VALUE);
  end;



  function NT_Read ( bDrive: BYTE;
                     dwStartSector: LONGWORD;
                     wSectors: WORD;
                     lpSectBuff: pointer): BOOLEAN;
  var
    res: boolean;
    bytestoread, numread, transfer: dword;
    dwpointer: dword;
    ldistancelow, ldistancehigh : dword;
    DestSector : longword;
  begin
    res:=false;

    if NT_changeDrive(bDrive, true) then
    begin
      ldistanceLow:=longword(dwStartSector) SHL NT_ShiftBase;
      ldistanceHigh:=longword(dwStartSector) SHR (32-NT_ShiftBase);

      dwpointer:=SetFilePointer(NThandle, ldistancelow, @ldistancehigh, FILE_BEGIN);
      if dwPointer <> $FFFFFFFF then
      begin
        bytestoread:=wSectors*nt_drv_params.bytespersector;
        repeat
          transfer:=bytestoread;
          if (transfer > TEMPSECTORS * nt_drv_params.bytespersector) then
            transfer:=TEMPSECTORS * nt_drv_params.bytespersector;
          res:=ReadFile(NThandle, tempbuf, transfer, numread, nil);
          if res then res:=boolean(numread=transfer);
          if res then move(tempbuf, lpSectBuff^, transfer);
          inc(longword(lpSectBuff),transfer);
          dec(bytestoread, transfer);
        until (NOT res) OR (bytestoread = 0);
      end;
    end;
    result:=res;
  end;


  function NT_Write ( bDrive: BYTE;
                     dwStartSector: LONGWORD;
                     wSectors: WORD;
                     lpSectBuff: pointer): BOOLEAN;
  var
    res: boolean;
    bytestoread, numread: dword;
    dwpointer: dword;
    ldistancelow, ldistancehigh: dword;
  begin
    res:=false;

    if NT_changeDrive(bDrive, false) then
    begin
      ldistanceLow:=dword(dwStartSector SHL 9);
      ldistanceHigh:=dword(dwStartSector SHR (32-9));
      dwpointer:=SetFilePointer(NThandle, ldistancelow, @ldistancehigh, FILE_BEGIN);
      if dwPointer <> $FFFFFFFF then
      begin
        bytestoread:=wSectors*nt_drv_params.bytespersector;
        res:=WriteFile(NThandle, lpSectBuff^, bytestoread, numread, nil);
        res:=(res AND (numread =bytestoread));
      end;
    end;
    result:=res;
  end;



  procedure MyExit;
  begin
    ExitProc := ExitSave;            { first restore old vector }

    if NOT (fWinNT) then
    begin
      // Win9X...
       if W95Handle <> INVALID_HANDLE_VALUE then
         CloseHandle(W95Handle);
       if CDHandle <> INVALID_HANDLE_VALUE then
         CloseHandle(CDHandle);
    end else
    begin
      // WinNT...
       if NThandle <> INVALID_HANDLE_VALUE then
         CloseHandle(NThandle);
    end;
  end;



begin
  optUseINT25:=TRUE;

  W95Handle := INVALID_HANDLE_VALUE;
  NTHandle  := INVALID_HANDLE_VALUE;

  fWin95OSR2orLater:=IsWin95OSR2orLater;
  fWinNT           :=IsWinNT;

  ExitSave := ExitProc;
  ExitProc := @MyExit;

  if NOT (fWinNT) then
  begin
    W95Handle := CreateFile('\\.\vwin32',
        0, 0, nil, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
    if W95handle = INVALID_HANDLE_VALUE then
      MessageBox(0, 'Error loading "VWIN32.VXD (INT25/26)"', 'Error', mb_IconExclamation + mb_ok);

    CDhandle:=CreateFile('\\.\INT2F.VXD',
       0, 0, nil, 0,  FILE_FLAG_DELETE_ON_CLOSE, 0);
    if CDhandle = INVALID_HANDLE_VALUE then
      MessageBox(0, 'Error loading "INT2F.VXD" (MSCDEX/CDFS)', 'Error', mb_IconExclamation + mb_ok);
  end;

end.





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -