

  {--------------------------------------------------------------------}

  {-                        LFN.PAS v1.10                             -}

  {-          Support of long filenames under Win95/98 for            -}

  {-              TP6, TP/BP7 und compatible compilers.               -}

  {-             Written by Andreas Killer, Germany, NRW              -}

  {-      homepage: http://home.t-online.de/home/andreas.killer       -}

  {--------------------------------------------------------------------}



List of contents

  1. General description

  2. Functionality of LFN

  3. Original routines

  4. Alternate routines that replaces others

  5. Special case DISKFREE/DISKSIZE

  6. Special case PARAMSTR/PARAMCOUNT  GETARGSTR/GETARGCOUNT

  7. Special case ASSIGN

  8. Notice to UseDos/UseWinDos/CompatToDos

  9. Notice to UseXXXXSharingFlags

 10. About myself and this unit :)



  {--------------------------------------------------------------------}



1. General description



  After integrating this unit all default-pascal-routines will have the

  ability to work with long filenames.



  This unit will detect automatically if Win95 or above is running and will

  disable ALL routines if not. If you have an OS that is compatible with

  Win95 but not detectable by this unit you can force LFN to enable the

  routines by calling procedure EnableLFN.



  If a routine checks that it is not supported by the OS, so the routine will

  disable itself automatically and call the original from unit System/Dos or

  WinDos.



  All extended routines ("Section 2" in the interface) of this unit are

  available under MSDOS and changes long filenames in their short 8.3 form.



  {--------------------------------------------------------------------}



2. Functionality of LFN



  To make this possible LFN determines at runtime the CALL FAR's of the

  routines in the unit System and gets a pointer to their code. After that

  LFN saves the first 9 bytes of this code and places a JMP FAR to the

  corresponding routine in LFN.



  This means that if you call a RESET during operation, your program makes a

  CALL to System.RESET, but the "first line" reads "JMP FAR to

  LFN.Win95Reset".



  If a routine detects that it isn't supported by the OS, LFN will replace

  the previously saved code and makes a JMP FAR to it.



  The only exceptions are very few routines from the Dos/WinDos unit which

  are meant to be substitutes for others, i.E.: FINDFIRST. These routines

  have other parameters than the original ones and so it's not possible to

  patch them.



  To prevent you from changing your own programs all these routines have the

  same names as in the Dos/WinDos unit.



  If such a routine detects that it is not used it will be marked and the

  original routine will be called from there on.



  {--------------------------------------------------------------------}



3. Original routines



  These routines are DIRECTLY taken from this unit and support the long

  filenames with Win95:



    - unit System :

      MkDir, RmDir, ChDir, GetDir,

      Assign, Reset, Rewrite, Append, Erase, Rename,

      ParamCount, ParamStr



  {$IFDEF UseDos}

    - unit Dos :

      GetFAttr, SetFAttr, GetFTime, SetFTime, GetEnv

  {$ENDIF}



  {$IFDEF UseWinDos}

    - unit WinDos :

      CreateDir, RemoveDir, SetCurDir, GetCurDir,

      GetArgCount, GetArgStr,

      GetFAttr, SetFAttr, GetFTime, SetFTime,

      FileExpand, FileSplit,

  {$ENDIF}



  Further routines which are directly connected with the routines above



   - unit System :

     Truncate, Flush, Read, Write, ReadLn, WriteLn,

     BlockRead, BlockWrite, Seek, FileSize, FilePos,



   - unit Dos/WinDos :

     UnpackTime, PackTime



  can be used without any restriction and gets the expected results.



  {--------------------------------------------------------------------}



4. Alternate routines that replaces others



  It is not necessary to put the LFN-Unit into the "USES"-clause in any of

  your units that do not use one of the alternate routines.



  The alternate routines are:



    FindFirst, FindNext, FindClose, FSplit, FExpand, DiskFree, DiskSize



  All alternate routines have the same names as the routines in Dos/WinDos so

  it is not necessary to rewrite your program.



  If you use the LFN unit and unit Dos/WinDos and you use on of the alternate

  routines, so you must place the LFN behind these unit in the USES-clause:

  uses Dos, WinDos, LFN;



  {--------------------------------------------------------------------}



