📄 pdiskio.pas
字号:
al, ah, al2, ah2: byte);
1: (
bx, bx2 : word;
dx, dx2 : word;
cx, cx2 : word;
ax, ax2 : word;
di, di2 : word;
si, si2 : word);
2: (
ebx: longword;
edx: longword;
ecx: longword;
eax: longword;
edi: longword;
esi: longword;
flags: longword);
end;
PDEVIOCTL_REGISTERS = ^DEVIOCTL_REGISTERS;
function DoINT13(preg: PDEVIOCTL_REGISTERS): boolean;
var
res: boolean;
cb: dword;
hDevice: thandle;
begin
res:=false;
preg.flags := CARRY_FLAG; { assume error (carry flag set) }
hDevice := CreateFile('\\.\vwin32',
GENERIC_READ, FILE_SHARE_READ OR FILE_SHARE_WRITE,
NIL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice <> INVALID_HANDLE_VALUE) then
begin
res:=DeviceIoControl(hDevice, VWIN32_DIOC_DOS_INT13,
preg, sizeof(DEVIOCTL_REGISTERS),
preg, sizeof(DEVIOCTL_REGISTERS), cb, nil);
CloseHandle(hDevice);
end;
DoINT13:=res;
end;
function INT13_reset(drv: byte): boolean;
var
r: DEVIOCTL_registers;
res: boolean;
begin
res:=false;
fillchar(r, sizeof(DEVIOCTL_REGISTERS), 0);
r.ah:=0;
r.dl:=drv;
res:=DoINT13(@r);
if res then
begin
res:=((r.flags and CARRY_FLAG) = 0);
end;
INT13_reset:=res;
end;
{ Get sector and cylinder number from combined sector/cylinder-code
(e.g. found in partition sector) }
procedure CnvSecCyl(SecCyl: word; var sector: byte; var cylinder: word);
begin
sector:=seccyl and 63;
cylinder:=hi(seccyl) + (lo(seccyl) and 192) shl 2;
end;
function INT13_GetDriveParams(drv: byte; params: PLegacyDriveParams): boolean;
var
r: DEVIOCTL_registers;
res: boolean;
cb: integer;
sec: byte;
cyl: word;
begin
res:=false;
fillchar(r, sizeof(DEVIOCTL_REGISTERS), 0);
r.ah:=8;
r.dl:=drv;
res:=DoINT13(@r);
if res then
begin
res:=((r.flags and CARRY_FLAG) = 0);
if res then
begin
CnvSecCyl(r.cx, sec, cyl);
params^.cylinders:=cyl+1;
params^.secpertrack:=sec;
params^.status:=r.ah;
params^.CMOS_DriveType:=r.bl;
params^.heads:=r.dh+1;
params^.drives:=r.dl;
end;
end;
INT13_GetDriveParams:=res;
end;
{ counterpart to CnvSecCyl }
procedure SetCnvSecCyl(sector, cylinder: word; var SecCyl: word);
begin
SecCyl:=WORD((LO(cylinder) SHL 8) OR ((HI(cylinder) AND 3) SHL 6) OR (sector AND 63));
end;
{ legacy read sector: returns number of sectors read }
function INT13_ReadSec(drv: byte; count: byte; cyl: word; sec: byte; head: byte; buf: pointer): byte;
var
r: DEVIOCTL_registers;
res: byte;
cb: integer;
SecCyl: word;
retry: byte;
begin
res:=0;
retry:=0;
repeat
SetCnvSecCyl(sec, cyl, SecCyl);
fillchar(r, sizeof(DEVIOCTL_REGISTERS), 0);
r.ah:=2;
r.al:=count;
r.cx:=SecCyl;
r.dh:=head;
r.dl:=drv;
r.ebx:=longword(@buf);
if (DoINT13(@r)) AND ((r.flags and CARRY_FLAG) = 0) then
begin
res:=r.al;
end;
inc(retry);
until (retry >= 3) OR (res > 0);
INT13_ReadSec:=res;
end;
// -----------------------------------------------------------------------------------
// INT13 Extensions...
// -----------------------------------------------------------------------------------
function CheckExtensions(drv: byte; var ver:byte; var subsets: word):Boolean;
var
res: boolean;
outbuf: array[0..3] of byte;
cb: dword;
begin
outbuf[0]:=0;
res:=DeviceIoControl(W95handle, DIOC_CHECKEXTENSIONS,
@drv, 1,
@outbuf, 1, cb, nil);
ver:=outbuf[1];
subsets:=(outbuf[2] SHL 8) OR outbuf[3];
CheckExtensions:=res AND (outbuf[0]=1);
end;
function ReadPhysicalSectors(drv: byte; LBA: longword; blocks: word; buf: pointer; ErrorDlg: boolean): boolean;
var
res: boolean;
struc: extstruc;
cb: dword;
tempbuf: array[0..511] of byte;
count: integer;
msgRes: integer;
begin
res:=FALSE;
if winNTflag then
res:=NT_Read(drv, LBA, blocks, buf, ErrorDlg)
else begin
if optUseINT13EXT then
begin
count:=0;
struc.Drv := drv;
struc.LBA := LBA;
struc.blocks := 1; //blocks;
struc.buf := {buf;} @tempbuf;
repeat
repeat
res:=DeviceIoControl(W95handle, DIOC_EXTENDEDREAD,
@struc, sizeof(extstruc),
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?'), 'ExtendedRead error', mb_applmodal or mb_iconwarning or mb_abortretryignore);
if msgRes = id_Retry then
begin
// try to reset controller...
INT13_reset(drv);
end;
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^, 512);
inc(longword(buf),512);
inc(count);
inc(struc.LBA);
until (NOT res) OR (count >= blocks);
end;
end;
result:=res;
end;
function WritePhysicalSectors(drv: byte; LBA: longword; blocks: word; buf: pointer;
verify: boolean; ErrorDlg: boolean): boolean;
var
res: boolean;
struc: extstruc;
cb: dword;
count: integer;
tempbuf: array[0..511] of byte;
msgRes: integer;
begin
res:=FALSE;
if winNTflag then
res:=NT_Write(drv, LBA, blocks, buf, ErrorDlg)
else begin
if optUseINT13EXT then
begin
count:=0;
struc.Drv := drv;
struc.LBA := LBA;
struc.blocks := 1; //blocks;
struc.buf := @tempbuf; //buf;
struc.verify := byte(verify);
repeat
move(buf^, tempbuf, 512);
repeat
res:=DeviceIoControl(W95handle, DIOC_EXTENDEDWRITE,
@struc, sizeof(extstruc),
nil, 0, cb, nil);
msgRes := id_abort;
if (NOT res) AND (ErrorDlg) then
begin
msgRes:=messagebox(0, pchar('Error writing sector, '+#13#10+'drv:'+inttostr(drv)+' LBA:'+inttostr(LBA)
+' blocks:'+inttostr(blocks) +#13#10#13#10
+' Abort, Retry or Ignore?'), 'ExtendedWrite 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),512);
inc(struc.LBA);
inc(count);
until (NOT res) OR (count >= blocks);
end;
end;
result:=res;
end;
function GetPhysDriveParams(drv: byte; resultbuf: PPhysDriveParams): boolean;
var
res: boolean;
struc: extstruc;
cb: dword;
dg: TDisk_Geometry;
ver: byte;
subsets: word;
legacy: TLegacyDriveParams;
dp: TDriveParams;
begin
res:=false;
if WinNTflag then
begin
// Windows NT...
res:=NT_GetDriveGeometry(drv, @dg);
if res then
begin
resultbuf^.MediaAttr:=0;
resultbuf^.Heads:=dg.cylinders.lowpart;
resultbuf^.TracksPerHead:=dg.trackspercylinder;
resultbuf^.SectorsPerTrack:=dg.sectorspertrack;
resultbuf.BytesPerSector:=dg.bytespersector;
resultbuf^.TotalPhysSec:=dg.cylinders.lowpart * dg.TracksPerCylinder * dg.SectorsPerTrack;
case dg.MediaType of
0: resultbuf^.MediaType:=PMEDIA_TYPE_UNKNOWN;
1..10, 13..22: begin
resultbuf^.MediaType:=PMEDIA_TYPE_FLOPPY;
resultbuf^.MediaAttr:=PMEDIA_ATTR_REMOVABLE;
end;
11: begin
resultbuf^.MediaType:=PMEDIA_TYPE_REMOVABLE;
resultbuf^.MediaAttr:=PMEDIA_ATTR_REMOVABLE;
end;
12: resultbuf^.MediaType:=PMEDIA_TYPE_FIXED;
end;
end;
end else
begin
// Windows 9X...
//INT13_reset(drv);
if drv < $80 then
begin
if OptUseINT13 then
begin
// legacy INT13...
res:=INT13_GetDriveParams(drv, @legacy);
if (res) AND (legacy.secpertrack = 0) then res:=false;
if (res) then
begin
if drv IN [0,1] then resultbuf^.MediaType:=PMEDIA_TYPE_FLOPPY
else resultbuf^.MediaType:=PMEDIA_TYPE_REMOVABLE; // ??
resultbuf^.MediaAttr:=PMEDIA_ATTR_REMOVABLE;
resultbuf^.Heads:=legacy.heads;
resultbuf^.TracksPerHead:=legacy.cylinders;
resultbuf^.SectorsPerTrack:=legacy.secpertrack;
resultbuf^.BytesPerSector:=512;
resultbuf^.TotalPhysSec:=legacy.cylinders * legacy.heads * legacy.secpertrack;
end;
end;
end else
begin
if OptUseINT13EXT then
begin
// INT13 Extensions...
struc.Drv := drv;
struc.buf := @dp;
dp.bufsize:=30;
res:=DeviceIoControl(W95handle, DIOC_GETDRIVEPARAMS,
@struc, sizeof(extstruc),
nil, 0, cb, nil);
if res then
begin
resultbuf^.MediaAttr:=0;
if (dp.infoflags AND IFLAG_REMOVABLE) <> 0 then
begin
resultbuf^.MediaType:=PMEDIA_TYPE_REMOVABLE;
resultbuf^.MediaAttr:=PMEDIA_ATTR_REMOVABLE;
end else resultbuf^.MediaType:=PMEDIA_TYPE_FIXED;
resultbuf^.Heads:=dp.physheads;
resultbuf^.TracksPerHead:=dp.physcyl;
resultbuf^.SectorsPerTrack:=dp.physsecptrk;
resultbuf^.BytesPerSector:=dp.bytesPerSec;
resultbuf^.TotalPhysSec:=dp.physsecLO;
end;
end;
end;
end;
result:=res;
end;
// -----------------------------------------------------------------------------------
// Main...
// -----------------------------------------------------------------------------------
procedure MyExit;
begin
ExitProc := ExitSave; { first restore old vector }
if NOT (winNTflag) then
begin
// Win9X...
if (W95handle <> INVALID_HANDLE_VALUE) then
begin
// CloseHandle(hDevice);
DeleteFile('\\.\INT13EXT');
end;
end else
begin
// WinNT...
if (NThandle <> INVALID_HANDLE_VALUE) then CloseHandle(NThandle);
end;
end;
begin
OptUseINT13:=TRUE;
OptUseINT13EXT:=TRUE;
W95handle:=INVALID_HANDLE_VALUE;
NThandle:=INVALID_HANDLE_VALUE;
winNTflag:=IsWinNT;
ExitSave := ExitProc;
ExitProc := @MyExit;
if NOT winNTflag then
begin
W95handle:=CreateFile('\\.\INT13EXT.VXD', 0, 0, nil, 0,
FILE_FLAG_DELETE_ON_CLOSE, 0);
if W95handle = INVALID_HANDLE_VALUE then
begin
MessageBox(0, 'Error loading "INT13EXT.VXD"', 'Error', mb_IconExclamation + mb_ok);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -