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

📄 diskio.pas

📁 === === === MiniHex 1.61 源程序说明 ============================== “$(MiniHex)Source”目录中的所有
💻 PAS
字号:
unit DiskIO;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;

const
  BytesPerSector = 512;
  
type

{ TDiskIO }

  TDiskIO = class(TObject)
  public
    function ReadLogicalSector(Drive: Char; SectorStart, SectorCount: Longint;
      DataStream: TMemoryStream): Boolean; virtual; abstract;
    function WriteLogicalSector(Drive: Char; SectorStart, SectorCount: Longint;
      DataStream: TMemoryStream): Boolean; virtual; abstract;
  end;

{ TWin9xDiskIO }

  TWin9xDiskIO = class(TDiskIO)
  public
    function ReadLogicalSector(Drive: Char; SectorStart, SectorCount: Longint;
      DataStream: TMemoryStream): Boolean; override;
    function WriteLogicalSector(Drive: Char; SectorStart, SectorCount: Longint;
      DataStream: TMemoryStream): Boolean; override;
  end;

{ TWinNTDiskIO }

  TWinNTDiskIO = class(TDiskIO)
  public
    function ReadLogicalSector(Drive: Char; SectorStart, SectorCount: Longint;
      DataStream: TMemoryStream): Boolean; override;
    function WriteLogicalSector(Drive: Char; SectorStart, SectorCount: Longint;
      DataStream: TMemoryStream): Boolean; override;
  end;

var
  DiskIOObject: TDiskIO;

implementation

uses WinVer;

{ TWin9xDiskIO }

const
  FILE_FLAG_DELETE_ON_CLOSE = $04000000;
  VWIN32_DIOC_DOS_IOCTL = 1; { MS-DOS Int 21h 44xxh functions call }
  VWIN32_DIOC_DOS_INT25 = 2; { MS-DOS Int 25h function call }
  VWIN32_DIOC_DOS_INT26 = 3; { MS-DOS Int 26h function call }
  VWIN32_DIOC_DOS_INT13 = 4; { MS-DOS Int 13h functions call }
  VWIN32_DIOC_DOS_DRIVEINFO = 6; {MS-DOS Int 21h function 730X}

type
  TDiskIORec = packed Record
    dwStartSector: Longint;
    wSectors: Smallint;
    lpBuffer: PChar;
  end;

  P32Regs = ^T32Regs; //32位寄存器结构
  T32Regs = record
    EBX: Longint;
    EDX: Longint;
    ECX: Longint;
    EAX: Longint;
    EDI: Longint;
    ESI: Longint;
    Flags: Longint;
  end;

function LockDisk(VMM32Handle: Cardinal; Disk: Byte; LockOrNot: Boolean): Boolean;
var
  R: T32Regs;
  cb: DWord;
begin
  if VMM32Handle = INVALID_HANDLE_VALUE then
  begin
    Result := False;
    Exit;
  end;
  FillChar(R, SizeOf(R), 0);
  if LockOrNot then
  begin
    R.ECX := $084b;
    R.EBX := $100 + Disk; //bh:0-3级  0,1,$80,$81...
    R.EDX := 1;           //1允许写,0允许格式化
  end else
  begin
    R.ECX := $086b;
    R.EBX := Disk;        //0,1,$80,$81...
  end;
  R.EAX := $440D;
  DeviceiOControl(VMM32Handle, VWIN32_DIOC_DOS_IOCTL, @R, SizeOf(R), @R, SizeOf(R), cb, nil);
  Result := (R.Flags and 1 = 0);
end;

function LockDrive(VMM32Handle: Cardinal; Drive: Byte; LockOrNot: Boolean): Boolean;
var
  R: T32Regs;
  cb: DWord;
begin
  if VMM32Handle = INVALID_HANDLE_VALUE then
  begin
    Result := False;
    Exit;
  end;
  FillChar(R, SizeOf(R), 0);
  if LockOrNot then
  begin
     R.ECX := $084a;
     R.EBX := $100 + drive; //bh:0-4级  0当前盘,1:A,2:B,3:C
     R.EDX := 1;            //1允许写,0允许格式化
  end
  else begin
     R.ECX := $086A;
     R.EBX := Drive;        //0当前盘,1:A,2:B,3:C
  end;
  R.EAX := $440D;
  DeviceiOControl(VMM32Handle, VWIN32_DIOC_DOS_IOCTL, @R, SizeOf(R), @R, SizeOf(R), cb, nil);
  Result := (R.Flags and 1 = 0); //and (R.EAX and $FFFF = 0);
end;
  
function TWin9xDiskIO.ReadLogicalSector(Drive: Char;
  SectorStart, SectorCount: Integer; DataStream: TMemoryStream): Boolean;
var
  cb: DWord;
  DriveNo: integer;
  DiskIORec: TDiskIORec;
  Reg: T32Regs;
  DeviceHandle: THandle;
