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

📄 pdiskio.pas

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

  Contact: alexander_grau@web.de

}

unit pdiskio;

interface

const
  { Media types }
  PMEDIA_TYPE_UNKNOWN   = 0;
  PMEDIA_TYPE_FLOPPY    = 1;
  PMEDIA_TYPE_REMOVABLE = 2;
  PMEDIA_TYPE_FIXED     = 3;

  { Media attributes }
  PMEDIA_ATTR_REMOVABLE = 1;

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


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

(* drv: the INT13 drive,   0=first floppy
                           1=second floppy
                           ...
                         80h=first fixed/removable disk
                         81h=second fixed/removable disk
                           ... *)

function ReadPhysicalSectors(drv: byte; LBA: longword; blocks: word; buf: pointer; ErrorDlg: boolean): boolean;
function WritePhysicalSectors(drv: byte; LBA: longword; blocks: word; buf: pointer;
  verify: boolean; ErrorDlg: boolean): boolean;
function GetPhysDriveParams(drv: byte; resultbuf: PPhysDriveParams): boolean;

var
  OptUseINT13: boolean;
  OptUseINT13EXT: boolean;

implementation

uses sysutils, windows, helpers;


// --------------- INT13 Extensions specific... ----------------------------------------------------
const
  IFLAG_HANDLES_DMA_BOUNDARY = 1;
  IFLAG_GEOMETRY_VALID       = 2;
  IFLAG_REMOVABLE            = 4;
  IFLAG_VERIFY_SUPPORT       = 8;
  IFLAG_CHANGE_LINE_SUPPORT  = 16;
  IFLAG_IS_LOCKABLE          = 32;
  IFLAG_NO_MEDIA_PRESENT     = 64;

