[Back to FILES SWAG index]  [Back to Main SWAG index]  [Original]

{$A+,B-,D-,E-,F-,G+,I-,L-,N+,O-,P-,Q-,R-,S-,T-,V+,X+,Y-}

Unit UFile95;

{A lot of declarations in this unit belong in other units, such as
 Move32 (UMemory); TBoolean/TByte/TChar - UGlobal. Unit was modified to
 be standalone.}


(* **************************************************************
     TO COMPILE  UFILE95  YOU NEED TO COMPILE THE  UMULTI  UNIT
         WHOSE SOURCE CAN BE FOUND AT THE END OF THIS FILE
   **************************************************************
                  PLEASE PUBLISH THIS IN THE SWAG
   ************************************************************** *)


Interface {Nothing!}

Const Author = 'UFile95 v6.2, 05-Feb-97, 1995-1997.'+
               'Written by Gil Shapira.'+
               'Bug or other reports to:  gilsh@ibm.net';

{Nicer looks ;-) }
Type TBoolean = Boolean;
     TPointer = Pointer;
     TChar = Char;
     TByte = Byte;
     TWord = Word;
     THalf = ShortInt;
     TInt = Integer;
     TDouble = LongInt;

Type THandle = TWord;
     TError = TWord;

{File modes}
Const fmRead = 0;
      fmWrite = 1;
      fmReadWrite = 2;
      fmDenyAll = 16;
      fmDenyWrite = 32;
      fmDenyRead = 48;
      fmDenyNone = 64;

{File seek origins}
Const foStart = 0;
      foCurrent = 1;
      foEnd = 2;

{File attributes}
Const faReadOnly = 1;
      faHidden = 2;
      faSystem = 4;
      faVolume = 8;
      faDirectory = 16;
      faArchive = 32;
      faAnyFile = 63;

{File parts}
Const fcExtension = 1;
      fcFileName = 2;
      fcDirectory = 4;
      fcWildcards = 8;

{Search record for DOS interrupt 21h}
Type PSearch = ^TSearch;
     TSearch = Record
                SearchDrive: TChar;
                SearchTemplate: Array [1..11] Of TByte;
                SearchAttr: TByte;
                DirEntry: TWord;
                StartCluster: TWord;
                Reserved: Array [1..4] Of TByte;
                Attr: TByte;
                Time: TWord;
                Date: TWord;
                Size: TDouble;
                Name: Array [1..13] Of TChar;
               End;

