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

📄 ldiskio.pas

📁 一个磁盘文件被删除后恢复的源程序! 内嵌汇编代码~!
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{
  Logical Disk Access for Delphi
  (Absolute disk read/write under Windows 95/98/ME and NT/2000/XP)
  Written 2001 by Alexander Grau

  Contact: alexander_grau@web.de

}

unit LDISKIO;

interface

const
  { Media types }
  LMEDIA_TYPE_UNKNOWN   = 0;
  LMEDIA_TYPE_FLOPPY    = 1;
  LMEDIA_TYPE_REMOVABLE = 2;
  LMEDIA_TYPE_FIXED     = 3;
  LMEDIA_TYPE_CDROM     = 4;

  { Media attributes }
  LMEDIA_ATTR_REMOVABLE = 1;

type
  PLogDriveParams = ^TLogDriveParams;
  TLogDriveParams = record
    MediaType        : word;       { see equals above }
    MediaAttr        : word;       { see equals above }
    Heads            : longword;
    TracksPerHead    : longword;
    SectorsPerTrack  : longword;
    BytesPerSector   : longword;
    TotalPhysSec     : longword;
  end;


(* -------------- published functions --------------------------------- *)

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

   function ReadLogicalSectors (bDrive: BYTE;
                                dwStartSector: LONGWORD;
                                wSectors: WORD;
                                lpSectBuff: pointer): BOOLEAN;

   function WriteLogicalSectors (bDrive: BYTE;
                                  dwStartSector: LONGWORD;
                                  wSectors: WORD;
                                  lpSectBuff: pointer): BOOLEAN;

   function GetLogDriveParams(bDrive: BYTE; params: PLogDriveParams): boolean;

var
  optUseINT25: boolean;

(* ------------------------------------------------------------------ *)


implementation

  uses windows, sysutils, math;


  // -------- Windows 9X specific... -------------------------------------------------------

  const
    VWIN32_DIOC_DOS_IOCTL     =1;
    VWIN32_DIOC_DOS_INT25     =2; // Performs the Absolute Disk Read command (Interrupt 25h)
    VWIN32_DIOC_DOS_INT26     =3; // Performs the Absolute Disk Write command (Interrupt 26h)
    VWIN32_DIOC_DOS_DRIVEINFO =6; // Performs Interrupt 21h Function 730X commands. This value is supported in Windows 95 OEM Service Release 2 and later.

   // Intel x86 processor status flag
    CARRY_FLAG = 1;

  type
    PDIOC_REGISTERS = ^DIOC_REGISTERS;
    DIOC_REGISTERS = packed record
       reg_EBX: DWORD;
       reg_EDX: DWORD;
       reg_ECX: DWORD;
       reg_EAX: DWORD;
       reg_EDI: DWORD;
       reg_ESI: DWORD;
       reg_Flags: DWORD;
    end;

    PDISKIO = ^ DISKIO;
    DISKIO = packed record
      dwStartSector: DWORD;   // starting logical sector number
      wSectors     : WORD;    // number of sectors
      lpBuffer     : pointer; // address of read/write buffer
    end;

    PDOSDPB = ^DOSDPB;
    DOSDPB = packed record
      specialFunc: BYTE;      //
      devType    : BYTE;      //
      devAttr    : WORD;      //
      cCyl       : WORD;      // number of cylinders
      mediaType  : BYTE;      //
      cbSec      : WORD;      // Bytes per sector
      secPerClus : BYTE;      // Sectors per cluster
      cSecRes    : WORD;      // Reserved sectors
      cFAT       : BYTE;      // FATs
      cDir       : WORD;      // Root Directory Entries
      cSec       : WORD;      // Total number of sectors in image
      bMedia     : BYTE;      // Media descriptor
      secPerFAT  : WORD;      // Sectors per FAT
      secPerTrack: WORD;      // Sectors per track
      cHead      : WORD;      // Heads
      cSecHidden : DWORD;     // Hidden sectors
      cTotalSectors: DWORD;   // Total sectors, if cbSec is zero
      reserved: array[0..5] of BYTE //
    end;


  // ------ INT2F.VXD specific... ------------------------------------------------
  const
    DIOC_ISCDROM         = 1;
    DIOC_READSECTORS     = 2;

  type
    cdromstruc = packed record  { Important! Delphi is not allowed to align to 32-Bit here!
                               (otherwise something goes wrong...) }
      drv   : byte;
      LBA   : longword;
      blocks: byte;
      buf   : pointer;
    end;

  // -------- Windows NT specific... -------------------------------------------------------
  (*typedef enum _MEDIA_TYPE {
     Unknown,                // Format is unknown
     F5_1Pt2_512,            // 5.25", 1.2MB,  512 bytes/sector
     F3_1Pt44_512,           // 3.5",  1.44MB, 512 bytes/sector
     F3_2Pt88_512,           // 3.5",  2.88MB, 512 bytes/sector
     F3_20Pt8_512,           // 3.5",  20.8MB, 512 bytes/sector
     F3_720_512,             // 3.5",  720KB,  512 bytes/sector
     F5_360_512,             // 5.25", 360KB,  512 bytes/sector
     F5_320_512,             // 5.25", 320KB,  512 bytes/sector
     F5_320_1024,            // 5.25", 320KB,  1024 bytes/sector
     F5_180_512,             // 5.25", 180KB,  512 bytes/sector
     F5_160_512,             // 5.25", 160KB,  512 bytes/sector
     RemovableMedia,         // Removable media other than floppy
     FixedMedia,             // Fixed hard disk media
     F3_120M_512,            // 3.5", 120M Floppy
     F3_640_512,             // 3.5" ,  640KB,  512 bytes/sector
     F5_640_512,             // 5.25",  640KB,  512 bytes/sector
     F5_720_512,             // 5.25",  720KB,  512 bytes/sector
     F3_1Pt2_512,            // 3.5" ,  1.2Mb,  512 bytes/sector
     F3_1Pt23_1024,          // 3.5" ,  1.23Mb, 1024 bytes/sector
     F5_1Pt23_1024,          // 5.25",  1.23MB, 1024 bytes/sector
     F3_128Mb_512,           // 3.5" MO 128Mb   512 bytes/sector
     F3_230Mb_512,           // 3.5" MO 230Mb   512 bytes/sector
     F8_256_128              // 8",     256KB,  128 bytes/sector
  } MEDIA_TYPE, *PMEDIA_TYPE;*)

  type
    PLARGE_INTEGER = ^LARGE_INTEGER;
    LARGE_INTEGER = packed record
	LowPart: dword;
	HighPart: dword;
    end;

    PDISK_GEOMETRY = ^TDISK_GEOMETRY;
    TDISK_GEOMETRY = packed record
      Cylinders: LARGE_INTEGER;
      MediaType: dword;
      TracksPerCylinder: dword;
      SectorsPerTrack: dword;
      BytesPerSector: dword;
    end;

  const
    FILE_DEVICE_DISK               =  $00000007;
    FILE_DEVICE_MASS_STORAGE       =  $0000002d;
    FILE_ANY_ACCESS                =  0;
    FILE_READ_ACCESS               =  $0001;     // file & pipe

    METHOD_BUFFERED                =  0;

    IOCTL_DISK_BASE                = FILE_DEVICE_DISK;
    IOCTL_STORAGE_BASE             = FILE_DEVICE_MASS_STORAGE;
    IOCTL_DISK_GET_DRIVE_GEOMETRY  = ( ((IOCTL_DISK_BASE) SHL 16) OR ((FILE_ANY_ACCESS) SHL 14) OR (($0000) SHL 2) OR (METHOD_BUFFERED) );
    IOCTL_DISK_CHECK_VERIFY        = ( ((IOCTL_DISK_BASE) SHL 16) OR ((FILE_READ_ACCESS) SHL 14)OR (($0200) SHL 2) OR (METHOD_BUFFERED) );
    IOCTL_STORAGE_CHECK_VERIFY     = ( ((IOCTL_STORAGE_BASE) SHL 16)OR((FILE_READ_ACCESS)SHL 14)OR (($0200) SHL 2)   OR (METHOD_BUFFERED) );
    IOCTL_DISK_GET_MEDIA_TYPES     = ( ((IOCTL_DISK_BASE) SHL 16)   OR((FILE_ANY_ACCESS)SHL 14) OR (($0300) SHL 2)   OR (METHOD_BUFFERED) );

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

  const
    TEMPSECTORS = 128;


  var
    CDHandle:   thandle;    // Win9X only: current CD-ROM handle (INT2F.VXD)
    W95Handle:  thandle;    // Win9X only: current handle (VWIN32.VXD)
    NTHandle:   thandle;    // WinNT only: current handle
    NTDrive:      byte;     // WinNT only: drive currently opened
    NT_DRV_Params : TLogDriveParams; // WinNT only: current drive params
    NT_ShiftBase  : byte; //WinNT only: NT_DRV_Params.BytesPerASector in Bit-Shifts 

    fWin95OSR2orLater: boolean;
    fWinNT           : boolean;

    tempbuf: array[0..512*TEMPSECTORS-1] of byte;

    ExitSave: Pointer;


  (* --- some forward declarations ----------------------------------------- *)


   //----------- under Windows 95 OEM Service Release 2 and later... -----------
   function NewReadSectors (bDrive: BYTE;
                            dwStartSector: LONGWORD;
                            wSectors: WORD;
                            lpSectBuff: pointer): BOOLEAN; forward;

  function NewWriteSectors (bDrive: BYTE;
                             dwStartSector: LONGWORD;
                             wSectors: WORD;
                             lpSectBuff: pointer): BOOLEAN; forward;


  // ------------- CD-ROM absolute read sector ---------------------------------
  function IsCDROM(drv: byte): boolean; forward;
  function ReadCDROMSectors(drv: byte; LBA: longword; blocks: byte; buf: pointer;
    ErrorDlg: boolean): boolean; forward;

  // -------------- under Windows NT... ----------------------------------------
  function NT_Read ( bDrive: BYTE;
                     dwStartSector: LONGWORD;
                     wSectors: WORD;
                     lpSectBuff: pointer): BOOLEAN; forward;

  function NT_Write ( bDrive: BYTE;
                     dwStartSector: LONGWORD;
                     wSectors: WORD;
                     lpSectBuff: pointer): BOOLEAN; forward;


  (* --- helper functions --------------------------------------------------- *)


  function IsWin95OSR2orLater: boolean;
  var
    os: TOSVersionInfo;
    res: boolean;
  begin
    ZeroMemory(@OS,SizeOf(OS));
    OS.dwOSVersionInfoSize:=SizeOf(OS);
    GetVersionEx(OS);

    res:=false;

    // from Microsoft Programmer's Guide to Win95:
    // "The GetVersionEx function fills the members of an OSVERSIONINFO data structure. If the dwPlatformId member of that structure
    // is VER_PLATFORM_WIN32_WINDOWS, and the low word of the dwBuildNumber member is greater than 1080, the system is running
    // Windows 95,OEM Service Release 2 or a later release of Windows 95."
    // if the there are problems with the following detection use above one...

    if os.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
    begin
      if (OS.dwMajorVersion >= 4) and (OS.dwMinorVersion>0) then res:=true
        else begin
          if (OS.dwMajorVersion=4) and (OS.dwMinorVersion=0) then
          begin
            if (Trim(OS.szCSDVersion)='B') then res:=true;
          end;
        end;
    end;

    result:=res;
  end;


  function IsWinNT: boolean;
  var
    info: TOSVersionInfo;
  begin
    IsWinNT:=false;
    info.dwOSVersionInfoSize:=sizeof(TOSVersionInfo);
    if GetVersionEx(info) then
    begin
      if info.dwPlatformId = VER_PLATFORM_WIN32_NT then IsWinNT:=true;
    end;
  end;


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

   Purpose:
      Reads sectors from a logical drive.  Uses Int 25h.

   Parameters:
      hDev
         Handle of VWIN32

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

      dwStartSector
         The first logical sector to read

      wSectors
         The number of sectors to read

      lpSectBuff
         The caller-supplied buffer that will contain the sector data

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

   Comments:
      This function does not validate its parameters.
   ------------------------------------------------------------------*)
   function ReadLogicalSectors (bDrive: BYTE; 
                                dwStartSector: LONGWORD;
                                wSectors: WORD;
                                lpSectBuff: pointer): BOOLEAN;
   var
      fResult:        BOOL;
      cb:             DWORD;
      reg:            DIOC_REGISTERS;
      dio:            DISKIO;

   begin
      if fWinNT then
      begin
        result:=NT_read( bDrive, dwStartSector, wSectors, lpSectBuff);
        exit;
      end;

      // CD-ROM (MSCDEX/CDFS) ?
      if IsCDROM( bDrive ) then
      begin
        result:=ReadCDROMSectors( bDrive, dwStartSector, wSectors, lpSectBuff, TRUE);
        exit;
      end;

      if optUseINT25 then
      begin
        // Windows 95 OEM Service Release 2 and later ?
        if fWin95OSR2orLater then
        begin
          result:=NewReadSectors( bDrive, dwStartSector, wSectors, lpSectBuff);
          exit;
        end;

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

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

        reg.reg_EAX := bDrive - 1;   // Int 25h drive numbers are 0-based.
        reg.reg_EBX := DWORD(@dio);
        reg.reg_ECX := $FFFF;        // use DISKIO struct

        fResult := DeviceIoControl(W95Handle, VWIN32_DIOC_DOS_INT25,
                                  @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 else result:=FALSE;
   end;


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

   Purpose:
      Writes sectors to a logical drive. Uses Int 26h

   Parameters:
      hDev
         Handle of VWIN32

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

      dwStartSector
         The first logical sector to write

      wSectors
         The number of sectors to write

      lpSectBuff
         The caller-supplied buffer that contains the sector data

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

   Comments:
      This function does not validate its parameters.
   ------------------------------------------------------------------*)
   function WriteLogicalSectors (bDrive: BYTE; 
                                  dwStartSector: LONGWORD;
                                  wSectors: WORD;
                                  lpSectBuff: pointer): BOOLEAN;
   var
     fResult: BOOL;
     cb     : DWORD;
     reg    : DIOC_REGISTERS;
     dio    : DISKIO;

   begin
      if fWinNT then
      begin
        result:=NT_write( bDrive, dwStartSector, wSectors, lpSectBuff);
        exit;
      end;

      if optUseINT25 then
      begin
        // Windows 95 OEM Service Release 2 and later ?
        if fWin95OSR2orLater then
        begin
          result:=NewWriteSectors(bDrive, dwStartSector, wSectors, lpSectBuff);
          exit;
        end;

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

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

        reg.reg_EAX := bDrive - 1;   // Int 26h drive numbers are 0-based.
        reg.reg_EBX := DWORD(@dio);
        reg.reg_ECX := $FFFF;        // use DISKIO struct

        fResult := DeviceIoControl(W95Handle, VWIN32_DIOC_DOS_INT26,
                                  @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 else result:=FALSE;
   end;


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

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

   Parameters:
     hDev
        Handle of VWIN32

⌨️ 快捷键说明

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