begin
  Result := False;
  DriveNo := Ord(UpCase(Drive)) - Ord('A') + 1; 
  DeviceHandle := CreateFile('\\.\VWIN32', 0, 0, nil, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
  if DeviceHandle <> INVALID_HANDLE_VALUE then
  begin
    DataStream.Clear;
    DataStream.SetSize(SectorCount * BytesPerSector);

    DiskIORec.dwStartSector := SectorStart;
    DiskIORec.wSectors := SectorCount;
    DiskIORec.lpBuffer := DataStream.Memory;

    Reg.EAX := $7305;
    Reg.EBX := Integer(@DiskIORec);
    Reg.ECX := -1;
    Reg.EDX := DriveNo;  //1-A 2-B 3-C
    Reg.ESI := 0;        //读
    Reg.Flags := 0;

    DeviceIoControl(DeviceHandle, VWIN32_DIOC_DOS_DRIVEINFO, @Reg, SizeOf(Reg), @Reg, SizeOf(Reg), cb, nil);
    Result := (Reg.Flags and 1) <> 1;
  end;
end;

function TWin9xDiskIO.WriteLogicalSector(Drive: Char;
  SectorStart, SectorCount: Integer; DataStream: TMemoryStream): Boolean;
var
  cb: DWord;
  DriveNo: integer;
  DiskIORec: TDiskIORec;
  Reg: T32Regs;
  DeviceHandle: THandle;
begin
  Result := False;
  DriveNo := Ord(UpCase(Drive)) - Ord('A') + 1; 
  DeviceHandle := CreateFile('\\.\VWIN32', 0, 0, nil, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
  if DeviceHandle <> INVALID_HANDLE_VALUE then
  begin
    DataStream.Clear;
    DataStream.SetSize(SectorCount * BytesPerSector);

    LockDrive(DeviceHandle, DriveNo, True);

    DiskIORec.dwStartSector := SectorStart;
    DiskIORec.wSectors := SectorCount;
    DiskIORec.lpBuffer := DataStream.Memory;

    Reg.EAX := $7305;
    Reg.EBX := Integer(@DiskIORec);
    Reg.ECX := -1;
    Reg.EDX := DriveNo;  //1-A 2-B 3-C
    Reg.ESI := 1;        //写
    Reg.Flags := 0;
    DeviceIoControl(DeviceHandle, VWIN32_DIOC_DOS_DRIVEINFO, @Reg, SizeOf(Reg), @Reg, SizeOf(Reg), cb, nil);
    Result := (Reg.Flags and 1) <> 1;

    LockDrive(DeviceHandle, DriveNo, False);
  end;
end;

{ TWinNTDiskIO }

function TWinNTDiskIO.ReadLogicalSector(Drive: Char;
  SectorStart, SectorCount: Integer; DataStream: TMemoryStream): Boolean;
var
  I: Integer;
  DriveStr: string;
  DeviceHandle: THandle;
begin
  Result := False;
  DriveStr := Format('\\.\%s:', [Drive]);
  DeviceHandle := CreateFile(PChar(DriveStr), GENERIC_READ,
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  if (DeviceHandle <> INVALID_HANDLE_VALUE) then
  begin
    DataStream.Clear;
    DataStream.SetSize(SectorCount * BytesPerSector);

    FileSeek(DeviceHandle, SectorStart * BytesPerSector, 0);
    I := FileRead(DeviceHandle, DataStream.Memory^, SectorCount*BytesPerSector);
    Result := (I = SectorCount*BytesPerSector);

    CloseHandle(DeviceHandle);
  end;
end;

function TWinNTDiskIO.WriteLogicalSector(Drive: Char;
  SectorStart, SectorCount: Integer; DataStream: TMemoryStream): Boolean;
var
  I: Integer;
  DriveStr: string;
  DeviceHandle: THandle;
begin
  Result := False;
  DriveStr := Format('\\.\%s:', [Drive]);
  DeviceHandle := CreateFile(PChar(DriveStr), GENERIC_ALL, 
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  if (DeviceHandle <> INVALID_HANDLE_VALUE) then
  begin
    DataStream.Clear;
    DataStream.SetSize(SectorCount * BytesPerSector);

    FileSeek(DeviceHandle, SectorStart * BytesPerSector, 0);
    I := FileWrite(DeviceHandle, DataStream.Memory^, SectorCount*BytesPerSector);
    Result := (I = SectorCount*BytesPerSector);

    CloseHandle(DeviceHandle);
  end;
end;

initialization
  if WinVersion in [wvWinNT, wvWin2000, wvWinXP] then
    DiskIOObject := TWinNTDiskIO.Create
  else
    DiskIOObject := TWin9xDiskIO.Create;

end.

⌨️ 快捷键说明

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