{Search record for Windows '95 interrupt 21h}
Type PSearch95 = ^TSearch95;
     TSearch95 = Record
                  Handle: TWord;
                  Attr: TDouble;
                  Creation: Comp;
                  LastAccess: Comp;
                  LastModify: Comp;
                  SizeHi: TDouble;
                  SizeLo: TDouble;
                  Reserved: Array [1..8] Of TByte;
                  Name: Array [0..259] Of TChar;
                  ShortName: Array [0..13] Of TChar;
                 End;

Var LockLevel,
    FileMode,
    FindAttr,
    CopyAttr,
    DeleteAttr,
    CreateAttr: TWord;
    flError: TError;
    isError,
    Using95: TBoolean;

 {Creates a new directory; only ONE directory at a time.}
Procedure CreateDir(PathName: PChar);
 {Removes an existing directory; should not be current directory}
Procedure RemoveDir(PathName: PChar);
 {Makes the specified directory the current directory,
  without changing the current drive}
Procedure ChangeDir(PathName: PChar);
 {Returns the current directory path}
Procedure CurrentDir(CurDir: PChar);
 {Makes the specified directory the current directory,
  and changes the current drive if needed}
Procedure ChangePath(PathName: PChar);
 {Creates a virtual drive for the path specified; should be
  used ONLY under Windows '95}
Procedure Subst(Drive: TChar; PathName: PChar);
 {Returns the path for the virtual drive specified; should be
  used ONLY under Windows '95}
Procedure QuerySubst(Drive: TChar; Var PathName: PChar);
 {Terminates the virtual drive association; should be
  used ONLY under Windows '95}
Procedure DeleteSubst(Drive: TChar);
 {Creates a new file}
Function Create(FileName: PChar): THandle;
 {Replaces an existing file, erasing its content}
Function Replace(FileName: PChar): THandle;
 {Opens an existing file}
Function Open(FileName: PChar): THandle;
 {Duplicated a file handle}
Function Duplicate(Handle: THandle): THandle;
 {Changes the position in the file; use the file origin
  constants for Origin}
Function Seek(Handle: THandle; Position: TDouble; Origin: TByte): TDouble;
 {Returns the current position in the file}
Function FilePos(Handle: THandle): TDouble;
 {Returns the size of the file}
Function FileSize(Handle: THandle): TDouble;
 {Splits the path to directory, filename (8), and extension (4)}
Function FSplit(Path,Dir,Name,Ext: PChar): TByte;
 {Expands a short/long filename}
Procedure FExpand(Path,Result: PChar);
 {Return the file attributes}
Function GetFileAttr(FileName: PChar): TByte;
 {Changes the file attributes}
Procedure SetFileAttr(FileName: PChar; Attr: TByte);
 {Returns a file's true name}
Procedure TrueName(FileName,TrueFileName: PChar);
 {Returns a file's short name (8.3); should be used only
  under Windows '95}
Procedure ShortName(FileName,ShortFileName: PChar);
 {Generates a short name (8.3) for a long file name; should
  be used only under Windows '95}
Procedure LongToShort(FileName,ShortFileName: PChar);
 {Deletes a file}
Procedure Delete(FileName: PChar);
 {Renames a file; can move a file between directories on the same drive}
Procedure Rename(FileName,NewName: PChar);
 {Deletes any bytes from the position in the file to its end}
Procedure Truncate(Handle: THandle);
 {Flushes any file buffers}
Procedure Commit(Handle: THandle);
 {Closes a file, writing any changes}
Procedure Close(Handle: THandle);
 {Reads a block of bytes to a buffer}
Function BlockRead(Handle: THandle; Var Buff; Count: TWord): TWord;
 {Writes a block of bytes to a file}
Function BlockWrite(Handle: THandle; Var Buff; Count: TWord): TWord;
 {Locks a drive to allow direct drive accesses}
Procedure LockDrive(Drive: TChar);
 {Unlocks a drive to disallow direct drive accesses}
Procedure UnlockDrive(Drive: TChar);
 {Changes the current drive}
Procedure ChangeDrive(Drive: TChar);
 {Returns the current drive}
Function CurrentDrive: TChar;
 {Disables a drive, rendering it completely inaccessible until reenabled}
Procedure DisableDrive(Drive: TChar);
 {Enables a previously disabled drive}
Procedure EnableDrive(Drive: TChar);
 {Turns a FLOPPY drive's led on}
Procedure TurnLedOn(Drive: TChar);
 {Turns a FLOPPY drive's led off}
Procedure TurnLedOff(Drive: TChar);
 {Returns a drive's information}
Function DriveInformation(Drive: TChar; Var DriveType: TByte; Volume: TPointer; Var Serial,TotalSpace,FreeSpace,
                           ClusterSize: TDouble): TBoolean;
 {Returns the amount of bytes free on a drive}
Function DiskFree(Drive: TChar): TDouble;
 {Returns the total amount of bytes used on a drive}
Function DiskSize(Drive: TChar): TDouble;
 {Resets a drive, flushing its buffers}
Procedure ResetDrive(Drive: TChar);
 {Quits from the calling program}
Procedure Halt(ErrorLevel: TByte);
 {Runs another program; READ NOTE IN THE CODE ITSELF!}
Procedure Exec(Prog,Params: PChar);
 {Sets the data transfer area; not to be changed normally}
Procedure SetDTA(Address: TPointer);
 {Returns the data transfer area's address}
Function GetDTA: TPointer;
 {Finds the first file; able to process long filenames; should be
  used ONLY under Windows '95}
Procedure FindFirst95(FileSpec: PChar; Attr: TByte; Var Search: TSearch95);
 {Returns the next file; should be
  used ONLY under Windows '95}
Procedure FindNext95(Var Search: TSearch95);
 {Closes a file search; MUST be done at the end of a search; should be
  used ONLY under Windows '95}
Procedure FindClose95(Var Search: TSearch95);
 {Finds the first file}
Procedure FindFirst(FileSpec: PChar; Attr: TWord; Var Search: TSearch);
 {Finds the next file}
Procedure FindNext(Var Search: TSearch);
 {Moves 4 bytes in each move; much faster; (80386 processors
  and faster ONLY)}
Procedure Move32(Var Source,Target; Len: TWord);


Implementation uses UMulti,Strings; {This is of course the Strings unit
                                     you got with your Borland/Turbo Pascal.
                                     The UMulti unit is at the end of this
                                     file. Compile if first.}

Var DTA: TPointer;
    ParameterBlock: TPointer;
    Block: Array [1..40] Of TByte;

Procedure Move32(Var Source,Target; Len: TWord); Assembler;
Asm
  Push          Ds
  Mov           Cx,Len
  Jcxz         @End
  Lds           Si,Source
  Les           Di,Target
  Cld
  ShR           Cx,1
  Jnc          @Sw
  MovSb
 @Sw:
  Shr           Cx,1
  Jnc          @Sd
  MovSw
 @Sd:
  Db            66h,0F3h,0A5h {Rep MovSd}
 @End:
  Pop           Ds
End;

Procedure CreateDir(PathName: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,7139h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,3900h
 @Use95:
  Lds           Dx,PathName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure RemoveDir(PathName: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,713Ah
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,3A00h
 @Use95:
  Lds           Dx,PathName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure ChangeDir(PathName: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,713Bh
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,3B00h
 @Use95:
  Lds           Dx,PathName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure CurrentDir(CurDir: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,7147h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,4700h
 @Use95:
  Xor           Dl,Dl
  Lds           Si,CurDir
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure ChangePath(PathName: PChar); Assembler;
Asm
  Push          Ds
  Lds           Si,PathName
  LodSw
  Cmp           Ah,':'
  Jne          @NoDrive
  Cmp           Al,'A'
  Jb           @NoUpper
  Cmp           Al,'Z'
  Ja           @NoUpper
  Sub           Al,20h
 @NoUpper:
  Xor           Ah,Ah
  Push          Ax
  Call          ChangeDrive
 @NoDrive:
  Lds           Si,PathName
  LodSw
  Cmp           Ah,':'
  Jne          @Added
  Dec           Si
  Dec           Si
 @Added:
  Mov           Ax,Ds
  Mov           Es,Ax
  Pop           Ds
  Push          Es
  Push          Si
  Call          ChangeDir
 @End:
End;

Procedure Subst(Drive: TChar; PathName: PChar); Assembler;
Asm
  Push          Ds
  Cmp           Using95,True
  Jne           @End
  Mov           Ax,71AAh
  Xor           Bh,Bh
  Mov           Bl,Drive
  Sub           Bl,64
  Lds           Dx,PathName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure QuerySubst(Drive: TChar; Var PathName: PChar); Assembler;
Asm
  Push          Ds
  Cmp           Using95,True
  Jne           @End
  Mov           Ax,71AAh
  Mov           Bh,02h
  Mov           Bl,Drive
  Sub           Bl,64
  Lds           Dx,PathName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure DeleteSubst(Drive: TChar); Assembler;
Asm
  Cmp           Using95,True
  Jne           @End
  Mov           Ax,71AAh
  Mov           Bh,01h
  Mov           Bl,Drive
  Sub           Bl,64
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Function Create(FileName: PChar): THandle; Assembler;
Asm
  Push          Ds
  Mov           Ax,716Ch
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,6C00h
 @Use95:
  Mov           Bl,Byte Ptr FileMode
  Mov           Bh,32
  Mov           Cx,Word Ptr CreateAttr
  Mov           Dx,0000000000010000b
  Lds           Si,FileName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Function Replace(FileName: PChar): THandle; Assembler;
Asm
  Push          Ds
  Mov           Ax,716Ch
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,6C00h
 @Use95:
  Mov           Bl,Byte Ptr FileMode
  Mov           Bh,32
  Mov           Cx,32
  Mov           Dx,0000000000010010b
  Lds           Si,FileName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Function Open(FileName: PChar): THandle; Assembler;
Asm
  Push          Ds
  Mov           Ax,716Ch
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,6C00h
 @Use95:
  Mov           Bl,Byte Ptr FileMode
  Mov           Bh,32
  Mov           Cx,32
  Mov           Dx,0000000000000001b
  Lds           Si,FileName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Function Duplicate(Handle: THandle): THandle; Assembler;
Asm
  Mov           Ah,45h
  Mov           Bx,Word Ptr Handle
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Function Seek(Handle: THandle; Position: TDouble; Origin: TByte): TDouble; Assembler;
Asm
  Mov           Ah,42h
  Mov           Al,Byte Ptr Origin
  Mov           Bx,Word Ptr Handle
  Mov           Cx,Word Ptr Position
  Mov           Dx,Word Ptr Position+2
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Function FilePos(Handle: THandle): TDouble; Assembler;
Asm
  Mov           Ah,42h
  Mov           Al,foCurrent
  Mov           Bx,Word Ptr Handle
  Xor           Cx,Cx
  Xor           Dx,Dx
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
  Xor           Dx,Dx
 @End:
End;

Function FileSize(Handle: THandle): TDouble; Assembler;
Var FPos: TDouble;
Asm
  Push          Word Ptr Handle
  Call          FilePos
  Cmp           Word Ptr flError,0
  Jne          @Error
  Mov           Word Ptr FPos,Dx
  Mov           Word Ptr FPos+2,Ax
  Mov           Ah,42h
  Mov           Al,foEnd
  Mov           Bx,Word Ptr Handle
  Xor           Cx,Cx
  Xor           Dx,Dx
  Int           21h
  Jc           @Error
  Pusha
  Mov           Ah,42h
  Mov           Al,foStart
  Mov           Bx,Word Ptr Handle
  Mov           Cx,Word Ptr FPos
  Mov           Dx,Word Ptr FPos+2
  Int           21h
  Jnc          @End
 @Error:
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
  Xor           Dx,Dx
 @End:
  Popa
End;

Function FSplit(Path,Dir,Name,Ext: PChar): TByte;
{Based on the Borland Pascal run-time library and EnhancedDos (Andrew Eigus);
 Modified for long filename support by Gil Shapira}
Var DirLen,NameLen,Flags: TWord;
    NamePtr,ExtPtr: PChar;
Begin
 NamePtr:=StrRScan(Path,'\');
 If (NamePtr=Nil) Then NamePtr:=StrRScan(Path,':');
 If (NamePtr=Nil) Then NamePtr:=Path Else Inc(NamePtr);
 ExtPtr:=StrScan(NamePtr,'.');
 If (ExtPtr=Nil) Then ExtPtr:=StrEnd(NamePtr);
 DirLen:=NamePtr-Path;
 NameLen:=ExtPtr-NamePtr;
 Flags:=0;
 If (StrScan(NamePtr,'?')<>Nil) Or (StrScan(NamePtr,'*')<>Nil) Then Flags:=fcWildcards;
 If (DirLen<>0) Then Flags:=Flags Or fcDirectory;
 If (NameLen<>0) Then Flags:=Flags Or fcFilename;
 If (ExtPtr[0]<>#0) Then Flags:=Flags Or fcExtension;
 If (Dir<>Nil) Then StrLCopy(Dir,Path,DirLen);
 If (Name<>Nil) Then StrLCopy(Name,NamePtr,NameLen);
 If (Ext<>Nil) Then StrLCopy(Ext,ExtPtr,4);
 FSplit:=Flags;
End;

Procedure FExpand(Path,Result: PChar); Assembler;
Asm
  Push	        Ds
  Cld
  Lds	        Si,Path
  Push          Ds
  Push          Si
  Call          StrLen
  Mov           Cx,Ax
  Add	        Cx,Si
  Les	        Di,Result
  LodSw
  Cmp	        Si,Cx
  Ja	       @1
  Cmp	        Ah,':'                  {If DriveLetter not present...}
  Jne          @1                       {use default drive}
  Cmp           Al,'a'                  {If DriveLetter below 'a'...}
  Jb	       @2
  Cmp	        Al,'z'                  {or above 'z'...}
  Ja	       @2                       {jump...}
  Sub	        Al,20h                  {or else make it uppercase...}
  Jmp	       @2                       {and jump}
 @1:                                    {Get current drive}
  Dec	        Si
  Dec	        Si
  Mov	        Ah,19h
  Int	        21h
  Add	        Al,'A'
  Mov	        Ah,':'
 @2:
  StoSw                                 {Write drive letter}
  Cmp	        Si,Cx                   {If source is only drive letter...}
  Je	       @21                      {jump...}
  Cmp	        Byte Ptr [Si],'\'       {if it includes path...}
  Je	       @3                       {jump}
 @21:                                   {Get current directory}
  Sub	        Al,'A'-1
  Mov	        Dl,Al
  Mov	        Al,'\'
  StoSb
  Push	        Si
  Push	        Ds
  Mov	        Ax,7147h
  Mov	        Si,Di
  Push	        Es
  Pop	        Ds
  Int	        21h
  Pop	        Ds
  Pop	        Si
  Jc	       @3
  Cmp	        Byte Ptr Es:[Di],0
  Je	       @3
  Push	        Cx
  Mov	        Cx,-1
  Xor	        Al,Al
  RepNe	        ScaSb
  Dec	        Di
  Mov	        Al,'\'
  StoSb
  Pop	        Cx
 @3:
  Sub   	Cx,Si
  Rep	        MovSb
  Xor	        Al,Al
  StoSb
  Lds	        Si,Result
  Mov	        Di,Si
  Push	        Di
 @4:
  LodSb
  Or	        Al,Al
  Je	       @6
  Cmp	        Al,'\'
  Je	       @6
  Cmp	        Al,'a'
  Jb	       @5
  Cmp	        Al,'z'
  Ja	       @5
 @5:
  StoSb
  Jmp	       @4
 @6:
  Cmp	        Word Ptr [Di-2],'.\'
  Jne	       @7
  Dec	        Di
  Dec	        Di
  Jmp	       @9
 @7:
  Cmp	        Word Ptr [Di-2],'..'
  Jne	       @9
  Cmp	        Byte Ptr [Di-3],'\'
  Jne	       @9
  Sub	        Di,3
  Cmp	        Byte Ptr [Di-1],':'
  Je	       @9
 @8:
  Dec	        Di
  Cmp	        Byte Ptr [Di],'\'
  Jne	       @8
 @9:
  Or	        Al,Al
  Jne	       @5
  Cmp	        Byte Ptr [Di-1],':'
  Jne	       @10
  Mov	        Al,'\'
  StoSb
 @10:
  Xor           Al,Al
  StoSb
  Pop           Di
  Pop	        Ds
End;

Function GetFileAttr(FileName: PChar): TByte; Assembler;
Asm
  Push          Ds
  Mov           Ax,7143h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,4300h
 @Use95:
  Xor           Bl,Bl
  Lds           Dx,FileName
  Int           21h
  Pop           Ds
  Jnc          @OK
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
  Jmp          @End
 @OK:
  Mov           Ax,Cx
 @End:
End;

Procedure SetFileAttr(FileName: PChar; Attr: TByte); Assembler;
Asm
  Push          Ds
  Mov           Ax,7143h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,4301h
 @Use95:
  Mov           Bl,01h
  Mov           Cl,Byte Ptr Attr
  Xor           Ch,Ch
  Lds           Dx,FileName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure TrueName(FileName,TrueFileName: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,7160h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,6000h
 @Use95:
  Mov           Cx,0002h
  Lds           Si,FileName
  Les           Di,TrueFileName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure ShortName(FileName,ShortFileName: PChar); Assembler;
Asm
  Push          Ds
  Cmp           Using95,True
  Jne          @End
  Mov           Ax,7160h
  Mov           Cx,0001h
  Lds           Si,FileName
  Les           Di,ShortFileName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure LongToShort(FileName,ShortFileName: PChar); Assembler;
Asm
  Cld
  Push          Ds
  Mov           Ax,71A8h
  Cmp           Using95,True
  Jne          @End
  Lds           Si,FileName
  Les           Di,ShortFileName
  Xor           Dx,Dx
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure Delete(FileName: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,7141h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,4100h
 @Use95:
  Lds           Dx,FileName
  Mov           Si,0001h
  Mov           Cl,Byte Ptr DeleteAttr
  Xor           Ch,Ch
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure Rename(FileName,NewName: PChar); Assembler;
Asm
  Push          Ds
  Mov           Ax,7156h
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,5600h
 @Use95:
  Lds           Dx,FileName
  Les           Di,NewName
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure Close(Handle: THandle); Assembler;
Asm
  Mov           Ah,3Eh
  Mov           Bx,Word Ptr Handle
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure Truncate(Handle: THandle); Assembler;
Asm
  Push          Ds
  Mov           Ah,40h
  Mov           Bx,Word Ptr Handle
  Xor           Cx,Cx
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure Commit(Handle: THandle); Assembler;
Asm
  Mov           Ah,68h
  Mov           Bx,Word Ptr Handle
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Function BlockRead(Handle: THandle; Var Buff; Count: TWord): TWord; Assembler;
Asm
  Push          Ds
  Mov           Ah,3Fh
  Mov           Bx,Word Ptr Handle
  Mov           Cx,Count
  Jcxz         @End
  Lds           Dx,Buff
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Function BlockWrite(Handle: THandle; Var Buff; Count: TWord): TWord; Assembler;
Asm
  Push          Ds
  Mov           Ah,40h
  Mov           Bx,Word Ptr Handle
  Mov           Cx,Count
  Jcxz         @End
  Lds           Dx,Buff
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Procedure LockDrive(Drive: TChar); Assembler;
Asm
  Mov           Ax,440Dh
  Mov           Cx,084Ah
  Mov           Bl,Drive
  Sub           Bl,'@'
  Mov           Bh,Byte Ptr LockLevel
  Mov           Dx,0000000000000001b
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure UnlockDrive(Drive: TChar); Assembler;
Asm
  Mov           Ax,440Dh
  Mov           Cx,086Ah
  Mov           Bl,Drive
  Sub           Bl,'@'
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure ChangeDrive(Drive: TChar); Assembler;
Asm
  Mov           Ah,0Eh
  Mov           Dl,Byte Ptr Drive
  Sub           Dl,'A'
  Int           21h
End;

Function CurrentDrive: TChar; Assembler;
Asm
  Mov           Ah,19h
  Int           21h
  Add           Al,'A'
End;

Procedure EnableDrive(Drive: TChar); Assembler;
Asm
  Mov           Ax,5F07h
  Mov           Dl,Byte Ptr Drive
  Sub           Dl,'A'
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Procedure DisableDrive(Drive: TChar); Assembler;
Asm
  Mov           Ax,5F08h
  Mov           Dl,Byte Ptr Drive
  Sub           Dl,'A'
  Int           21h
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
  Xor           Ax,Ax
 @End:
End;

Procedure FindFirst95(FileSpec: PChar; Attr: TByte; Var Search: TSearch95); Assembler;
Asm
  Push          Ds
  Mov           Ax,714Eh
  Xor           Si,Si
  Xor           Ch,Ch
  Mov           Cl,Attr
  Lds           Dx,FileSpec
  Les           Di,Search
  Inc           Di
  Inc           Di
  Int           21h
  Dec           Di
  Dec           Di
  StoSw
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure FindNext95(Var Search: TSearch95); Assembler;
Asm
  Push          Ds
  Lds           Si,Search
  LodSw
  Mov           Bx,Ax
  Mov           Ax,714Fh
  Xor           Si,Si
  Les           Di,Search
  Inc           Di
  Inc           Di
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure FindClose95(Var Search: TSearch95); Assembler;
Asm
  Push          Ds
  Lds           Si,Search
  LodSw
  Mov           Bx,Ax
  Mov           Ax,71A1h
  Int           21h
  Pop           Ds
  Jnc          @End
  Mov           flError,Ax
  Mov           isError,True
 @End:
End;

Procedure FindFirst(FileSpec: PChar; Attr: TWord; Var Search: TSearch); Assembler;
Asm
  Push          Ds
  Mov           Ah,4Eh
  Mov           Cx,Attr
  Lds           Dx,FileSpec
  Int           21h
  Jnc          @Transfer
  Mov           flError,Ax
  Mov           isError,True
  Jmp          @End
 @Transfer:
  Les           Si,DTA
  Push          Es
  Push          Si
  Les           Si,Search
  Push          Es
  Push          Si
  Push          43
  Call          Move32
 @End:
  Pop           Ds
End;

Procedure FindNext(Var Search: TSearch); Assembler;
Asm
  Push          Ds
  Les           Si,Search
  Push          Es
  Push          Si
  Les           Si,DTA
  Push          Es
  Push          Si
  Push          43
  Call          Move32
  Mov           Ah,4Fh
  Int           21h
  Jnc          @Transfer
  Mov           flError,Ax
  Mov           isError,True
  Jmp          @End
 @Transfer:
  Les           Si,DTA
  Push          Es
  Push          Si
  Les           Si,Search
  Push          Es
  Push          Si
  Push          43
  Call          Move32
 @End:
  Pop           Ds
End;

Procedure Halt(ErrorLevel: TByte); Assembler;
Asm
  Mov           Ah,4Ch
  Mov           Al,Byte Ptr ErrorLevel
  Int           21h
End;

Procedure Exec(Prog,Params: PChar); Assembler;
{For some reason, you need to add a space before the Params
 string. For example:

 To run:
   C:\COMMAND.COM /C DIR C:\
 The variables need to be like this:
   Prog:='C:\COMMAND.COM';
   Params:=' /C DIR C:\';   {Notice the space before the /C}

Var ShortFileName: PChar;
Asm
  Push          Ds
{Building ParameterBlock}
  Cld
  Les           Di,ParameterBlock
  Lds           Si,Params
  Inc           Di
  Inc           Di
  Mov           Ax,Si
  StoSw
  Mov           Ax,Ds
  StoSw
  Db            86h,0D0h,90h,86h,0C2h,86h,0C9h
  Pop           Ds
  Push          Ds
  Cmp           Using95,True
  Je           @Use95
  Lds           Dx,Prog
  Jmp          @OK
 @Use95:
{Getting short filename}
  Mov           Ax,7160h
  Mov           Cx,0001h
  Lds           Si,Prog
  Les           Di,ShortFileName
  Int           21h
  Lds           Dx,ShortFileName
  Jc           @End
{Executing}
 @OK:
  Les           Bx,ParameterBlock
  Mov           Ah,4Bh
  Xor           Al,Al
  Int           21h
 @End:
  Pop           Ds
End;

Procedure SetDTA(Address: Pointer); Assembler;
Asm
  Push          Ds
  Mov           Ah,1Ah
  Lds           Dx,Address
  Int           21h
  Pop           Ds
End;

Function GetDTA: Pointer; Assembler;
Asm
  Mov           Ah,2Fh
  Int           21h
  Mov           Dx,Es
  Mov           Ax,Bx
End;

Function DriveInformation(Drive: TChar; Var DriveType: TByte; Volume: TPointer; Var Serial,TotalSpace,FreeSpace,
                           ClusterSize: TDouble): TBoolean; Assembler;
Asm
  Push          Ds
  Mov           Ax,440Dh
  Mov           Bl,Drive
  Sub           Bl,64
  Mov           Cx,0860h
  Lds           Dx,ParameterBlock
  Int           21h
  Mov           Al,1
  Jnc          @Continue
  Xor           Al,Al
  Jmp          @Error
 @Continue:
  Mov           Si,Dx
  Inc           Si
  LodSb
  Les           Di,DriveType
  StoSb
  Pop           Ds
  Push          Ds
  Les           Di,ParameterBlock
  Xor           Ax,Ax
  StoSw
  Lds           Dx,ParameterBlock
  Mov           Ax,440Dh
  Mov           Bl,Drive
  Sub           Bl,64
  Mov           Cx,0866h
  Int           21h
  Mov           Si,Dx
  Inc           Si
  Inc           Si
  Les           Di,Serial
  Dw            0A566h
  Les           Di,Volume
  Dw            0A566h
  Dw            0A566h
  MovSw
  MovSb
  Mov           Ah,36h
  Mov           Dl,Drive
  Sub           Dl,64
  Int           21h
  Push          Dx
  Push          Ax
  Mul           Cx
  Les           Di,ClusterSize
  StoSw
  Mov           Ax,Dx
  StoSw
  Pop           Ax
  Push          Ax
  Mul           Cx
  Mul           Bx
  Les           Di,FreeSpace
  StoSw
  Mov           Ax,Dx
  StoSw
  Pop           Ax
  Pop           Dx
  Mov           Bx,Dx
  Mul           Cx
  Mul           Bx
  Les           Di,TotalSpace
  StoSw
  Mov           Ax,Dx
  StoSw
  Mov           Al,1
 @Error:
  Pop           Ds
End;

Function DiskFree(Drive: TChar): TDouble; Assembler;
Asm
  Mov           Ah,36h
  Mov           Dl,Drive
  Sub           Dl,64
  Int           21h
  Cmp           Ax,0FFFFh
  Je           @Error
  Mul           Cx
  Mul           Bx
  Jmp          @End
 @Error:
  Mov           Dx,Ax
 @End:
End;

Function DiskSize(Drive: TChar): TDouble; Assembler;
Asm
  Mov           Ah,36h
  Mov           Dl,Drive
  Sub           Dl,64
  Int           21h
  Cmp           Ax,0FFFFh
  Je           @Error
  Mul           Cx
  Mul           Dx
  Jmp          @End
 @Error:
  Mov           Dx,Ax
 @End:
End;

Procedure ResetDrive(Drive: TChar); Assembler;
Asm
  Mov           Ax,710Dh
  Cmp           Using95,True
  Je           @Use95
  Mov           Ax,0D00h
 @Use95:
  Mov           Cx,01h
  Xor           Dh,Dh
  Mov           Dl,Drive
  Sub           Dx,65
  Int           21h
End;

Procedure TurnLedOn(Drive: TChar); Assembler;
Asm
  Mov           Al,Drive
  Sub           Al,65
  Mov           Cl,Al
  Add           Cl,4
  Mov           Ah,1
  ShL           Ah,Cl
  Add           Al,Ah
  Add           Al,12
  Mov           Dx,03F2h
  Out           Dx,Al
End;

Procedure TurnLedOff(Drive: TChar); Assembler;
Asm
  Mov           Al,Drive
  Sub           Al,53
  Mov           Dx,03F2h
  Out           Dx,Al
End;


Begin
 CreateAttr:=faArchive;
 FindAttr:=faArchive Or faReadOnly;
 CopyAttr:=faArchive Or faReadOnly;
 DeleteAttr:=faArchive;
 FileMode:=fmReadWrite;
 FillChar(Block,40,$00);
 ParameterBlock:=@Block;
 LockLevel:=0;
 Using95:=(Task.OS=osWin95);
 DTA:=GetDTA;
End.

(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)
(* UMulti - multitasker support unit *)
(*        Compile this first         *)

Unit UMulti;

Interface uses UGlobal;

Const Tasker: Array [0..10] Of String[9] = ('DOS','Windows ''95','Windows','OS/2','DesqView','TopView','DoubleDos',
                                            'NetWare','MultiLink','CSwitch','EuroDOS');

Const osDOS = 0;
      osWin95 = 1;
      osWindows = 2;
      osOS2 = 3;
      osDesqView = 4;
      osTopView = 5;
      osDoubleDos = 6;
      osNetWare = 7;
      osMultiLink = 8;
      osCSwitch = 9;
      osEuroDOS = 10;

Type TaskRec = Record
      OS: Word;
      Version: Word;
      Delay: Word;
     End;

Const Task: TaskRec = (OS: 0;
                       Version: 0;
                       Delay: 100);

{ Call  GiveTimeSlice  to release CPU cycles to the multitasker. }

{ Polling  could be use as procedure to be used inside ReadKey procedures
  to read the clock, update the screen, and release CPU cycles. Polling is
  at startup the same as GiveTimeSlice }

Var GiveTimeSlice,
    Polling: TProc;

{ AssignProcs  is called automatically by the startup procedure Init }
Procedure AssignProcs;

{ ReleaseTime is a macro procedure which takes only 7 bytes, and releases
  DOS, Windows, Windows '95, and OS/2 timeslices }
Procedure ReleaseTime; Inline($CD/$28/$B8/$80/$16/$CD/$2F);

Implementation

{$F+}
Procedure NetWare_GTS; Assembler;
Asm
  Mov           Bx,000Ah
  Int           7Ah
End;

Procedure DoubleDOS_GTS; Assembler;
Asm
  Mov           Ax,0EE02h
  Int           21h
End;

Procedure Windows_Win95_OS2_GTS; Assembler;
Asm
  Mov           Ax,1680h
  Int           2Fh
End;

Procedure DesqView_TopView_GTS; Assembler;
Asm
  Mov           Ax,1000h
  Int           15h
End;

Procedure DOS_GTS; Assembler;
Asm
  Int           28h
End;

Procedure MultiLink_GTS; Assembler;
Asm
  Mov           Ah,02h
  Int           7Fh
End;

Procedure CSwitch_GTS; Assembler;
Asm
  Mov           Ah,01h
  Int           62h
End;

Procedure EuroDOS_GTS; Assembler;
Asm
  Mov           Ah,89h
  Xor           Cx,Cx
  Int           21h
End;
{$F-}

Procedure AssignProcs;
Begin
 Case Task.OS Of
  osDos: GiveTimeSlice:=DOS_GTS;
  osWin95: GiveTimeSlice:=Windows_Win95_OS2_GTS;
  osWindows: GiveTimeSlice:=Windows_Win95_OS2_GTS;
  osOS2: GiveTimeSlice:=Windows_Win95_OS2_GTS;
  osDesqView: GiveTimeSlice:=DesqView_TopView_GTS;
  osTopView: GiveTimeSlice:=DesqView_TopView_GTS;
  osDoubleDos: GiveTimeSlice:=DoubleDOS_GTS;
  osNetWare: GiveTimeSlice:=NetWare_GTS;
  osMultiLink: GiveTimeSlice:=MultiLink_GTS;
  osCSwitch: GiveTimeSlice:=CSwitch_GTS;
  osEuroDOS: GiveTimeSlice:=EuroDOS_GTS;
 End;
End;

Procedure Init; Assembler;
Asm
  Mov           Task.OS,00h
  Mov           Task.Version,00h
  Mov           Ah,87h
  Xor           Al,Al
  Int           21h
  Cmp           Al,0
  Jne          @EuroDOS
  Mov           Ah,30h
  Mov           Al,01h
  Int           21h
  Cmp           Al,14h
  Je           @OS2
  Mov           Ax,160Ah
  Int           2Fh
  Cmp           Ax,00h
  Je           @Windows
  Mov           Ax,1022h
  Mov           Bx,0000h
  Int           15h
  Cmp           Bx,00h
  Jne          @DesqView
  Mov           Ah,2Bh
  Mov           Al,01h
  Mov           Cx,4445h
  Mov           Dx,5351h
  Int           21h
  Cmp           Al,0FFh
  Jne          @TopView
  Mov           Ax,0E400h
  Int           21h
  Cmp           Al,00h
  Jne          @DoubleDos
  Mov           Ax,7A00h
  Int           2Fh
  Cmp           Al,0FFh
  Je           @NetWare
  Jmp          @End
 @Windows:
  Cmp           Bh,04h
  Jne          @Win3
  Mov           Task.OS,01h
  Jmp          @Windows_OK
 @Win3:
  Mov           Task.OS,02h
 @Windows_OK:
  Mov           Task.Version,Bx
  Jmp          @End
 @OS2:
  Mov           Task.OS,03h
  Mov           Bh,Ah
  Xor           Ah,Ah
  Mov           Cl,0Ah
  Div           Cl
  Mov           Ah,Bh
  XChg          Ah,Al
  Mov           Task.Version,Ax
  Jmp          @End
 @DesqView:
  Mov           Task.OS,04h
  Jmp          @End
 @TopView:
  Mov           Task.OS,05h
  Jmp          @End
 @DoubleDos:
  Mov           Task.OS,06h
  Jmp          @End
 @NetWare:
  Mov           Task.OS,07h
  Jmp          @End
 @MultiLink:
  Mov           Task.OS,08h
  Jmp          @End
 @CSwitch:
  Mov           Task.OS,09h
  Jmp          @End
 @EuroDOS:
  Mov           Task.OS,10h
 @End:
  Call          AssignProcs
End;

Begin
 Init;
 Polling:=GiveTimeSlice;
End.

[Back to FILES SWAG index]  [Back to Main SWAG index]  [Original]