5. Special case DISKFREE/DISKSIZE



  These function's are now able to work on drives larger than 2Gb and return

  the correct results. You can control the returned value by changing the

  DEFINE's: DFSReturnComp and DFSReturnKb.



  Any combinations are possible:



  {$IFDEF DFSReturnComp}

    {$IFDEF DFSReturnKb}

       The returned value is COMP and the result will be in Kb

    {$ELSE}

       The returned value is COMP and the result will be in Byte

    {$ENDIF}

  {$ELSE}

    {$IFDEF DFSReturnKb}

       The returned value is LONGINT and the result will be in Kb

    {$ELSE}

       The returned value is LONGINT and the result will be in Byte

    {$ENDIF}

  {$ENDIF}



  Both DEFINE's are disabled by default to make LFN compatibel to your

  existing programs. But if the result is too large to place it in a LongInt

  both functions will return MaxLongInt in this case.



  Note: DiskFree/DiskSize use the AX=$7303/INT $21 call. These function will

  work properly under Windows/DOS7.x, but if you develop a program in the IDE

  (Turbo or BP), then the correct result is only returned after the first

  call of the program. I dont know why this happens.



  {--------------------------------------------------------------------}



6. Special case PARAMSTR/PARAMCOUNT  GETARGSTR/GETARGCOUNT



  If you place filenamens in commandline that HAS BLANKS than you must pad

  this name in "", i.E.: This is "my file" with blanks.



  ParamCount and ParamStr will note this and return "my file" as one

  parameter but without the "".



  If there are some non-blanks padded around a " these chars will be added to

  the current parameter. For example: To get "C:\Program Files\" as one

  parameter (without the "") this variants are possible:



    "C:\Program Files\"

    "C:\Program Files"\

    C:\"Program Files"\

    C:\"Program Files\"



  The priority of more than one different delimiters are valued in the order

  of there appearence.



  If you dont want this feature you can disable it by saying

    ParamDelims:= [];

  and the normal reaction will occur. Of course you can place your own

  delimiters in here if you want. In this case and/or if you plan to evaluate

  the commandline by yourself you can use the functions ParamLine and

  ParamPosition.



  All Param...-function (not ParamLine) evaluate the pointer namend ParamPtr.



  It is also possible to read commandlines from a file and evaluate it with

  ParamStr/ParamCount. For an example and better instruction to do this

  please have a look into EXREDIR.PAS.



  It's the same for GetArgCount/GetArgstr from unit WinDos.



  {--------------------------------------------------------------------}



7. Special case ASSIGN



  A problem will be filenames larger than 79 chars, because the filevariables

  TEXT and FILE can only hold smaller names. I used a little trick to make

  larger filenames possible that are only availble if you enable the DEFINE

  AssignLongName.



  If a filename is longer than 79 chars (and only then), ASSIGN will call the

  procedure AssignNew. LFN will make AssignNew point to LFNAssignNew (you can

  find this procedure in LFN.IN3 at the end) by initialisation.



  LFNAssignNew allocates a pointer at the heap that holds the complete

  filename as ASCIIZ. If not enough heapmemory is avaible then ASSIGN returns

  an IOResult 203: "Heap overflow".



  The pointer will be stored in the first 4 bytes in UserData-Field of a

  filevariable. If you use this field by your own LFN is not compatible to

  your program. Sorry.



  Since the filename's been saved on the heap its name has become available.  

  To make it easier for you to debug you programs ASSIGN creates a peudonym

  like this:

    [Drive]:\...\[FileName]

  I.E. you will get for

    Assign(F, 'C:\WINDOWS\Startmen\Programme\Internet\'+

              'Netscape Communicator\Hilfsprogramme\Profil-Manager.lnk');

  a name in the filevariable after ASSIGN like that:

    'C:\...\Profil-Manager.lnk'



  The deallocating of the filename can be made in 2 different ways selectable

  by the DEFINE AutoAssignDispose. If this DEFINE is disabled you have to

  call the procedure AssignDispose to deallocate it.



  AssignDispose points to the procedure LFNAssignDispose by default.



  If AutoAssignDispose is enabled CLOSE will automaticly call AssignDispose.

  Note: if you want to RESET/REWRITE/etc. the same file again you must call

  ASSIGN once again before doing so!



  If you don't want all these things, but still want to work with filenames

  longer than 79 chars you can set your procedures to AssignNew,

  AssignGetName and AssignDispose and store the filenames as ASCIIZ

  (important!) i.E. a single-linked list or a collection or something like

  that.



  A demonstration how you can do this is avaible in EXASSIGN.PAS.



  If the returned value from AssignGetName is NIL, so ASSIGN will figure that

  the name in the filevariable is valid.



  {--------------------------------------------------------------------}



