The LFN Library for Clipper is a set of functions for handling long file names. It is an original work by Klas Engwall and placed in the public domain. Source code is included, so you can change anything you want to make it better suit your needs. The LIB files included in the distribution are compiled with Clipper 5.2e, so you may need to recompile the source code if your environment is different.
Changes since the initial revision are listed here
Ian's approach was much more ambitious than my approach in this library, and his knowledge of the inner workings of Clipper and DOS is on an entirely different level than mine. So if Clipper had been more cooperative, his patch would have solved the LFN problem (except on NT4, which has no LFN support at all in the VDM) in a better way than I can offer.
But unfortunately Ian discovered that Clipper truncates file names after 16 characters, so in spite of all his work and clever solutions there was still a serious problem caused by Clipper itself. And judging from the readme files included in the last available beta version of his library (version 0.05), that was the reason he stopped development.
There have been many questions about LFN support on comp.lang.clipper in the years since, but as far as I know there is no other solution than Ian's DBLFN library publicly available. Until now (2002).
I spent a couple of weeks in June/July 2002 working on this project, and this is what I came up with. I call it the LFN Library. It has functions for creating, opening, renaming and erasing files with long names, for creating, renaming and erasing directories, for changing the current directory, for searching directories and a few other things. After the relase of the first beta version (Rev 0.90) on July 31 2002, I decided to migrate some routines to assembly in order to speed up executuion and also to try to add support for the extended get/set attributes DOS services (getting and setting file date, time and attributes). This support was added in Rev 0.91, and it was further extended in Rev 0.92, which also included a function for copying an existing file with a long file name to a new file. Rev 1.00 added a little more speed to that function by moving the read/write loop to assembly.
Over the years since 2002 I have added a few new functions to the library version I use internally and fixed a few minor things in the functions that existed in rev 1.00. After a question about LFN dbf files on comp.lang.clipper in September 2007 I decided to make a new public release of the things I have been added since 2002/2003.
The library comes with an almost complete demo application. It is included in the LIB file for convenience. It includes everything except the dbf/ntx/ndx handling functions. Just call it with "LFNdemo()" from your application and you will se what the LFN Library can do. LFNdemo() will restore the screen and the program settings when it returns control to your application.
The LFN Library did not originally have any direct support for using long file names with "Clipper's own" files, but this was changed in revision 1.10. Now it is possible to create and use dbf files with long file names as well as single index files (.ntx and .ndx). This is done by converting the long file names specified in the function calls to their short equivalents and then passing those short names on to Clipper's dbusearea(), dbcreateindex() and dbsetindex() functions respectively. Dbf files are created directly by calling the LFN library function LF_Fcreate() internally. There is still no support for cdx indexes.
On the subject of LFN support, it should be said that using long file names on the command line in a DOS box is a completely separate thing from using long file names in DOS applications running on the same computer. The "DOS boxes", if I may use that term to refer to the command line of both CMD.EXE (on NT-class operating systems) and COMMAND.COM, are Win32 console applications which can handle long file names because they use the Win32 API.
This does not necessarily mean that there is also support for the DOS LFN services, which are what we must use from inside a DOS application to get the same functionality. And unfortunately Microsoft "forgot" to add that kind of support in the NTVDM (the NT Virtual DOS Machine) on NT-versions prior to Windows 2000, so there is no official way to use the LFN Library in that environment. However, there is something called "The LFN Services for Windows NT 4.0" which claims to solve this problem, at least to some extent. It is available for download at http://www.frontiernet.net/~fys/longfile.htm. I should add that I have not tested that solution!
| Long file name functions: | ||
| LF_7143Supp() | Check if DOS function 7143h is supported | |
| LF_ChDir() | Change current directory to an LFN directory | |
| LF_ChkSubst() | * | Check the long path name of a SUBSTed drive |
| LF_CloseHand() | Close the FileFind handle after a file search | |
| LF_CurDir() | Get the current long file name directory | |
| LF_DbCreate() | * | Create a new dbf file with a long file name |
| LF_DbCreInd() | * | Create a new index file with a long file name |
| LF_DbSetInd() | * | Open an index file with a long file name |
| LF_DbUse() | * | Open a dbf file with a long file name |
| LF_Directory() | Find all files that match a name pattern | |
| LF_Fcopy() | Copy a file with a long name to a new file | |
| LF_Fcreate() | Create a new file with a long file name | |
| LF_Ferase() | Erase a file with a long file name | |
| LF_Ferror() | Return the error code for an LFN operation | |
| LF_FindFirst() | Find the first file that matches a name pattern | |
| LF_FindNext() | Find the next file that matches a name pattern | |
| LF_Fopen() | Open an existing file with a long file name | |
| LF_Frename() | Rename a file | |
| LF_GetFAttr() | Get the attributes of a file | |
| LF_GetFInfo() | Get the date/time, (physical) size and attributes of a file | |
| LF_GetFSize() | Get the physical size of a file (including slack) | |
| LF_GetFTime() | Get the creation time or last write or access time of a file | |
| LF_GetHinfo() | Get the date/time, (real) size and attributes of a file, based on a file handle | |
| LF_IsFile() | Determine if a file or a directory exists | |
| LF_KillSubst() | * | Remove a SUBST |
| LF_LibVers() | Get the version number of the LFN Library | |
| LF_MemoRead() | * | Read a disk file into a character string |
| LF_MemoWrit() | * | Write a character string to a disk file |
| LF_MkDir() | Create a directory with a long file name | |
| LF_RmDir() | Remove a directory with a long file name | |
| LF_SetFAttr() | Set the attributes of a file | |
| LF_SetFTime() | Set the creation time or last write or access time of a file | |
| LF_Subst() | * | Create a SUBST with a long path name |
| LF_Support() | Check if long file names are supported by the OS | |
| LF_ToLong() | Get the canonical long name for a short file name | |
| LF_ToShort() | Get the short name for a long file name or path | |
| LF_VolInfo() | Get volume info for a drive | |
| Demo application: | ||
| LFNdemo() | A complete demo application | |
| The following functions are included in the Low Level Library (starting with Rev 1.00 of the LFN Library these functions have been moved to a separate library file). | ||
| Low level functions: | ||
| LL_FreeMem() | Free a memory block allocated by LL_Str2Mem() | |
| LL_I2Attr() | Convert numerical file attributes to character | |
| LL_IsBitOn() | Check if a certain bit in an integer is on or off | |
| LL_IsProt() | * | Check if the application is running in protected mode |
| LL_LibVers() | Get the version number of the Low Level Library | |
| LL_Mem2Str() | Copy a string from memory to a char variable | |
| LL_Offset() | Get the offset of a protected mode memory selector | |
| LL_Segment() | Get the segment of a protected mode memory selector | |
| LL_Str2Mem() | Copy a string to a static memory location | |
New functions since the previous version are marked with an asterisk. Please note that the low level functions that were moved from the LFN Library to the Low Level Library were also renamed from LF_* to LL_*
More info about the latest changes can be found on the Changes page.
It is recommended that you start by checking if the operating system supports the LFN-specific DOS services and avoid using them if that is not the case. The function to use for that test is LF_Support(). In order to make your applications useful in both kinds of environments, you still have to provide support for "the old way" to handle files.
If you intend to use any of the extended get/set attributes functions, it is recommended that you also call LF_7143Supp() to find out if the operating system supports those functions. That support follows its own rules in addition to requiring support for the LFN DOS services in general (a total mess, in my humble opinion). It is probably safer to use LF_GetHInfo() instead to retrieve that kind of information since the DOS service used by it seems to have more consistent support in various Windows versions.
Although using most of the LFN Library functions only makes sense if the OS supports the LFN DOS services (for example, trying to create a file with a long name will definitely fail on "plain old DOS"), there are a few exceptions to that rule. LF_FindFirst(), LF_FindNext(), LF_Directory() and LF_IsFile() have support for both the LFN services and the corresponding SFN services that have been around since DOS 2.0, and they switch automatically between the two versions depending on the environment. This allows you to use the same routines to handle the result no matter which OS your application is running on.
I have written a few additional file date/time specific bit manipulation routines to take care of what was missing in Clipper and Nanfor. In Rev 0.90 they were written in Clipper and therefore not very fast. In Rev 0.91 they were migrated from Clipper code to assembly, so they are now substantially faster than before.
The names of the internal functions were also changed to reduce the risk of clashes with functions in other libraries. They now all start with "_lf".
In Rev 0.92, there were no changes in the existing code. The only significant changes in the library since Rev 0.91 were the added functions that are mentioned on the Changes page and also briefly above.
In Rev 1.00, the most important change is the reorganization of the library in two separate LIB files. This will require an update of your link script(s) and possibly some function name changes in your code (if you use any of the functions listed under "Low Level functions" above).
Rev 1.00a adds a few new functions to the Low Level Library, but the LFN Library itself has not been changed.
Rev 1.10 adds support for dbf/ntx/ndx files and SUBSTed drives as well as LFN replacements for Clipper's memoread() and memowrit() functions. A few fixes and improvements to the already existing functions were also made.
It is also a fact that the support for the extended get/set attributes DOS services (getting and setting file date, time and attributes) varies between the different Windows versions with the older versions being the worst. See the docs for the individual functions for more info.
If you want to reassemble the assembly functions you also need MASM, the Microsoft Macro Assembler. I use version 5.1, but older versions should also work. I have tried version 6.1, but it is quite different from the earlier versions and may need changes in the source code. OBJ files for the assembly functions are included separately in case you do not have MASM but still want to rebuild the library from scratch.
Starting with Rev 1.00, the library itself is split into two different lib files. The directly LFN related functions are in LFN.LIB as before, but the low level functions previously labeled "Companion Functions" have been moved to the new LL.LIB file and at the same time been renamed from LF_* to LL_*. You must supply both library names (LFN.LIB and LL.LIB) in your link script! Rev 1.00 of the LFN Library requires Rev 1.00 or higher of the Low Level Library.
You also need the Nanforum Toolkit and its companion CPMI library. If you do not have them already, you can download them from the Oasis. CPMI.LIB is included in the Nanfor ZIP file.
So in order to use the LFN Library, these are the four libraries that you must add to your link script: LFN, LL, NANFOR and CPMI
If you need a Win32 Norton Guide viewer I can recommend Dave Pearson's WEG which you can download from his web site.
For recompiling the library source code, including the demo application, you also need the FTINT86.CH header file which comes with the Nanforum Toolkit, the LFNLIB.CH header file which is included in the LFN Library distribution and several standard Clipper header files.
It is recommended that you use #defines from LFNLIB.CH in your own applications when making calls to LFN Library functions.
If you have any problems with the current version or any suggestions for making the library better, do not hesitate to tell me about them, either on comp.lang.clipper or via email at the address below.
However, do not expect me to fix things overnight. This is free software, and you have the source code in the distribution. So if you are in a hurry to get something fixed, feel free to do it yourself for your own needs. But please let me know what you did so I can fix it in the next release for everyone's benefit.
And please read the "Caution and Disclaimer"
document!
Changes since the initial beta revision
are listed here.
Enjoy,
Klas
| LFNLIB.ZIP | Download the LFN Library |
| NFLIB305.ZIP | Download the Nanforum Toolkit (from the Oasis) |
| WEG | Download Dave Pearson's Norton Guide reader for Win32 (from Dave's website) |
| In case you want to talk to me about the LFN Library
(no general Clipper support questions please) |
|
| Back | Go back to the Engwall InfoTech Clipper Pages main page |
This document was last revised on 2008-05-31