home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1998 July / pcx23_9807.iso / PC-XUSER / PC-XUSER.16 / TT / R4S_FDOS.INT next >
Encoding:
Text File  |  1998-04-13  |  33.1 KB  |  894 lines

  1. {*********************************************}
  2. {                                             }
  3. {   R4s File DOS Function Unit                }
  4. {   Copyright (c) 1996, 97 By Bérczi László   }
  5. {                                             }
  6. {*********************************************}
  7. {Last Edit: 1997 VI 1. 15:00}
  8. {R4s File DOS = R4s rewrited all the DOS File user function for making a
  9.  virtual disks. It means you have a disk image file and R4sFDOS makes a
  10.  virtual drive from it - under R4sFDOS -.}
  11. {$G+}
  12.  
  13. {Bugs:
  14.  - Critical error No mouse update (while Dump-ing disk, NO Handle Event)
  15.  - Just that ONE ... ^
  16. }
  17.  
  18. unit R4s_FDOS;
  19.  
  20. INTERFACE
  21. uses Objects, R4s_Symb, X_Stream;
  22.  
  23. type
  24.  
  25.   PChar13 = ^TChar13;
  26.   TChar13 = Array[1..13] of Char;
  27.  
  28.   PChar11 = ^TChar11;
  29.   TChar11 = Array[1..11] of Char;
  30.  
  31.   PChar8 = ^TChar8;
  32.   TChar8 = Array[1..8] of Char;
  33.  
  34.   PChar3 = ^TChar3;
  35.   TChar3 = Array[1..3] of Char;
  36.  
  37.   PFCB = ^TFCB;
  38.   TFCB = record {for DOS 5.0+}
  39.     DriveNumber   : Byte;
  40.     FileName      : TChar8;
  41.     FileExt       : TChar3;
  42.     CurrBlockNum  : Word; {current block number; each block is 128 Byte long}
  43.     LogicalRecSize: Word;
  44.     FileSize      : Longint;
  45.     FileDate,             {Date of last write}
  46.     FileTime      : Word; {Time of last write}
  47. {S+}SysFileEntry  : Byte; {EXT FUNCS} {number of system file table entry for file}
  48.     Attribute     : Byte; {bits 7,6 - SHARE.exe ... ; bits 5-0 device attribute word}
  49.     ExtraInfo     : Byte; {b7: RO attr from SFT; b6 archive attr from SFT
  50.                            b5-0: high number of sector number}
  51.     StartCluster  : Word; {starting cluster of file}
  52.     SectorNumber  : Word; {low word of sector number containing directory entry}
  53. {E+}DirEntrypSec  : Byte; {END EXT FUNCS} {number of directory entry within sector}
  54.     RecordInCurBlk: Byte; {record within current block 0-127}
  55.     RndAccRecNum  : Longint; {random access record number (if record size is > 64 bytes, high byte is omitted)}
  56.     R4sFCBsPos    : Byte;
  57.   end;
  58.  
  59.   PRFCB = ^TRFCB;
  60.   TRFCB = record {TRFCB: FCB for renaming}
  61.     DriveNumber: Byte;
  62.     OldFileName: TChar8;
  63.     OldFileExt : TChar3;
  64.     NillAreaLow: Array[1..5] of Char;
  65.     NewFileName: TChar8;
  66.     NewFileExt : TChar3;
  67.     NillAreaHi : Array[1..9] of Char;
  68.   end;
  69.  
  70.   PHandle = ^THandle;
  71.   THandle = record
  72.     Path    : String[80]; {temporary}
  73.     Entry   : TDirectoryEntry;        
  74.     Position: Longint; {in Byte from start of file}
  75.     PosZero : Boolean;
  76.     OwnerDIR: Word;    {Owner directory's cluster number}
  77.   end;
  78.  
  79.   {R4s_Symb includes these types}
  80. (*PDirectoryEntry = ^TDirectoryEntry;
  81.   TDirectoryEntry = record
  82.     FileName : TChar8;
  83.     Extension: TChar3;
  84.     Attribute: Byte;
  85.     Reserved : Array[1..10] of Byte;
  86.     Time,
  87.     Date,
  88.     ClusterNumber: Word;
  89.     FileSize     : Longint;
  90.   end;
  91.  
  92.   PDriveParameterBlock = ^TDriveParameterBlock;
  93.   TDriveParameterBlock = record
  94.     Drive             : Byte; {0: A, 1: B . . .}
  95.     UNWDeviceDriver   : Byte;
  96.     BytePerSector     : Word;
  97.     SectorPerCluster  : Byte;
  98.     SqrNSectorACluster: Byte;
  99.     BootSizeInSector  : Word;
  100.     FATNumber         : Byte;
  101.     MaxDirectories    : Word;
  102.     FirstDataSector   : Word;
  103.     MaxCluster        : Word;
  104.     SectorPerFAT      : Word;
  105.     FirstDIRsSector   : Word;
  106.     DeviceHeader      : PDeviceHeader;
  107.     MediaID           : Byte;
  108.     AccessByte        : Byte;
  109.     NextDPB           : PDriveParameterBlock;
  110.     FirstFreeCluster  : Word;
  111.     FreeClusterssNumb : Word
  112.   end;  {R4s_REM}
  113.  
  114.   PFileTime = ^TFileTime;
  115.   TFileTime = record
  116.     Hour,
  117.     Minute,
  118.     Second: Byte;
  119.   end;
  120.  
  121.   PFileDate = ^TFileDate;
  122.   TFileDate = record
  123.     Year : Word;
  124.     Month,
  125.     Day  : Byte;
  126.   end;
  127.  
  128.   PBootSecInforms = ^TBootSecInforms; {SizeOf(TBootSecInforms) = 62 Byte}
  129.   TBootSecInforms = record
  130.     JMP            : Array[1..3] of Byte;
  131.     OEMName        : Array[1..8] of Char;
  132.     Byte_Sector    : Word;
  133.     Sector_Cluster : Byte;
  134.     ReservedSecs   : Word;
  135.     FATCount       : Byte;    {FATCount * SectorInOneFAT          }
  136.     MaxRootEntries,           {(MaxRootEntries * 32) / Byte_Sector}
  137.     Total_Sector   : Word;    {DataStart = ReservedSecs + FATSize + RootSize}
  138.     MediaDescriptor: Byte;
  139.     SectorInOneFAT,
  140.     Sector_Track,
  141.     Head_Number,
  142.     Hidden_Sector  : Word;    {if partitions > 32M then It's the Lo Word    }
  143.     Hidden_SectorHi: Word;    {if partitions > 32M then used else not used  }
  144.     BIGTotal_Sector: Longint; {if (partitions > 32M) And (Total_Sector = 0) }
  145.     PhisicalDriveNo: Byte;    {   then used else not used                   }
  146.     InfoLevel      : Word;    {Must be 0 ???}
  147.     SerialNumber   : Longint; {In Hex (bin) }
  148.     VolumeLabel    : Array[1..11] of Char; {'NO NAME    ' if none present}
  149.     FileSystemType : Array[1..8] of Char;  {'FAT12   ' or 'FAT16   ' or 'FAT     ' (OS2)}
  150.     TempArray      : Array[1..1024-62] of Byte;
  151.   end;   
  152.   *)
  153.  
  154.   PFindFileDataType = ^TFindFileDataType;
  155.   TFindFileDataType = record    
  156.     DriveLetter      : Byte;
  157.     SearchTemp       : TChar11;
  158.     SearchAttribute  : Byte;
  159.     EnrtyCountwDIR   : Word;
  160.     OwnerDIRStartClus: Word;
  161.     OwnerDIRSector   : Longint;
  162.     {Reserved         : Array[1..4] of Char;}
  163.     FoundAttribute   : Byte;
  164.     FileTime,
  165.     FileDate         : Word;
  166.     FileSize         : Longint;
  167.     FileName         : TChar13; {ASCIIZ !!!}    
  168.   end;
  169.  
  170.   PNameBuffer = ^TNameBuffer;
  171.   TNameBuffer = Array[1..128] of Char;
  172.  
  173.   PDiskInfo_Serial = ^TDiskInfo_Serial;
  174.   TDiskInfo_Serial = record
  175.     InfoLevel     : Word; {Must be 0}
  176.     SerialNumber  : Longint;
  177.     VolumeLabel   : Array[1..11] of Char; {'NO NAME    ' if none present}
  178.     FileSystemType: Array[1..8] of Char;  {'FAT12   ' or 'FAT16   '}
  179.   end;
  180.  
  181.   PCurrentDIR = ^TCurrentDIR;
  182.   TCurrentDIR = record
  183.     Sector: Longint;
  184.     Path  : String;
  185.   end;
  186.  
  187.   PBuffer4k = ^TBuffer4k;
  188.   TBuffer4k = Array[1..4096] of Char;
  189.  
  190.   PBuffer = ^TBuffer;
  191.   TBuffer = Array[1..16384] of Char;
  192.  
  193.   PBuffer64k = ^TBuffer64k;
  194.   TBuffer64k = Array[1..65535] of Char;
  195.  
  196.   PBooleanArray = ^TBooleanArray;
  197.   TBooleanArray = Array[0..5760] of Boolean;
  198.  
  199.   PSector = ^TSector;
  200.   TSector = Array[1..4096] of Char; {Usually the Sector size is 512 Byte}
  201.  
  202.   PFileTime = ^TFileTime;
  203.   TFileTime = record
  204.     Hour,
  205.     Minute,
  206.     Second: Byte;
  207.   end;
  208.  
  209.   PFileDate = ^TFileDate;
  210.   TFileDate = record
  211.     Year : Word;
  212.     Month,
  213.     Day  : Byte;
  214.   end;
  215.  
  216.   PAbstractDrive = ^TAbstractDrive;
  217.   TAbstractDrive = Object(TObject)
  218.   public
  219.     LastStatus: Byte;
  220.     CF        : Boolean; {Carray Flag}
  221.     Drive     : Byte;
  222.     constructor Init(ADrive: Byte);
  223.     destructor  Done; virtual;
  224.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}
  225.     function  GetStatusOfLastOperation(ADrive: Byte): Byte; virtual;  {Ret: Status} {1301}
  226.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector,
  227.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  228.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector,
  229.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  230.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector,
  231.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  232.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  233.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  234.     procedure GetDriveDatas(var AFATStart, AFATSize, ARootStart, ARootSize, ADataStart: Word; var AMaxEntryPerSec: Byte;
  235.                 var ABootInf: TBootSecInforms);
  236.     function  GetDriveNumber: Byte;
  237.   private
  238.     FATStart,
  239.     FATSize,
  240.     RootStart,
  241.     RootSize,
  242.     DataStart       : Word;
  243.     MaxEntryPerSec  : Byte;
  244.     BootInf         : TBootSecInforms; {The BootSector's informations}
  245.     UseXMSCache     : Boolean;
  246.     IsSectorIn,
  247.     IsSectorModified: PBooleanArray;
  248.     XMSCache        : PXMSStream;
  249.   end;
  250.  
  251.   PPhisicalDrive = ^TPhisicalDrive;
  252.   TPhisicalDrive = Object(TAbstractDrive)
  253.   public
  254.     constructor Init(ADrive: Byte);
  255.     destructor  Done; virtual;
  256.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}    
  257.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  258.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  259.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  260.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  261.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  262.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  263.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  264.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  265.   end;
  266.  
  267.   PImageDrive = ^TImageDrive;
  268.   TImageDrive = Object(TAbstractDrive)
  269.   public
  270.     DriveStr : String[80];
  271.     ImageFile: File;
  272.     constructor Init(ADrive: String);
  273.     destructor  Done; virtual;
  274.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}    
  275.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  276.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  277.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  278.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  279.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  280.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  281.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  282.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  283.     function  SetWriteProtect(On: Boolean): Boolean; virtual;
  284.   private
  285.     IsWriteProtected: Boolean;
  286.     function  GetBytePERSector: Word;
  287.   end;
  288.  
  289. (* PXMSImageDrive = ^TXMSImageDrive;
  290.   TXMSImageDrive = Object(TAbstractDrive)
  291.   public
  292.     DriveStr : String[80];
  293.     ImageFile: File;
  294.     constructor Init(ADrive: String);
  295.     destructor  Done; virtual;
  296.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}
  297.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  298.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  299.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  300.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  301.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  302.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  303.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  304.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  305.     function  SetWriteProtect(On: Boolean): Boolean; virtual;
  306.   private
  307.     IsWriteProtected: Boolean;
  308.     function  GetBytePERSector: Word;
  309.   end;
  310. *)
  311.  
  312.   {MicroSoft offers handle-oriented file commands instead of FCB like !!!
  313.    So handle-oriented file commands is more reliable then FCB like.
  314.    /FCB oriented file command may mistakes/  - MicroSoft (MS-DOS)}
  315.  
  316.   PR4sFileDOS = ^TR4sFileDOS;
  317.   TR4sFileDOS = Object(TObject)
  318.   public {Original DOS functions}
  319. {R} constructor Init(ADriveObj: PAbstractDrive); {R means it's ready}
  320. {R} destructor  Done; virtual;
  321. {R} procedure SelectDefaultDrive(DriveImageFile: String); virtual;               {210E}
  322. {R} function  OpenFileByFCB(var FCB: TFCB): Boolean; virtual;  {UnOp}            {210F}
  323. {R} function  CloseFileByFCB(var FCB: TFCB): Boolean; virtual; {  Op}            {2110}
  324.     function  FindFirstByFCB(FCB: TFCB): Boolean; virtual; {UnOp}                {2111}
  325.     function  FindNextByFCB(FCB: TFCB): Boolean; virtual;  {UnOp}                {2112}
  326.     function  DeleteFileByFCB(FCB: TFCB): Boolean; virtual;{UnOp}                {2113}
  327. {R} function  SeqReadByFCB(var FCB: TFCB): Boolean;virtual;{Op,Return data in DTA 2114}
  328.     function  SeqWriteByFCB(FCB: TFCB): Boolean; virtual;  {Op,Expect data in DTA 2115}
  329.     function  CreateFileByFCB(FCB: TFCB): Boolean; virtual;{UnOp,overw. if exist  2116}
  330.     function  RenameFileByFCB(RFCB: TRFCB): Boolean; virtual;                    {2117}
  331. {R} function  GetCurrentDrive: String; virtual;                                  {2119}
  332. {R} procedure SetDTA(Address: Pointer); virtual;           {Disk Transfer Area    211A}
  333.     procedure GetAllocationInformationForDefDrive(var SecClus: Byte;    {211B}
  334.                 var ByteSec: Word; var TotClus: Word; var MediaID: Byte); virtual;
  335.   (*procedure GetAllocationInformationForSpecDrive(Drive: String; var SecClus: Byte;  {211C}
  336.               var ByteSec: Word; var TotClus: Word; var MediaID: Byte); virtual;*)
  337.     function  GetDPBForDefDrive: PDriveParameterBlock; virtual;                  {211F}
  338.     function  ReadRandomRecByFCB(FCB: TFCB): Boolean; virtual;   {Op,Return data in DTA 2121}
  339.     function  WriteRandomRecByFCB(FCB: TFCB): Boolean; virtual;  {Op,Except data in DTA 2122}
  340.     function  GetFileSizeByFCB(var FCB: TFCB): Boolean; virtual; {UnOp   2123}
  341.     procedure SetRandomRecNumbForFCB(var FCB: TFCB); virtual;    {Op     2124}
  342.     function  RandomBlockReadByFCB(var NumbRecToRead: Word; var FCB: TFCB): Boolean; virtual; {Op,Return data in DTA 2127}
  343.     function  RandomBlockWriteByFCB(var NumbRecToRead: Word; var FCB: TFCB): Boolean; virtual;{Op,Except data in DTA 2128}
  344.     function  PraseFileNameToFCB(var FCB: TFCB; Str: String; var UnPrasedPos: Byte): Boolean; virtual; {UnOp 2129}
  345. {R} function  GetDTA: Pointer; virtual; {212F}
  346.   (*function  GetDPBForSpecDrive(Drive: String): PDriveParameterBlock; virtual; {2132}*)
  347.     function  GetFreeDiskSpace(Drive: String; var SecClus, FreeClus, ByteClus, TotalClus: Word): Boolean; virtual; {2136}
  348.     function  MkDIR(Name: TASCIIZ): Boolean; virtual; {2139}
  349.     function  RmDIR(Name: TASCIIZ): Boolean; virtual; {213A}
  350. {R} function  ChDIR(Name: TASCIIZ): Boolean; virtual; {213B}
  351.     function  CreatFile(Name: TASCIIZ; Attributes: Word; var Handle: Word): Boolean; virtual; {213C}
  352. {R} function  OpenFile(Name: TASCIIZ; AccessMode: Byte; var Handle: Word): Boolean; virtual;  {213D}
  353. {R} function  CloseFile(Handle: Word): Boolean; virtual; {213E}
  354. {R?}function  ReadFromFile(Handle: Word; var ByteToRead: Word; var Buf; BufSize: Word): Boolean; virtual; {213F}
  355. {N} function  WriteToFile(Handle: Word; var ByteToWrite: Word; var Buf): Boolean; virtual; {2140}
  356.     function  DeleteFile(Name: String): Boolean; virtual; {2141}
  357. {R} function  SeekFile(Handle: Word; SeekType: Byte; var Pos: Longint): Boolean; virtual;  {2142}
  358. {R} function  GetFilePos(Handle: Word): Longint; {2142xx} {if Return = $FFFFFFFF then It means Error !}
  359. {*} function  GetFileAttributes(Name: String; var Attributes: Word): Boolean; virtual; {214300}
  360.     function  SetFileAttributes(Name: String; Attributes: Word): Boolean; virtual;     {214301}
  361.   (*function  GetDeviceInforms(Handle: Word; var Inform: Word): Boolean; virtual;      {214400}
  362.     function  SetDeviceInforms(Handle: Word; Inform: Word): Boolean; virtual;          {214401}*)
  363.     function  DuplicateFileHandle(Handle: Word; var NewHandle: Word): Boolean; virtual;  {2145}
  364. {?} function  DuplicateFileHandle2(Handle: Word; var NewHandle: Word): Boolean; virtual; {2146}
  365.     function  GetCurrentDIR(Drive: Byte; var ASCIIZPath: TASCIIZ): Boolean; virtual; {2147}
  366. {R} function  FindFirstFile(Name: TASCIIZ; Attribute: Byte): Boolean; virtual; {Return FF DataBlock in DTA  214E}
  367. {R} function  FindNextFile: Boolean; virtual; {EXCEPT previous FF DataBlock in DTA  214F}
  368.     function  RenameFile(OldName, NewName: TASCIIZ): Boolean; virtual; {2156}
  369. {R} function  GetFilesTimeAndDate(Handle: Word; var Time, Date: Word): Boolean; virtual; {215700}
  370.     function  SetFilesTimeAndDate(Handle: Word; Time, Date: Word): Boolean; virtual;     {215701}
  371.   (*function  GetExtAttributesForFile    {215702}
  372.     function  GetExtAttributesProperties {215703}
  373.     function  SetExtAttributes           {215704}*)
  374.     function  CreateTempFile(var Name: TASCIIZ {\ !}; Attribute: Word; var Handle: Word): Boolean; virtual; {215A}
  375.     function  CreateNewFile(var Name: TASCIIZ; Attribute: Word; var Handle: Word): Boolean; virtual;        {215B}
  376.     function  NameExpand(Name: TASCIIZ; var OutNameBuffer: TNameBuffer): Boolean; virtual; {Canonicalize filename or path 2160}
  377.     function  FlushFileDatas(Handle: Word): Boolean; virtual; {2168}
  378. {*} function  GetDiskSerialNumber(Disk: String; var DiskInfo: TDiskInfo_Serial): Boolean; virtual; {216900}
  379.     function  SetDiskSerialNumber(Disk: String; DiskInfo: TDiskInfo_Serial): Boolean; virtual;     {216901}
  380.     function  ComitFile(Handle: Word): Boolean; virtual; {216A}
  381. {}  function  ExtendedOpenOrCreateFile(Name: String; OpenMode, Flags: Byte; Attribute: Word; Action: Byte;
  382.                 var Handle: Word): Boolean; virtual; {216C00}
  383.    {function  AbsouluteDiskRead(Disk: String; SecToRead, StartSec: Word; var Buf ... {26..}
  384.   public {DOS Extensions}
  385.     function  GetFileSize(Handle: Word): Longint;
  386.   public {Helper methods for using DOS functions}
  387.     DTA  : Pointer;
  388.     Error: Byte;
  389.     procedure PrepareFCBForUsing(var FCB: TFCB; AFileName, AFileExt: String);
  390.     procedure TempFunc;
  391.   public {Temporary, check methods for out use}
  392.     function  GetHandle(Handle: Byte): PHandle;
  393.   private {Sub-methods for internal use of FDOS}
  394.     function  GetSectorOfDirectory(Name: TASCIIZ; var Sector: Longint; var Path: String): Boolean; virtual;
  395.   private
  396.     MyFCB     : TFCB;
  397.     TheDrive  : String;
  398.     DriveNum  : Byte;
  399.     DriveObj  : PAbstractDrive;
  400.     DriveImage: File;
  401.     CurDIR    : TCurrentDIR;
  402.     ASector   : TSector;
  403.     AEntry    : TDirectoryEntry;
  404.     FATStart,
  405.     FATSize,
  406.     RootStart,
  407.     RootSize,
  408.     DataStart     : Word;
  409.     MaxEntryPerSec: Byte;
  410.     BootInf       : TBootSecInforms; {The BootSector's informations}
  411.     FCBs          : Array[1..50] of PFCB;
  412.     Handles       : Array[6..55] of THandle;
  413.     IsUsedHandle  : Array[6..55] of Boolean;
  414.     FAT           : PBuffer; {64k;}
  415.     Is12bitFAT    : Boolean;
  416.     CRC_ASector,
  417.     SectorNumber  : Longint;
  418.   private {Internal converter, and other helper methods}
  419.     function  GetSectorPerByteInADriveImage(Drive: String): Word;
  420.     procedure ClearAllLocalVariable;
  421.     function  ReadLogicalSector(SecNb: Longint): Boolean;
  422.     function  ReadnLogigalSector(FromSector: Longint; var Count: Word; ToMem: Pointer): Boolean;
  423.     function  IsEntryASimpleFile(Entry: TDirectoryEntry): Boolean;
  424.     function  ConvertClusterNumberToLogicalSector(ClusNum: Word): Longint;
  425.     function  ConvertLogicalSectorToClusterNumber(LogSec: Longint): Word;
  426.     function  IsNULLEntry(const Entry: TDirectoryEntry): Boolean;
  427.     function  IsNULLTheEntry(Sector: TSector; Index: Word): Boolean;
  428.     function  IsFillWithEntry(Sector: TSector): Boolean;
  429.     function  IsUsedEntry(Sector: TSector; Index: Word): Boolean;
  430.     procedure CopyBufToBootInforms(var Buf; var ABootInf: TBootSecInforms);
  431.     procedure ConvertTimeWordToRecord(FileTimeW: Word; var FileTime: TFileTime);
  432.     procedure ConvertDateWordToRecord(FileDateW: Word; var FileDate: TFileDate);
  433.     procedure CopyBufToDirEntry(var Buf; Index: Byte; var _AEntry: TDirectoryEntry);
  434.     procedure GetBootInforms;
  435.     function  GetFirstFreeFCBsPos: Byte;
  436.     function  ReadFAT: Boolean;
  437.     function  HasDrive12bitFAT: Boolean;
  438.     function  Convert12BitFATToWord(FATBuf: Pointer; FATIndex: Word): Word;
  439.     procedure CopyASectorToDTA(var _ASector; Count: Word);
  440.     procedure BringDecedXByte(var Buf; SegBuf, OfsBuf, WithX: Word; SizeOfBuf: Integer);
  441.     procedure ConvertStringToChar13(S: String; var CArray: TChar13);
  442.     procedure ConvertStringToChar11(S: String; var CArray: TChar11);
  443.   end;
  444.  
  445. const
  446.  
  447.   SeekFrom_Start      = 0;
  448.   SeekFrom_CurFilePos = 1;
  449.   SeekFrom_End        = 2;
  450.  
  451.   Cluster12_FREE = $0000;
  452.   Cluster12_RES  = $0FF0; {RESERVED}
  453.   Cluster12_RES2 = $0FF1; {RESERVED}
  454.   Cluster12_RES3 = $0FF2; {RESERVED}
  455.   Cluster12_RES4 = $0FF3; {RESERVED}
  456.   Cluster12_RES5 = $0FF4; {RESERVED}
  457.   Cluster12_RES6 = $0FF5; {RESERVED}
  458.   Cluster12_RES7 = $0FF6; {RESERVED}
  459.   Cluster12_BAD  = $0FF7;
  460.   Cluster12_EOF  = $0FF8;
  461.   Cluster12_EOF2 = $0FF9;
  462.   Cluster12_EOF3 = $0FFA;
  463.   Cluster12_EOF4 = $0FFB;
  464.   Cluster12_EOF5 = $0FFC;
  465.   Cluster12_EOF6 = $0FFD;
  466.   Cluster12_EOF7 = $0FFE;
  467.   Cluster12_EOF8 = $0FFF;
  468.  
  469.   Cluster16_FREE = $0000;
  470.   Cluster16_RES  = $FFF0; {RESERVED}
  471.   Cluster16_RES2 = $FFF1; {RESERVED}
  472.   Cluster16_RES3 = $FFF2; {RESERVED}
  473.   Cluster16_RES4 = $FFF3; {RESERVED}
  474.   Cluster16_RES5 = $FFF4; {RESERVED}
  475.   Cluster16_RES6 = $FFF5; {RESERVED}
  476.   Cluster16_RES7 = $FFF6; {RESERVED}
  477.   Cluster16_BAD  = $FFF7;
  478.   Cluster16_EOF  = $FFF8;
  479.   Cluster16_EOF2 = $FFF9;
  480.   Cluster16_EOF3 = $FFFA;
  481.   Cluster16_EOF4 = $FFFB;
  482.   Cluster16_EOF5 = $FFFC;
  483.   Cluster16_EOF6 = $FFFD;
  484.   Cluster16_EOF7 = $FFFE;
  485.   Cluster16_EOF8 = $FFFF;
  486.  
  487.   {Original DOS Error}
  488.   R4sFDOS_NoError               = $00; {ConvertExtErrCodeToString}
  489.   R4sFDOS_FunctionNumberInvalid = $01;
  490.   R4sFDOS_FileNotFound          = $02;
  491.   R4sFDOS_PathNotFound          = $03;
  492.   R4sFDOS_TooManyOpenFiles      = $04;
  493.   R4sFDOS_AccessDenied          = $05;
  494.   R4sFDOS_InvalidHandle         = $06;
  495.   R4sFDOS_FormatInvalid         = $0B;
  496.   R4sFDOS_AccessCodeInvalid     = $0C;
  497.   R4sFDOS_DataInvalid           = $0D;
  498.   R4sFDOS_InvalidDrive          = $0F;
  499.   R4sFDOS_AttemptedToRemoveCurrentDirectory = $10;
  500.   R4sFDOS_NoMoreFiles           = $12;
  501.   R4sFDOS_DiskWrite_Protected   = $13;
  502.   R4sFDOS_UnknownUnit           = $14;
  503.   R4sFDOS_DriveNotReady         = $15;
  504.   R4sFDOS_UnknownCommand        = $16;
  505.   R4sFDOS_DataError_CRC         = $17;
  506.   R4sFDOS_BadRequestStructureLength = $18;
  507.   R4sFDOS_SeekError             = $19;
  508.   R4sFDOS_UnknownMediaType      = $1A;
  509.   R4sFDOS_SectorNotFound        = $1B;
  510.   R4sFDOS_WriteFault            = $1D;
  511.   R4sFDOS_ReadFault             = $1E;
  512.   R4sFDOS_GeneralFailure        = $1F;
  513.   R4sFDOS_SharingViolation      = $20;
  514.   R4sFDOS_LockViolation         = $21;
  515.   R4sFDOS_DiskChangeInvalid     = $22;
  516.   R4sFDOS_FCBUnavailable        = $23;
  517.   R4sFDOS_SharingBufferOverflow = $24;
  518.   R4sFDOS_InsufficientDiskSpace = $27;
  519.   R4sFDOS_FileExists            = $50;
  520.   R4sFDOS_CannotMakeDirectory   = $52;
  521.   {R4sFileDOS Enhanced Error Codes}
  522.   R4sFDOS_EOF                   = $53;
  523.   R4sFDOS_FATToBig              = $54;
  524.   R4sFDOS_Unknown               = $FF;
  525.  
  526.   NoAttr    = $00;
  527.   ReadOnly  = $01;
  528.   Hidden    = $02;
  529.   SysFile   = $04;
  530.   VolumeID  = $08;
  531.   Directory = $10;
  532.   Archive   = $20;
  533.   AnyFile   = $3F;
  534.  
  535. IMPLEMENTATION
  536. uses R4s_Init, DOS, CRC, R4s_Str, R4s_Conv, R4s_MEMF;
  537.  
  538. {TAbstractDrive}
  539. constructor TAbstractDrive.Init(ADrive: Byte);
  540. begin
  541.   {Inherited Init;} {OFF: Because it fill himself with 0}
  542. end;
  543.  
  544. destructor  TAbstractDrive.Done;
  545. begin
  546.   Abstract;
  547. end;
  548.  
  549. function  TAbstractDrive.ResetDisk(ADrive: Byte): Byte;
  550. begin
  551.   Abstract;
  552. end;
  553.  
  554. function  TAbstractDrive.GetStatusOfLastOperation(ADrive: Byte): Byte;
  555. begin
  556.   GetStatusOfLastOperation:=LastStatus;
  557. end;
  558.  
  559. function  TAbstractDrive.ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  560.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean;
  561. begin
  562.   Abstract;
  563. end;
  564.  
  565. function  TAbstractDrive.WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  566.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean;
  567. begin
  568.   Abstract;
  569. end;
  570.  
  571. function  TAbstractDrive.VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  572.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean;
  573. begin
  574.   Abstract;
  575. end;
  576.  
  577. function  TAbstractDrive.ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  578.             var Status, ReadedSecCount: Byte): Boolean;
  579. begin
  580.   Abstract;
  581. end;
  582.  
  583. procedure TAbstractDrive.GetDriveDatas(var AFATStart, AFATSize, ARootStart, ARootSize, ADataStart: Word; 
  584.               var AMaxEntryPerSec: Byte; var ABootInf: TBootSecInforms);
  585. begin
  586.   AFATStart:=FATStart;
  587.   AFATSize:=FATSize;
  588.   ARootStart:=RootStart;
  589.   ARootSize:=RootSize;
  590.   ADataStart:=DataStart;
  591.   AMaxEntryPerSec:=MaxEntryPerSec;
  592.   ABootInf:=BootInf;
  593. end;
  594.  
  595. function  TAbstractDrive.GetDriveNumber: Byte;
  596. begin
  597.   GetDriveNumber:=Drive;
  598. end;
  599.  
  600. {TPhisicalDrive}
  601. constructor TPhisicalDrive.Init(ADrive: Byte);
  602. var Status, Readed: Byte;
  603. begin
  604.   Inherited Init(ADrive);
  605.   Drive:=ADrive;
  606.   for Readed:=0 to 4 do if ResetDisk(Drive) = 0 then Break;
  607.   ReadSectorsIntoMemory(BootInf, Drive, 0, 0, 1, 2, Status, Readed);
  608.   with BootInf do
  609.   begin
  610.     FATStart:=ReservedSecs;
  611.     FATSize:=FATCount * SectorInOneFAT;
  612.     RootStart:=FATStart + FATSize;
  613.     RootSize:=(MaxRootEntries * 32) div Byte_Sector;
  614.     DataStart:=RootStart + RootSize;
  615.     MaxEntryPerSec:=(Sector_Cluster * Byte_Sector) div $20;  {20h = 32 = AEntry Size}
  616.  
  617.     if IsXMSDriverInstalled
  618.     then if Total_Sector * Byte_Sector < (GetTotalExtendedMemorySize* 1024)+(64*1024)
  619.          then UseXMSCache:=True
  620.          else UseXMSCache:=False
  621.     else UseXMSCache:=False;
  622.  
  623.   end;
  624.  
  625.   {
  626.     IsSectorIn,
  627.     IsSectorModified: PBooleanArray;
  628.     XMSCache        : PXMSStream;
  629.   }
  630. end;
  631.  
  632. destructor  TPhisicalDrive.Done;
  633. begin
  634. end;
  635.  
  636. function  TPhisicalDrive.ResetDisk(ADrive: Byte): Byte; Assembler;
  637. asm
  638.   xor  ah, ah
  639.   mov  dl, ADrive
  640.   and  al, 01111111b
  641.   int  13h
  642.   mov  al, ah
  643. end;
  644.  
  645. function  TPhisicalDrive.ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  646.             SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; Assembler;
  647. asm
  648.   push es
  649.   push di
  650.  
  651.   cmp  SecCount, 00h
  652.   jne  @Cont
  653.   mov  ah, 0FFh
  654.   xor  al, al
  655.   jmp  @Error
  656.  
  657. @Cont:
  658.   mov  ax, Track  {CylNum -> ax (ah, al)}
  659.   shl  ah, 6      {xxxx xxBB -> BBxx xxxx}
  660.   mov  bl, Sector {SecNum -> bl}
  661.   shl  bl, 2      {xxBB BBBB -> BBBB BB00}
  662.   shr  bl, 2      {BBBB BB00 -> 00BB BBBB}
  663.   add  ah, bl     {ah -> ah felsô két bit  és  bl alsô 6 bit}
  664.   xchg al, ah     {ah, al között csere}
  665.   mov  cx, ax   
  666.  
  667.   mov  ah, 02h
  668.   mov  al, SecCount
  669.   mov  dh, Head
  670.   mov  dl, ADrive
  671.   les  bx, [Buf]
  672.   int  13h
  673.   jc   @Error
  674.  
  675.   les  di, Self
  676.   mov  Byte Ptr es:[di].TPhisicalDrive.LastStatus, ah
  677.   mov  Byte Ptr es:[di].TPhisicalDrive.CF, False
  678.   les  di, Status
  679.   mov  Byte Ptr es:[di], ah
  680.   les  di, ReadedSecCount
  681.   mov  Byte Ptr es:[di], al 
  682.  
  683.   mov  al, True
  684.   jmp  @Exit
  685.  
  686. @Error:
  687.   les  di, Self
  688.   mov  Byte Ptr es:[di].TPhisicalDrive.LastStatus, ah
  689.   mov  Byte Ptr es:[di].TPhisicalDrive.CF, True
  690.   les  di, Status
  691.   mov  Byte Ptr es:[di], ah
  692.   les  di, ReadedSecCount
  693.   mov  Byte Ptr es:[di], al 
  694.   mov  al, False
  695. @Exit:
  696.   pop  di
  697.   pop  es
  698. end;
  699.  
  700. function  TPhisicalDrive.WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  701.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean;
  702. begin
  703. end;
  704.  
  705. function  TPhisicalDrive.VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  706.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean;
  707. begin
  708. end;
  709.  
  710. function  TPhisicalDrive.ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  711.             var Status, ReadedSecCount: Byte): Boolean;
  712. var
  713.   Track : Word;
  714.   Sector,
  715.   Head : Byte;
  716. begin
  717.   Sector:=Byte(((StartSec) mod BootInf.Sector_Track)+1);
  718.   Track:=Word(((StartSec) div BootInf.Sector_Track) div BootInf.Head_Number);
  719.   if ADrive > $7F then Head:=Byte(((((StartSec) div BootInf.Sector_Track) mod BootInf.Head_Number))+1) {HDD}
  720.                   else Head:=Byte((((StartSec) div BootInf.Sector_Track) mod BootInf.Head_Number));    {FDD}
  721.   ReadLogicalSectorIntoMemory:=ReadSectorsIntoMemory(Buf, ADrive, Head, Track, 
  722.     Sector, SecCount, Status, ReadedSecCount);
  723. end;
  724.  
  725. {TImageDrive}
  726. constructor TImageDrive.Init(ADrive: String);
  727. var 
  728.   TempW: Word;
  729.   Status, Readed: Byte;
  730. begin
  731.   Inherited Init(0);
  732.   DriveStr:=ADrive;
  733.   Assign(ImageFile, DriveStr);
  734.   GetFAttr(ImageFile, TempW);
  735.   IsWriteProtected:=(TempW and ReadOnly) <> 0;
  736.   if (TempW and ReadOnly) <> 0 then FileMode:=0;
  737.   {$I-}
  738.   Reset(ImageFile, GetBytePERSector);
  739.   {$I+}
  740.   if IOResult <> 0 then RunError($5); {File Not Found!}
  741.   if (TempW and ReadOnly) <> 0 then FileMode:=2;
  742.  
  743.   Drive:=0;
  744.   ResetDisk(Drive);
  745.   ReadSectorsIntoMemory(BootInf, Drive, 0, 0, 1, 2, Status, Readed);
  746.   with BootInf do
  747.   begin
  748.     FATStart:=ReservedSecs;
  749.     FATSize:=FATCount * SectorInOneFAT;
  750.     RootStart:=FATStart + FATSize;
  751.     RootSize:=(MaxRootEntries * 32) div Byte_Sector;
  752.     DataStart:=RootStart + RootSize;
  753.     MaxEntryPerSec:=(Sector_Cluster * Byte_Sector) div $20;  {20h = 32 = AEntry Size}
  754.   end;                  
  755. end;
  756.  
  757. destructor  TImageDrive.Done;
  758. begin
  759.   Close(ImageFile);
  760. end;
  761.  
  762. function  TImageDrive.ResetDisk(ADrive: Byte): Byte;
  763. begin
  764.   Seek(ImageFile, 0);
  765.   if IOResult = 0 then ResetDisk:=0
  766.                   else ResetDisk:=$80;
  767. end;
  768.  
  769. function  TImageDrive.ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; 
  770.             Sector, SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean;
  771. var LogicalSec: Longint;
  772. begin
  773.   LogicalSec:= Track * BootInf.Head_Number * BootInf.Sector_Track + Head * BootInf.Sector_Track + Sector - 1;
  774.   ReadSectorsIntoMemory:=ReadLogicalSectorIntoMemory(Buf, ADrive, LogicalSec, SecCount, Status, ReadedSecCount);
  775. end;
  776.  
  777. function  TImageDrive.WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  778.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean;
  779. var 
  780.   TempWord  : Word;
  781.   LogicalSec: Longint;
  782. begin
  783.   if IsWriteProtected 
  784.   then begin Status:=$03; SecWrited:=0; WriteSectors:=False; end
  785.   else begin
  786.          LogicalSec:= Track * BootInf.Head_Number * BootInf.Sector_Track + Head * BootInf.Sector_Track + Sector - 1;
  787.          Seek(ImageFile, LogicalSec);
  788.          BlockWrite(ImageFile, Buf, SecToWrite, TempWord);
  789.          if IOResult = 0 then Status:=0
  790.                          else Status:=$80;
  791.          SecWrited:=Byte(TempWord);  
  792.          WriteSectors:= IOResult = 0;
  793.        end;
  794. end;
  795.  
  796. function  TImageDrive.VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; 
  797.             Sector, SecToVerify: Byte; var Status, SecVerified: Byte): Boolean;
  798. begin
  799.   VerifySectors:=ReadSectorsIntoMemory(Buf, ADrive, Head, Track, Sector, 
  800.     SecToVerify, Status, SecVerified);
  801. end;
  802.  
  803. function  TImageDrive.ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  804.                 var Status, ReadedSecCount: Byte): Boolean;
  805. var TempWord: Word;
  806. begin
  807.   Seek(ImageFile, StartSec);
  808.   BlockRead(ImageFile, Buf, SecCount, TempWord);
  809.   if IOResult = 0 then Status:=0
  810.                   else Status:=$80;
  811.   ReadedSecCount:=Byte(TempWord);  
  812.   ReadLogicalSectorIntoMemory:= IOResult = 0;
  813. end;
  814.  
  815. function  TImageDrive.SetWriteProtect(On: Boolean): Boolean;
  816. var Attr: Word;
  817. begin
  818.   GetFAttr(ImageFile, Attr); 
  819.   if On then Attr:=Attr or ReadOnly
  820.         else Attr:=Attr and Not ReadOnly;
  821.   if IOResult = 0 then begin 
  822.                          SetFAttr(ImageFile, Attr);
  823.                          if IOResult = 0 then SetWriteProtect:=True
  824.                                          else SetWriteProtect:=False;
  825.                        end
  826.                   else SetWriteProtect:=False;
  827. end;
  828.  
  829. function  TImageDrive.GetBytePERSector: Word;
  830. var 
  831.   F   : File;
  832.   BInf: TBootSecInforms;
  833.   W   : Word;
  834. begin
  835.   Assign(F, DriveStr);
  836.   {$I-}
  837.   Reset(F, 1024);
  838.   if IOResult <> 0 then begin GetBytePERSector:=512; Exit; end; {Structureless!!!}
  839.   {$I+}
  840.   BlockRead(F, BInf, 1, W);
  841.   if W = 1 then GetBytePERSector:=BInf.Byte_Sector
  842.            else GetBytePERSector:=512;
  843.   Close(F);
  844. end;
  845.  
  846. {PUBLIC Original DOS functions}
  847. constructor TR4sFileDOS.Init(ADriveObj: PAbstractDrive);
  848. var Mem, Disk: Longint;
  849. begin
  850.   New(FAT);
  851.  
  852.   DriveObj:=ADriveObj;
  853.   DriveNum:=ADriveObj^.GetDriveNumber;
  854.  
  855.   SelectDefaultDrive(TheDrive);
  856.   if Error <> 0 then begin Error:=R4sFDOS_DriveNotReady; Fail; end;
  857.   Is12bitFAT:=HasDrive12bitFAT;
  858.   SetDTA(Ptr(PrefixSeg, $80));
  859. end;
  860.  
  861. destructor  TR4sFileDOS.Done;
  862. begin
  863.   ClearAllLocalVariable;
  864.   Dispose(FAT);
  865.   DriveObj^.Done;
  866.   Inherited Done;
  867. end;
  868.  
  869. procedure TR4sFileDOS.SelectDefaultDrive(DriveImageFile: String);
  870. var
  871.   TempW: Word;
  872.   TempB: Boolean;
  873. begin
  874. {  if ExistFile(DriveImageFile) then {Because of read before exists ?!!!}
  875. {  begin}
  876. (*    TheDrive:=DriveImageFile;
  877.     TempW:=GetSectorPerByteInADriveImage(TheDrive);
  878.     {$I-} Assign(DriveImage, TheDrive);
  879.     Reset(DriveImage, TempW);  {$I+}*)
  880.     ClearAllLocalVariable;
  881.     DriveObj^.GetDriveDatas(FATStart, FATSize, RootStart, RootSize, 
  882.                             DataStart, MaxEntryPerSec, BootInf);
  883.  
  884.     CurDIR.Sector:=RootStart; {ConvertClusterNumberToLogicalSector(8);}
  885.     CurDIR.Path:=':\';
  886.     if IOResult <> 0 then Error:=R4sFDOS_DriveNotReady
  887.                      else if Not ReadFAT then Error:=R4sFDOS_FATToBig;
  888.   {end                          else Error:=R4sFDOS_DriveNotReady;}
  889. end;
  890.  
  891. {... a többit majd a következô számokban ...}
  892.  
  893.  
  894. END.