{$A-} unit Dskio;interfaceuses Windows, Messages, Classes, SysUtils, Forms, D_IOCTL;const {FAT values explanations} FAT_Available = 0; FAT_Reserved_Min = $FFFFFFF0; FAT_Reserved_Max = $FFFFFFF6; FAT_BAD = $FFFFFFF7; FAT_EOF_Min = $FFFFFFF8; FAT_EOF_Max = $FFFFFFFF; {FAT values masks for different file systems} FAT_MASK_12 = $FFF; FAT_MASK_16 = $FFFF; FAT_MASK_32 = $FFFFFFF; {Attribute field bits meanings} ATTR_ARCHIVE = $20; ATTR_DIRECTORY = $10; ATTR_VOLUME = $08; ATTR_SYSTEM = $04; ATTR_HIDDEN = $02; ATTR_READONLY = $01;type {File system used type on selected volume} TFileSystem = (fsNone, fsFAT12, fsFAT16, fsFAT32); {Universal directory entry - valid on all file systems} PDIR_Entry = ^TDIR_Entry; TDIR_Entry = record Attributes: Byte; // File attributes StartCluster: Longint; // File starting cluster CreateTime: Longint; // File creation time CreateDate: Longint; // File creation date FileSize: Longint; // File size LastAccessDate: Longint; // File last access date Name: String[255]; // DOS 8.3 filename as DOS reports LongName: String[255]; // Windows 95 long filename // if '' then no long filename available Erased: Boolean; // True for erased file entry end; TDiskIO = class private FHandle: THandle; FVolume: Longint; FPhysicalVolume: Longint; FLogicalSectors: Longint; FPhysicalSectors: Longint; FHeads: Longint; FCylinders: Longint; FBytesPerSector: Longint; FSectorsPerCluster: Longint; FFATSector: Pointer; FFATCount: Longint; FRootDirSector: Longint; FRootDirCluster: Longint; FFileSystem: TFileSystem; FSectorsPerFAT: Longint; FRootDirEntries: Longint; FCluster2Sector: Longint; FFATSize: Longint; FFAT: Pointer; FEndingCluster: Longint; FSerial: Longint; FLabel: String; procedure IOCTL(Command: Longint; var Regs: T32Regs); function ObtainVolumeLock(Level: Byte; Lock: TLockType): Boolean; procedure ReleaseVolumeLock(Lock: TLockType); function VolumeLock(Lock: TLockType): Boolean; procedure VolumeUnlock(Lock: TLockType); function GetDrive: Char; procedure SetDrive(Value: Char); procedure CheckFileSystem; function WriteLogicalSectorEx(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean; function ReadLogicalSectorEx(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean; function GetFATCluster(FATIndex: Longint): Longint; function GetFATEntry(CopyOfFAT: Longint; Cluster: Longint): Longint; procedure SetFATEntry(CopyOfFAT: Longint; Cluster: Longint; Value: Longint); function VolumeCheck(var Flags: Longint): Boolean; function GetMediaID(MID: PMID): Boolean; function ReadRootDIR(var DIR: PDIR_Entry; var Entries: Longint): Boolean; function ReadOtherDir(Cluster: Longint; var DIR: PDIR_Entry; var Entries: Longint): Boolean; public constructor Create; virtual; destructor Destroy; override; function ValidCluster(Cluster: Longint): Boolean; // Check cluster for bounds validation function ReadLogicalSector(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean; // Reads nSectors from disk into Buffer of size nSize startin at StartSector number function WriteLogicalSector(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean; // Writes nSectors to disk from Buffer of size nSize startin at StartSector number procedure FlushFAT; // Flushes internal memory FAT image to disk procedure DriveReread; // Rescans drive (usually used after changes made) function ReadCluster(Cluster: Longint; var Buffer; BufferSize: Longint): Boolean; // Reads cluster number Cluster into Buffer of size BufferSize function WriteCluster(Cluster: Longint; var Buffer; BufferSize: Longint): Boolean; // Writes cluster number Cluster to disk from Buffer of size BufferSize function ReadClusterChain(StartCluster: Longint; var Buffer: Pointer; var BufferSize: Longint): Boolean; // Reads total cluster chain starting from StartCluster into Buffer returning size of buffer BufferSize function WriteClusterChain(StartCluster: Longint; Buffer: Pointer; BufferSize: Longint): Boolean; // Writes total cluster chain starting from StartCluster from Buffer of size BufferSize function SeekForChainStart(Cluster: Longint): Longint; // Seeks for starting chain cluster number, Cluster represents any mid cluster of a chain function DIRPath(Path: String; var DIR: PDIR_Entry; var Entries: Longint): Boolean; // Returns all directory entries of a path Path including deleted entries into // DIR as a pointer to TDIR_Entry array returning amount of Entries found function ExtractDIREntry(Path: String; var DIR: TDIR_Entry): Boolean; // Gets DIR entry of a Path (or file as Path) specified property Drive: Char read GetDrive write SetDrive; // Assign drive letter for class property LogicalSectors: Longint read FLogicalSectors; // Amount of Logical sectors on selected drive property PhysicalSectors: Longint read FPhysicalSectors; // Amount of Physical sectors on selected drive property Heads: Longint read FHeads; // Amount of heads on selected drive property Cylinders: Longint read FCylinders; // Amount of Cylinders on selected drive property BytesPerSector: Longint read FBytesPerSector; // Amount of Bytes per sector on selected drive property PhysicalDrive: Longint read FPhysicalVolume; // Physical drive number property SectorsPerCluster: Longint read FSectorsPerCluster; // Amount of sectors per cluster on selected drive property SectorsPerFAT: Longint read FSectorsPerFAT; // Amount of sectors per FAT on selected drive property FATSector[FATIndex: Longint]: Longint read GetFATCluster; // Returns first sector number of a FAT copy FATIndex property FATCount: Longint read FFATCount; // Amount of FAT copies property RootDirCluster: Longint read FRootDirCluster; // First cluster number of a Root dir (has meaning only for FAT32) property RootDirSector: Longint read FRootDirSector; // First sector number of a Root dir property RootDirEntries: Longint read FRootDirEntries; // Amount of a Root dir entries for a drive (non FAT32 only) property Cluster2Sector: Longint read FCluster2Sector; // Gives exact Sector number of Cluster number 2 (data start for non FAT32 drives) property EndingCluster: Longint read FEndingCluster; // Maximum FAT number for a drive property FATEntry[CopyOfFAT, Cluster: Longint]: Longint read GetFATEntry write SetFATEntry; // Gets or sets FAT Entry for cluster Cluster and for FAT copy CopyOfFAT property Serial: Longint read FSerial; // Gets volume serial number property VolumeLabel: String read FLabel; // Shows volume label property FileSystem: TFileSystem read FFileSystem; // What kind of FAT system is used for a drive end;procedure ParseDOSDate(Date: Word; var Day, Month, Year: Word); // Use this function to get Day, Month and Year of a Date fields in Dir_Entryprocedure ParseDOSTime(Time: Word; var Hour, Minute, Second: Word); // Use this function to get Hour, Minute and Second of a Time fields in Dir_Entry
procedure ParseDOSTime(Time: Word; var Hour, Minute, Second: Word); begin Second := (Time and $001f)*2; Minute := (Time and $07e0) shr 5; Hour := (Time and $f800) shr 11; end;procedure ParseDOSDate(Date: Word; var Day, Month, Year: Word); begin Day := Date and $001f; Month := (Date and $01e0) shr 5; Year := (Date and $fe00) shr 9; end;function TDiskIO.GetFATCluster(FATIndex: Longint): Longint; begin Result := 0; if FFATCount=0 then Exit; if FATIndex<1 then FATIndex := 1; if FATIndex>FFATCount then FATIndex := FFATCount; Result := Longint(Pointer(Longint(FFATSector)+(FATIndex-1)*4)^); end;procedure TDiskIO.IOCTL(Command: Longint; var Regs: T32Regs); var R: T32Regs; cb: DWord; begin if FHandle = 0 then Exit; R := Regs; DeviceIOControl(FHandle, Command, @R, SizeOf(R), @R, SizeOf(R), cb, NIL); Regs := R; end;function TDiskIO.ObtainVolumeLock(Level: Byte; Lock: TLockType): Boolean; var R: T32Regs; cb: DWord; W: Longint; V: Byte; begin W := Level; W := W shl 8; if Lock = lPhysical then begin V := FPhysicalVolume; R.EAX := $440D; R.EBX := W or V; R.ECX := $084B; if Level = 1 then R.EDX := 1 else R.EDX := 0; DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL, @R, SizeOf(R), @R, SizeOf(R), cb, NIL); Result := (R.Flags and 1)=0; end else begin R.EAX := $440D; R.EBX := W or (FVolume and $FF); R.ECX := $084A; R.EDX := 0; DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL, @R, SizeOf(R), @R, SizeOf(R), cb, NIL); Result := (R.Flags and 1)=0; end; end;procedure TDiskIO.ReleaseVolumeLock(Lock: TLockType); var R: T32Regs; cb: DWord; V: Byte; begin if Lock = lPhysical then begin V := FPhysicalVolume; R.EAX := $440D; R.EBX := V; R.ECX := $086B; DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL, @R, SizeOf(R), @R, SizeOf(R), cb, NIL); end else begin R.EAX := $440D; R.EBX := FVolume and $FF; R.ECX := $086A; DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL, @R, SizeOf(R), @R, SizeOf(R), cb, NIL); end; end;function TDiskIO.VolumeLock(Lock: TLockType): Boolean; begin Result := False; if FHandle = 0 then Exit; if FVolume = 0 then Exit; if Lock = lPhysical then if FPhysicalVolume = -1 then Exit; Result := ObtainVolumeLock(1, Lock); if not Result then Exit; Result := ObtainVolumeLock(2, Lock); if not Result then begin ReleaseVolumeLock(Lock); Exit; end; Result := ObtainVolumeLock(3, Lock); if not Result then begin ReleaseVolumeLock(Lock); ReleaseVolumeLock(Lock); Exit; end; end;
to huanzhugege(中国人) delphi6.0里没有D_IOCTL单元啊,是第三方的吧,那里有得down。 在此先谢了。
unit Dskio;interfaceuses Windows, Messages, Classes, SysUtils, Forms, D_IOCTL;const
{FAT values explanations}
FAT_Available = 0;
FAT_Reserved_Min = $FFFFFFF0;
FAT_Reserved_Max = $FFFFFFF6;
FAT_BAD = $FFFFFFF7;
FAT_EOF_Min = $FFFFFFF8;
FAT_EOF_Max = $FFFFFFFF; {FAT values masks for different file systems}
FAT_MASK_12 = $FFF;
FAT_MASK_16 = $FFFF;
FAT_MASK_32 = $FFFFFFF; {Attribute field bits meanings}
ATTR_ARCHIVE = $20;
ATTR_DIRECTORY = $10;
ATTR_VOLUME = $08;
ATTR_SYSTEM = $04;
ATTR_HIDDEN = $02;
ATTR_READONLY = $01;type
{File system used type on selected volume}
TFileSystem = (fsNone, fsFAT12, fsFAT16, fsFAT32); {Universal directory entry - valid on all file systems}
PDIR_Entry = ^TDIR_Entry;
TDIR_Entry = record
Attributes: Byte; // File attributes
StartCluster: Longint; // File starting cluster
CreateTime: Longint; // File creation time
CreateDate: Longint; // File creation date
FileSize: Longint; // File size
LastAccessDate: Longint; // File last access date
Name: String[255]; // DOS 8.3 filename as DOS reports
LongName: String[255]; // Windows 95 long filename
// if '' then no long filename available
Erased: Boolean; // True for erased file entry
end; TDiskIO = class
private
FHandle: THandle;
FVolume: Longint;
FPhysicalVolume: Longint;
FLogicalSectors: Longint;
FPhysicalSectors: Longint;
FHeads: Longint;
FCylinders: Longint;
FBytesPerSector: Longint;
FSectorsPerCluster: Longint;
FFATSector: Pointer;
FFATCount: Longint;
FRootDirSector: Longint;
FRootDirCluster: Longint;
FFileSystem: TFileSystem;
FSectorsPerFAT: Longint;
FRootDirEntries: Longint;
FCluster2Sector: Longint;
FFATSize: Longint;
FFAT: Pointer;
FEndingCluster: Longint;
FSerial: Longint;
FLabel: String;
procedure IOCTL(Command: Longint; var Regs: T32Regs);
function ObtainVolumeLock(Level: Byte; Lock: TLockType): Boolean;
procedure ReleaseVolumeLock(Lock: TLockType);
function VolumeLock(Lock: TLockType): Boolean;
procedure VolumeUnlock(Lock: TLockType);
function GetDrive: Char;
procedure SetDrive(Value: Char);
procedure CheckFileSystem;
function WriteLogicalSectorEx(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean;
function ReadLogicalSectorEx(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean;
function GetFATCluster(FATIndex: Longint): Longint;
function GetFATEntry(CopyOfFAT: Longint; Cluster: Longint): Longint;
procedure SetFATEntry(CopyOfFAT: Longint; Cluster: Longint; Value: Longint);
function VolumeCheck(var Flags: Longint): Boolean;
function GetMediaID(MID: PMID): Boolean;
function ReadRootDIR(var DIR: PDIR_Entry; var Entries: Longint): Boolean;
function ReadOtherDir(Cluster: Longint; var DIR: PDIR_Entry; var Entries: Longint): Boolean;
public
constructor Create; virtual;
destructor Destroy; override;
function ValidCluster(Cluster: Longint): Boolean;
// Check cluster for bounds validation
function ReadLogicalSector(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean;
// Reads nSectors from disk into Buffer of size nSize startin at StartSector number
function WriteLogicalSector(StartSector, nSectors: Longint; var Buffer; nSize: Longint): Boolean;
// Writes nSectors to disk from Buffer of size nSize startin at StartSector number
procedure FlushFAT;
// Flushes internal memory FAT image to disk
procedure DriveReread;
// Rescans drive (usually used after changes made)
function ReadCluster(Cluster: Longint; var Buffer; BufferSize: Longint): Boolean;
// Reads cluster number Cluster into Buffer of size BufferSize
function WriteCluster(Cluster: Longint; var Buffer; BufferSize: Longint): Boolean;
// Writes cluster number Cluster to disk from Buffer of size BufferSize
function ReadClusterChain(StartCluster: Longint; var Buffer: Pointer; var BufferSize: Longint): Boolean;
// Reads total cluster chain starting from StartCluster into Buffer returning size of buffer BufferSize
function WriteClusterChain(StartCluster: Longint; Buffer: Pointer; BufferSize: Longint): Boolean;
// Writes total cluster chain starting from StartCluster from Buffer of size BufferSize
function SeekForChainStart(Cluster: Longint): Longint;
// Seeks for starting chain cluster number, Cluster represents any mid cluster of a chain
function DIRPath(Path: String; var DIR: PDIR_Entry; var Entries: Longint): Boolean;
// Returns all directory entries of a path Path including deleted entries into
// DIR as a pointer to TDIR_Entry array returning amount of Entries found
function ExtractDIREntry(Path: String; var DIR: TDIR_Entry): Boolean;
// Gets DIR entry of a Path (or file as Path) specified
property Drive: Char read GetDrive write SetDrive;
// Assign drive letter for class
property LogicalSectors: Longint read FLogicalSectors;
// Amount of Logical sectors on selected drive
property PhysicalSectors: Longint read FPhysicalSectors;
// Amount of Physical sectors on selected drive
property Heads: Longint read FHeads;
// Amount of heads on selected drive
property Cylinders: Longint read FCylinders;
// Amount of Cylinders on selected drive
property BytesPerSector: Longint read FBytesPerSector;
// Amount of Bytes per sector on selected drive
property PhysicalDrive: Longint read FPhysicalVolume;
// Physical drive number
property SectorsPerCluster: Longint read FSectorsPerCluster;
// Amount of sectors per cluster on selected drive
property SectorsPerFAT: Longint read FSectorsPerFAT;
// Amount of sectors per FAT on selected drive
property FATSector[FATIndex: Longint]: Longint read GetFATCluster;
// Returns first sector number of a FAT copy FATIndex
property FATCount: Longint read FFATCount;
// Amount of FAT copies
property RootDirCluster: Longint read FRootDirCluster;
// First cluster number of a Root dir (has meaning only for FAT32)
property RootDirSector: Longint read FRootDirSector;
// First sector number of a Root dir
property RootDirEntries: Longint read FRootDirEntries;
// Amount of a Root dir entries for a drive (non FAT32 only)
property Cluster2Sector: Longint read FCluster2Sector;
// Gives exact Sector number of Cluster number 2 (data start for non FAT32 drives)
property EndingCluster: Longint read FEndingCluster;
// Maximum FAT number for a drive
property FATEntry[CopyOfFAT, Cluster: Longint]: Longint read GetFATEntry write SetFATEntry;
// Gets or sets FAT Entry for cluster Cluster and for FAT copy CopyOfFAT
property Serial: Longint read FSerial;
// Gets volume serial number
property VolumeLabel: String read FLabel;
// Shows volume label
property FileSystem: TFileSystem read FFileSystem;
// What kind of FAT system is used for a drive
end;procedure ParseDOSDate(Date: Word; var Day, Month, Year: Word);
// Use this function to get Day, Month and Year of a Date fields in Dir_Entryprocedure ParseDOSTime(Time: Word; var Hour, Minute, Second: Word);
// Use this function to get Hour, Minute and Second of a Time fields in Dir_Entry
begin
Second := (Time and $001f)*2;
Minute := (Time and $07e0) shr 5;
Hour := (Time and $f800) shr 11;
end;procedure ParseDOSDate(Date: Word; var Day, Month, Year: Word);
begin
Day := Date and $001f;
Month := (Date and $01e0) shr 5;
Year := (Date and $fe00) shr 9;
end;function TDiskIO.GetFATCluster(FATIndex: Longint): Longint;
begin
Result := 0;
if FFATCount=0 then Exit;
if FATIndex<1 then FATIndex := 1;
if FATIndex>FFATCount then FATIndex := FFATCount;
Result := Longint(Pointer(Longint(FFATSector)+(FATIndex-1)*4)^);
end;procedure TDiskIO.IOCTL(Command: Longint; var Regs: T32Regs);
var R: T32Regs;
cb: DWord;
begin
if FHandle = 0 then Exit;
R := Regs;
DeviceIOControl(FHandle, Command,
@R, SizeOf(R), @R, SizeOf(R), cb, NIL);
Regs := R;
end;function TDiskIO.ObtainVolumeLock(Level: Byte; Lock: TLockType): Boolean;
var R: T32Regs;
cb: DWord;
W: Longint;
V: Byte;
begin
W := Level;
W := W shl 8;
if Lock = lPhysical then
begin
V := FPhysicalVolume;
R.EAX := $440D;
R.EBX := W or V;
R.ECX := $084B;
if Level = 1 then R.EDX := 1 else R.EDX := 0;
DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL,
@R, SizeOf(R), @R, SizeOf(R), cb, NIL);
Result := (R.Flags and 1)=0;
end else
begin
R.EAX := $440D;
R.EBX := W or (FVolume and $FF);
R.ECX := $084A;
R.EDX := 0;
DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL,
@R, SizeOf(R), @R, SizeOf(R), cb, NIL);
Result := (R.Flags and 1)=0;
end;
end;procedure TDiskIO.ReleaseVolumeLock(Lock: TLockType);
var R: T32Regs;
cb: DWord;
V: Byte;
begin
if Lock = lPhysical then
begin
V := FPhysicalVolume;
R.EAX := $440D;
R.EBX := V;
R.ECX := $086B;
DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL,
@R, SizeOf(R), @R, SizeOf(R), cb, NIL);
end else
begin
R.EAX := $440D;
R.EBX := FVolume and $FF;
R.ECX := $086A;
DeviceIOControl(FHandle, VWIN32_DIOC_DOS_IOCTL,
@R, SizeOf(R), @R, SizeOf(R), cb, NIL);
end;
end;function TDiskIO.VolumeLock(Lock: TLockType): Boolean;
begin
Result := False;
if FHandle = 0 then Exit;
if FVolume = 0 then Exit;
if Lock = lPhysical then
if FPhysicalVolume = -1 then Exit;
Result := ObtainVolumeLock(1, Lock);
if not Result then Exit;
Result := ObtainVolumeLock(2, Lock);
if not Result then
begin
ReleaseVolumeLock(Lock);
Exit;
end;
Result := ObtainVolumeLock(3, Lock);
if not Result then
begin
ReleaseVolumeLock(Lock);
ReleaseVolumeLock(Lock);
Exit;
end;
end;
delphi6.0里没有D_IOCTL单元啊,是第三方的吧,那里有得down。
在此先谢了。
不过美中不足的是不能在windows2000/XP下用。
不过美中不足的是不能在windowsNT/2000/XP下使用。
只是我没时间翻译成delphi
有时间最翻译在NT和2000下,通过CreateFile来打开需要读写的驱动器,ReadFile、WriteFile来进行磁盘读写。下面的代码演示了,如何读写A驱/* -----------------------------------------------------Read Floppy Disk Sector for win NT/2000
reads [numsec] sectors from [head] [track] [sector]-------------------------------------------------------*/
char* ReadSectors(int head, int sector, int track, int numsec)
{
// getting logical sector from absolute head/track/sector ...
//计算扇区位置
int LogicalSector = (sector-1) +
(head*SECTORSPERTRACK) +
(track*SECTORSPERTRACK*NUMOFHEADS) ;char *buffer ;
HANDLE hDevice ;
HANDLE hDevice;
char* buffer = (char*)malloc (512*numsec);
strset ( buffer , ' ');
DWORD bytesread ;// getting a handle to the drive a: using
// CreateFile () function ....
//打开驱动器 \\.\A:
hDevice = CreateFile("\\\\.\\A:",
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL); if (hDevice == NULL)
{
MessageBox ("Failed !");
return NULL;
}
// setting the file pointer to the start of the
// sector we want to read .
//移动文件指针到需要读取位置
SetFilePointer (hDevice,
(LogicalSector*512),
NULL,
FILE_BEGIN); // reading sector(s) ...
//读数据
if (!ReadFile ( hDevice,
buffer,
512*numsec,
&bytesread,
NULL) )
{
/*
int err;
char error[10];
err=GetLastError ();
itoa (err, error, 10);
MessageBox (error, "Reading sectors ...Failed ");
return NULL ;
*/
}
//关闭
CloseHandle(hDevice); return buffer ;
}