home *** CD-ROM | disk | FTP | other *** search
- //lfn.c lfn-handling file functions for 16-bit apps
- //created 5/25/95 Matt Ginzton
-
- //(c) 1995 Matt Ginzton, MaDdoG Software
- //permission is granted to use and modify this code as long as attribution
- //is given. Questions? Email mginzton@leland.stanford.edu, or via
- //CompuServe, 75022,650.
-
-
- /*
- * this implements, basically, dos.h for long filenames
- *
- * Implemented:
- * findfirst, findnext
- * chdir, getcwd, getdcwd
- * dos_open
- * also, _lfn_eof, which corresponds to _eof or feof (there never was a _dos_eof)
- * all these can be used interchangeably with the old versions, except
- * that one must remember to call findclose after a find.
- * NOT done yet: mkdir, rmdir, ren, del equivalents
- *
- * main weakness: depends on global gSystem, initialized by _lfn_init(),
- * which works fine as long as you only work with one drive at a time and
- * call _lfn_init() in between; because all other calls use gSystem to
- * determine whether to map to the short or long calls.
- */
-
- #include <windows.h>
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <dos.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <direct.h>
- #include "lfn.h"
-
-
- #define FS_SHORT 0 //file system only supports short fn's
- #define FS_LONG 1 //lfns supported!
- int gSystem=FS_SHORT; //global system type flag
-
-
- #define FS_LFN_APIS 0x4000 //from guide.hlp
- #define FILE_OPEN 0x0001 //also from guide.hlp
-
- //#define DOS_DEBUG_CODE
-
- unsigned _LFN_findnext( _lfnfind_t *fileinfo );
- unsigned _LFN_findfirst( const char *filename, unsigned attrib, _lfnfind_t *fileinfo );
- void FillSFNInfo ( _lfnfind_t *fileinfo );
-
-
- #pragma warning( disable: 4704 )
-
- int _lfn_init (char drive)
- {
- char szBuffer[32];
- int BufSize=sizeof(szBuffer);
- char RootName[]="@:\\";
- int Flags;
- int MaxFilename;
- int MaxPath;
- int errCode;
- char near * pBuf=szBuffer;
- char near * pRoot=RootName;
-
- RootName[0]=toupper (drive);
-
- #ifdef DOS_DEBUG_CODE
- printf ("InitSystemType() on drive %s\n", RootName);
- #endif
-
- _asm
- {
- mov ax, 0x71A0 ; Get Volume Information
- mov di, ds
- mov es, di
- mov di, pBuf
- mov cx, BufSize ; size of buffer, in bytes
- mov dx, pRoot
- int 0x21
- jc error
- mov [Flags], bx ; file system flags
- mov [MaxFilename], cx ; max. filename length including null
- mov [MaxPath], dx ; max. path length including null
- mov errCode, 0
- ja exitpoint
- error:
- mov errCode, 1
- exitpoint:
- }
-
- if (errCode)
- {
- #ifdef DOS_DEBUG_CODE
- printf ("System does not even support extended calls.\n");
- #endif
- return FS_SHORT;
- }
-
- #ifdef DOS_DEBUG_CODE
- printf ("GetVolumeInfo successful... flags %x.\n", Flags);
- printf ("File system is %s\n", szBuffer);
- printf ("Max filename is %d, max path is %d\n", MaxFilename, MaxPath);
- #endif
-
- gSystem=(Flags & FS_LFN_APIS) ? FS_LONG : FS_SHORT;
- return gSystem;
- }
-
-
- unsigned _lfn_findfirst( const char *filename, unsigned attrib, _lfnfind_t *fileinfo )
- {
- unsigned ret;
-
- if (gSystem == FS_SHORT)
- {
- ret = _dos_findfirst (filename, attrib, &fileinfo->SFN);
- fileinfo->name=fileinfo->SFN.name;
- }
- else
- {
- ret = _LFN_findfirst (filename, attrib, fileinfo);
- FillSFNInfo (fileinfo); //copy applicable long info into short part
- }
-
- return ret;
- }
-
-
- unsigned _lfn_findnext( _lfnfind_t *fileinfo )
- {
- unsigned ret;
-
- if (gSystem == FS_SHORT)
- {
- ret = _dos_findnext (&fileinfo->SFN);
- fileinfo->name=fileinfo->SFN.name;
- }
- else
- {
- ret = _LFN_findnext (fileinfo);
- FillSFNInfo (fileinfo); //copy applicable long info into short part
- }
-
- return ret;
- }
-
-
- void FillSFNInfo ( _lfnfind_t *fileinfo )
- {
- fileinfo->bIsLong=1;
- fileinfo->name=fileinfo->LFN.cFileName;
- fileinfo->SFN.attrib=(char)fileinfo->LFN.dwFileAttributes; //whatever fits
- fileinfo->SFN.size=fileinfo->LFN.nFileSizeLow; //low 32 bits of 64-bit filesize
- }
-
-
- unsigned _LFN_findfirst( const char *filename, unsigned attrib, _lfnfind_t *fileinfo )
- {
- //int MustMatchAttrs=0; //we won't support this
- int DateTimeFormat=1; //use MS-DOS format
- short fnSeg, fnOff; //seg and offs of filename
- short recSeg, recOff; //seg and offs of FindData record
- WIN32_FIND_DATA far * pLFN=&fileinfo->LFN;
- const char far * pFilename=filename;
- int errCode;
- int Handle;
- int ConversionCode;
-
- fnSeg=_FP_SEG(pFilename);
- fnOff=_FP_OFF(pFilename);
- recSeg=_FP_SEG(pLFN);
- recOff=_FP_OFF(pLFN);
-
- _asm
- {
- mov ax, 0x714E ; Find First File
- //mov ch, MustMatchAttrs ; must match attributes
- //mov cl, attrib ; search attributes
- mov cx, attrib ; real search attributes
- mov dx, fnSeg ; file to search for
- mov ds, dx
- mov dx, fnOff
- mov di, recSeg ; address of WIN32_FIND_DATA struct
- mov es, di
- mov di, recOff
- mov si, DateTimeFormat ; format for returned date and time
- int 0x21
- jc error
- mov [Handle], ax ; search handle
- mov [ConversionCode], cx ; UNICODE to OEM/ANSI conversion ok?
- mov errCode, 0
- ja exitpoint
- error:
- mov errCode, 1
- exitpoint:
- }
-
- fileinfo->Handle=Handle;
-
- return errCode;
- }
-
-
- unsigned _LFN_findnext( _lfnfind_t *fileinfo )
- {
- short recSeg, recOff; //seg and offs of FindData record
- int DateTimeFormat=1; //use MS-DOS format
- int errCode;
- int ConversionCode;
- int Handle;
- WIN32_FIND_DATA far * pLFN=&fileinfo->LFN;
-
- recSeg=_FP_SEG(pLFN);
- recOff=_FP_OFF(pLFN);
- Handle=fileinfo->Handle;
-
- _asm
- {
- mov ax, 0x714F ; Find Next File
- mov bx, Handle ; search handle from Find First File
- mov di, recSeg ; address of WIN32_FIND_DATA struct
- mov es, di
- mov di, recOff
- mov si, DateTimeFormat ; format for returned date and time
- int 0x21
- jc error
- mov [ConversionCode], cx ; UNICODE to OEM/ANSI conversion ok?
- mov errCode, 0
- ja exitpoint
- error:
- mov errCode, 1
- exitpoint:
- }
-
- return errCode;
- }
-
-
- void _lfn_findclose ( _lfnfind_t * fileinfo)
- {
- int Handle;
-
- if (gSystem == FS_SHORT)
- return; //nothing to do
-
- Handle=fileinfo->Handle;
- _asm
- {
- mov ax, 0x71A1 ; find close
- mov bx, Handle ; search handle
- int 0x21
- }
- }
-
-
- int _lfn_chdir ( const char * dirname)
- {
- int errCode;
- const char far * pPath=dirname;
- short pathOfs, pathSeg;
-
- if (gSystem == FS_SHORT)
- {
- return _chdir (dirname);
- }
-
- pathOfs=_FP_OFF (pPath);
- pathSeg=_FP_SEG (pPath);
-
- _asm
- {
- mov ax, 0x713B ; Change Directory
- mov dx, pathSeg ; address of path for new directory
- mov ds, dx
- mov dx, pathOfs
- int 0x21
- jc error
- mov errCode, 0
- ja exitpoint
- error:
- mov errCode, -1
- exitpoint:
- }
-
- #ifdef DOS_DEBUG_CODE
- if (errCode)
- printf ("couldn't change to %s\n", dirname);
- #endif
-
- return errCode;
- }
-
-
- char * _lfn_getcwd( char *buffer, int maxlen )
- {
- return _lfn_getdcwd (0, buffer, maxlen);
- }
-
-
- char * _lfn_getdcwd( int drive, char *buffer, int maxlen )
- {
- char far * lpBuf;
- short bufSeg, bufOfs;
- char dr=drive;
- int errCode;
-
- if (gSystem == FS_SHORT)
- {
- return _getdcwd (drive, buffer, maxlen);
- }
-
- if (!buffer)
- {
- buffer=malloc (maxlen+1);
- assert (buffer);
- }
- strcpy (buffer, "@:\\");
- *buffer=_getdrive()+'A'-1;
- lpBuf=buffer+3;
-
- bufSeg=_FP_SEG (lpBuf);
- bufOfs=_FP_OFF (lpBuf);
-
- _asm
- {
- mov ax, 0x7147 ; Get Current Directory
- mov dl, dr ; drive number
- mov si, bufSeg ; address of buffer for path
- mov ds, si
- mov si, bufOfs
- int 0x21
- jc error
- mov errCode, 0
- ja exitpoint
- error:
- mov errCode, -1
- exitpoint:
- }
-
- if (errCode)
- return NULL;
- else
- return buffer;
- }
-
-
- unsigned _lfn_open( const char *filename, unsigned mode, int *handle )
- {
- int errCode;
- const char far * lpFN=filename;
- short fnSeg, fnOfs;
- int Handle; //output -- file handle
- int ModeAndFlags=mode; //mode -- from mode argument
- int Attributes=0; //attributes -- ignored since we don't create
- int Action=FILE_OPEN; //open only
- int AliasHint=0;
- int ActionTaken; //output -- ignore
-
- if (gSystem == FS_SHORT)
- {
- return _dos_open (filename, mode, handle);
- }
-
- fnSeg=_FP_SEG (lpFN);
- fnOfs=_FP_OFF (lpFN);
-
- _asm
- {
- mov ax, 0x716C ; Create or Open File
- mov bx, ModeAndFlags ; access and sharing modes and flags
- mov cx, Attributes ; file attributes
- mov dx, Action ; action to take
- mov si, fnSeg ; address of filename
- mov ds, si
- mov si, fnOfs
- mov di, AliasHint ; numeric tail for file's short name
- int 0x21
- jc error
- mov [Handle], ax ; file handle
- mov [ActionTaken], cx ; action taken to open file
- mov errCode, 0
- ja exitpoint
- error:
- mov errCode, 1
- exitpoint:
- }
-
- if (!errCode)
- *handle=Handle;
-
- return errCode;
- }
-
- #ifndef SEEK_BEG
- #define SEEK_BEG 0
- #endif
-
- #ifndef SEEK_REL
- #define SEEK_REL 1
- #endif
-
- #ifndef SEEK_END
- #define SEEK_END 2
- #endif
-
-
- int _lfn_eof (int handle)
- {
- unsigned long oldPos;
-
- oldPos=_dos_seek (handle, 0, SEEK_REL); //don't seek anywhere... just get pos
- if (oldPos==_dos_seek (handle, 0, SEEK_END)) //seek to end; if it's the same
- return 1; //return TRUE
-
- _dos_seek (handle, oldPos, SEEK_BEG); //seek back to beginning
-
- return 0;
- }
-
- #pragma warning( default: 4704 )
-