8. Comments to UseDos/UseWinDos/CompatToDos



  In any case one of the units Dos/WinDos is used, although both DEFINEs

  UseDos/UseWinDos are disabled. (These are default settings.) In this case

  LFN will determine automatically witch unit shoud be used:



    {$IFDEF Windows} uses WinDos; {$ELSE} uses Dos; {$ENDIF}



  It is also possible to enable both DEFINEs und let LFN hook into it, but as

  there is no DOS.TPW LFN will use these rules:

  

    {$IFDEF Windows} uses WinDos; {$ELSE} uses WinDos, Dos; {$ENDIF}



  FINDFIRST exists in both units (Dos and WinDos) and LFN can't support both

  FINDFIRST's at a time. You can select the syntax of FINDFIRST by using the

  DEFINE CompatToDos if you want the layout for unit Dos (enabled) or for

  unit WinDos (disabled):



  {$IFDEF CompatToDos}

     procedure FindFirst(Path : String; Attr : Word; var F : SearchRec);

  {$ELSE}

     procedure FindFirst(Path : PChar; Attr : Word; var F : TSearchRec);

  {$ENDIF}



  If you enable only one of the DEFINE UseDos/UseWinDos LFN will choose the

  correct setting for CompatToDos automatically.



  {--------------------------------------------------------------------}



9. Notice to UseXXXXSharingFlags



  I've heard of problems that CLOSE generates an IOresult 6 (invalid file

  handle). Now I've figured out that it is possible i.E. to open the same

  file 2 times via REWRITE and write into it. Then if you close this file the

  second call to CLOSE will generate an RTE 6, because the filehandle is

  allready closed and no more avaible yet.



  These is obvious the result that FileMode is, more or not, ignored if a

  file is opened. However you can remedy this by setting a filesharingmode

  too.



  As this can also be done automatically, I implemented the 2 defines

  UseTEXTSharingFlag and UseFILESharingFlag that activates this feature

  (default setting). After access a file via Reset/Rewrite/etc. the old

  FileMode is restored and has is previous value.



  All other flags in FileMode are not affected.



  If the define UseTEXTSharingFlags ist enabled, then LFN will set these

  filesharingmodes automatically on filevariables which typ is TEXT:



     Operation ³ SharingFlag

     ÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄ

     Rewrite   ³ fmDenyRead

     Reset     ³ fmDenyWrite

     Append    ³ fmDenyRead



  If the define UseFILESharingFlags ist enabled, then LFN will set these

  filesharingmodes automatically on filevariables which typ is FILE:



     FileMode ³ SharingFlag

     ÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄ

        0     ³ fmDenyWrite

        1     ³ fmDenyRead

        2     ³ fmDenyAll



  To have a comparison over all possible fileaccesses and the results with

  and without LFN I left the program SHARERES in this package. Please try

  call it with SHARERES >RESULT (or else), because the output is very

  extensive.



  {--------------------------------------------------------------------}





10. About myself and this unit :)



  This is the last version of this unit because TP/BP is now an ancient

  compiler and this unit works IMHO perfectly on lokal systems.



  So now have a lot of fun working with LFN.



  Andreas Killer