type
  PDriveParams = ^TDriveParams;
  TDriveParams = packed record { used by GetDriveParams }
     bufsize    : word;
     infoflags  : word;
     physcyl    : longword;
     physheads  : longword;
     physsecptrk: longword;
     physsecLO  : longword;
     physsecHI  : longword;
     bytesPerSec: word;
     EDDptr     : pointer;
    { DevPathInfoFlag: word;
     DevPathInfoLen : byte;
     res0           : byte;
     res1           : word;
     HostBusType    : array[0..3] of char;
     InterfaceType  : array[0..7] of char;
     InterfacePath  : Qword;
     DevicePath     : Qword;
     res2           : byte;
     DevPathInfoChksum: byte; }
  end;


  // --------- Windows NT specific... -------------------------------------------------------------

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) );

  (*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;


  // ------ INT13EXT.VXD specific... ------------------------------------------------
const
    DIOC_CHECKEXTENSIONS = 1;
    DIOC_EXTENDEDREAD    = 2;
    DIOC_EXTENDEDWRITE   = 3;
    DIOC_GETDRIVEPARAMS  = 4;


type
    extstruc = 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;
      verify: byte;
    end;


  // --------------------------------------------------------------------------------
const
  TEMPSECTORS = 128;

var
  W95Handle:   thandle;    // Win9X/ME only: current handle
  NTHandle:    thandle;    // WinNT only: current handle
  NTDrive:     byte;       // WinNT only: drive currently opened

  ExitSave: Pointer;
  winNTflag: boolean;
  i: integer;
  disk_geometry: tdisk_geometry;
  tempbuf: array[0..512*TEMPSECTORS-1] of byte;



  
// -----------------------------------------------------------------------------------
//     Windows NT specific...
// -----------------------------------------------------------------------------------


function NT_changedrive(drv: byte; ReadOnly: boolean): boolean;
var
  hDevice: thandle;
begin
  if NThandle <> INVALID_HANDLE_VALUE then
  begin
    if NTdrive = drv then
    begin
      result:=true;
      exit;
    end else
    begin
      CloseHandle(NThandle);
    end;
  end;

  { handle drive numbers like INT13 Extensions! 0..$7f are removable, $80 and above are fixed }

  if drv IN [0..$7f] then
  begin
    if (drv IN [0..1]) then
    begin
      if ReadOnly then
        hDevice := CreateFile(pchar('\\.\'+chr(ord('A')+drv)+':'), GENERIC_READ, FILE_SHARE_READ OR FILE_SHARE_WRITE,
          nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0)
      else
        hDevice := CreateFile(pchar('\\.\'+chr(ord('A')+drv)+':'), GENERIC_WRITE, FILE_SHARE_WRITE,
          nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0)
    end;
  end
  else begin
    if ReadOnly then
      hDevice:=CreateFile(pchar('\\.\PhysicalDrive'+inttostr(drv-$80)), GENERIC_READ, FILE_SHARE_READ OR FILE_SHARE_WRITE,
        nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0)
    else
      hDevice:=CreateFile(pchar('\\.\PhysicalDrive'+inttostr(drv-$80)), GENERIC_WRITE, FILE_SHARE_WRITE,
        nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0);
  end;

  NThandle:=hDevice;
  NTdrive:=drv;
  result:=(hDevice <> INVALID_HANDLE_VALUE);
end;


function NT_CheckMedia(hDev: thandle): boolean;
var
  cb: DWORD;
begin
  cb:=0;
  result := DeviceIoControl(hDev,
        IOCTL_STORAGE_CHECK_VERIFY, nil, 0,
        nil, 0, cb, nil);
  // here's something wrong with floppy disks...
  result:=true;
end;

function NT_GetDriveGeometry(drv: byte; dg: PDISK_GEOMETRY): boolean;
var
  hDevice: thandle;
  fResult: boolean;
  cb: DWORD;
begin
    fResult:=false; hDevice:=INVALID_HANDLE_VALUE;

    { handle drive numbers like INT13 Extensions! 0..$7f are removable, $80 and above are fixed }
    if drv IN [0..$7f] then
    begin
      if (drv IN [0..1]) then
      hDevice := CreateFile(pchar('\\.\'+chr(ord('A')+drv)+':'),
        0, FILE_SHARE_READ OR FILE_SHARE_WRITE,
        nil, OPEN_EXISTING, 0, 0);
      if (hDevice <> INVALID_HANDLE_VALUE) then
      begin
        if NOT (NT_CheckMedia(hDevice)) then
        begin
          CloseHandle(hDevice);
          hDevice:=INVALID_HANDLE_VALUE;
        end;
      end;
    end
    else
      hDevice := CreateFile(pchar('\\.\PhysicalDrive'+inttostr(drv-$80)),
        0, FILE_SHARE_READ OR FILE_SHARE_WRITE,
        nil, OPEN_EXISTING, 0, 0);

    if (hDevice <> INVALID_HANDLE_VALUE) then
    begin
      fResult := DeviceIoControl(hDevice,
        IOCTL_DISK_GET_DRIVE_GEOMETRY, nil, 0,
        dg, sizeof(TDISK_GEOMETRY), cb, nil);
      CloseHandle(hDevice);
    end;

    NT_GetDriveGeometry:=fResult;
end;


function NT_Read(drv: byte; LBA: longword; blocks: word; buf: pointer; ErrorDlg: boolean): boolean;
var
  res: boolean;
  bytestoread, numread, transfer: longword;
  err: dword;
  i: integer;
  dwpointer: dword;
  ldistancelow, ldistancehigh: dword;
  msgRes: integer;
begin
  res:=false;
  if NT_changedrive(drv, true) then
  begin
    ldistanceLow:=dword(LBA SHL 9);
    ldistanceHigh:=dword(LBA SHR (32-9));
    dwpointer:=SetFilePointer(NThandle, ldistancelow, @ldistancehigh, FILE_BEGIN);
    if dwPointer <> $FFFFFFFF then
    begin
      bytestoread:=blocks*512;
      repeat
        transfer:=bytestoread;
        if (transfer > TEMPSECTORS * 512) then transfer:=TEMPSECTORS * 512;
        repeat
          res:=ReadFile(NThandle, tempbuf, transfer, numread, nil);
          if res then res:=boolean(numread=transfer);
          msgRes := id_abort;
          if (NOT res) AND (ErrorDlg) then
          begin
            err:=GetLastError;
            msgRes:=messagebox(0, pchar('error no.'+inttostr(err)+#13#10+'drv:'+inttostr(drv)+' LBA:'+inttostr(LBA)
              +' blocks:'+inttostr(blocks)+#13#10#13#10
              +'Abort, Retry or Ignore?'), 'NT_read error', 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^, transfer);
        inc(longword(buf),transfer);
        dec(bytestoread, transfer);
      until (NOT res) OR (bytestoread = 0);
    end;
  end;
  NT_Read:=(res); // AND (numread=blocks*512);
end;


function NT_Write(drv: byte; LBA: longword; blocks: word; buf: pointer; ErrorDlg: boolean): boolean;
var
  res: boolean;
  bytestowrite, numwritten, transfer: longword;
  err: dword;
  i: integer;
  bufp: ^byte;
  dwpointer: dword;
  ldistancelow, ldistancehigh: dword;
  msgRes: integer;
begin
  res:=false;
  if NT_changedrive(drv, false) then
  begin
    ldistanceLow:=dword(LBA SHL 9);
    ldistanceHigh:=dword(LBA SHR (32-9));
    dwpointer:=SetFilePointer(NThandle, ldistancelow, @ldistancehigh, FILE_BEGIN);
    if dwPointer <> $FFFFFFFF then
    begin
      bytestowrite:=blocks*512;
      repeat
        transfer:=bytestowrite;
        if (transfer > TEMPSECTORS * 512) then transfer:=TEMPSECTORS * 512;
        move(buf^, tempbuf, transfer);
        repeat
          res:=WriteFile(NThandle, tempbuf, transfer, numwritten, nil);
          if res then res:=boolean(numwritten=transfer);
          msgRes := id_abort;
          if (NOT res) AND (ErrorDlg) then
          begin
            err:=GetLastError;
            msgRes:=messagebox(0, pchar('error no.'+inttostr(err)+#13#10+'drv:'+inttostr(drv)+' LBA:'+inttostr(LBA)
              +' blocks:'+inttostr(blocks)+#13#10#13#10
              +'Abort, Retry or Ignore?'), 'NT_write error',  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;
        inc(longword(buf),transfer);
        dec(bytestowrite, transfer);
      until (NOT res) OR (bytestowrite = 0);
    end;
  end;
  NT_write:=(res); // AND (numread=blocks*512);
end;


// -----------------------------------------------------------------------------------
//     legacy INT13 functions...
// -----------------------------------------------------------------------------------

const
  VWIN32_DIOC_DOS_IOCTL = 1;
  VWIN32_DIOC_DOS_INT13 = 4;

  CARRY_FLAG            = $0001; // Intel x86 processor status flags

type
  PLegacyDriveParams = ^TLegacyDriveParams;
  TLegacyDriveParams = record
    status         : byte;
    CMOS_DriveType : byte;
    cylinders      : word;
    secpertrack    : byte;
    heads          : byte;
    drives         : byte;
  end;


  DEVIOCTL_REGISTERS=record
    case Integer of
    0: (
      bl, bh, bl2, bh2: byte;
      dl, dh, dl2, dh2: byte;
      cl, ch, cl2, ch2: byte;

⌨️ 快捷键说明

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