home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 Shareware (Platinum Edition) / QUEPLAT95.ISO / files / programm / lfnlib / lfn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-23  |  11.3 KB  |  424 lines

  1. //lfn.c                         lfn-handling file functions for 16-bit apps
  2. //created 5/25/95               Matt Ginzton
  3.  
  4. //(c) 1995 Matt Ginzton, MaDdoG Software
  5. //permission is granted to use and modify this code as long as attribution
  6. //is given.  Questions?  Email mginzton@leland.stanford.edu, or via
  7. //CompuServe, 75022,650.
  8.  
  9.  
  10. /*
  11.  * this implements, basically, dos.h for long filenames
  12.  *
  13.  * Implemented:
  14.  *  findfirst, findnext
  15.  *  chdir, getcwd, getdcwd
  16.  *  dos_open
  17.  *  also, _lfn_eof, which corresponds to _eof or feof (there never was a _dos_eof)
  18.  *  all these can be used interchangeably with the old versions, except
  19.  *  that one must remember to call findclose after a find.
  20.  * NOT done yet: mkdir, rmdir, ren, del equivalents
  21.  *
  22.  * main weakness: depends on global gSystem, initialized by _lfn_init(),
  23.  * which works fine as long as you only work with one drive at a time and
  24.  * call _lfn_init() in between; because all other calls use gSystem to
  25.  * determine whether to map to the short or long calls.
  26.  */
  27.  
  28. #include <windows.h> 
  29. #include <string.h>
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <dos.h>
  33. #include <stdlib.h>
  34. #include <assert.h>
  35. #include <direct.h>
  36. #include "lfn.h"
  37.  
  38.  
  39. #define FS_SHORT                                0           //file system only supports short fn's
  40. #define FS_LONG                                 1           //lfns supported!
  41. int gSystem=FS_SHORT;                                       //global system type flag
  42.  
  43.  
  44. #define FS_LFN_APIS                             0x4000      //from guide.hlp
  45. #define FILE_OPEN                               0x0001      //also from guide.hlp
  46.  
  47. //#define DOS_DEBUG_CODE
  48.  
  49. unsigned _LFN_findnext( _lfnfind_t *fileinfo );
  50. unsigned _LFN_findfirst( const char *filename, unsigned attrib, _lfnfind_t *fileinfo );
  51. void FillSFNInfo ( _lfnfind_t *fileinfo );
  52.  
  53.  
  54. #pragma warning( disable: 4704 )
  55.  
  56. int _lfn_init (char drive)
  57. {
  58.     char szBuffer[32];
  59.     int BufSize=sizeof(szBuffer);
  60.     char RootName[]="@:\\";
  61.     int Flags;
  62.     int MaxFilename;
  63.     int MaxPath;
  64.     int errCode;
  65.     char near * pBuf=szBuffer;
  66.     char near * pRoot=RootName;
  67.                                                     
  68.     RootName[0]=toupper (drive);
  69.                 
  70. #ifdef DOS_DEBUG_CODE
  71.     printf ("InitSystemType() on drive %s\n", RootName);
  72. #endif
  73.  
  74.     _asm
  75.     {
  76.         mov ax, 0x71A0         ; Get Volume Information
  77.         mov di, ds
  78.         mov es, di
  79.         mov di, pBuf
  80.         mov cx, BufSize        ; size of buffer, in bytes
  81.         mov dx, pRoot
  82.         int 0x21
  83.         jc  error
  84.         mov [Flags], bx        ; file system flags
  85.         mov [MaxFilename], cx  ; max. filename length including null
  86.         mov [MaxPath], dx      ; max. path length including null
  87.         mov errCode, 0
  88.         ja  exitpoint
  89.       error:
  90.         mov errCode, 1
  91.       exitpoint:
  92.     }
  93.                 
  94.     if (errCode)
  95.     {
  96. #ifdef DOS_DEBUG_CODE
  97.         printf ("System does not even support extended calls.\n");
  98. #endif
  99.         return FS_SHORT;
  100.     }
  101.                 
  102. #ifdef DOS_DEBUG_CODE
  103.     printf ("GetVolumeInfo successful... flags %x.\n", Flags);
  104.     printf ("File system is %s\n", szBuffer);
  105.     printf ("Max filename is %d, max path is %d\n", MaxFilename, MaxPath);
  106. #endif
  107.  
  108.     gSystem=(Flags & FS_LFN_APIS) ? FS_LONG : FS_SHORT;
  109.     return gSystem;
  110. }
  111.  
  112.  
  113. unsigned _lfn_findfirst( const char *filename, unsigned attrib, _lfnfind_t *fileinfo )
  114. {
  115.     unsigned ret;
  116.                 
  117.     if (gSystem == FS_SHORT)
  118.     {
  119.         ret = _dos_findfirst (filename, attrib, &fileinfo->SFN);
  120.         fileinfo->name=fileinfo->SFN.name;
  121.     }
  122.     else
  123.     {
  124.         ret = _LFN_findfirst (filename, attrib, fileinfo);
  125.         FillSFNInfo (fileinfo);         //copy applicable long info into short part
  126.     }
  127.                 
  128.     return ret;
  129. }
  130.  
  131.  
  132. unsigned _lfn_findnext( _lfnfind_t *fileinfo )
  133. {
  134.     unsigned ret;
  135.                 
  136.     if (gSystem == FS_SHORT)
  137.     {
  138.         ret = _dos_findnext (&fileinfo->SFN);
  139.         fileinfo->name=fileinfo->SFN.name;
  140.     }
  141.     else
  142.     {
  143.         ret = _LFN_findnext (fileinfo);
  144.         FillSFNInfo (fileinfo);         //copy applicable long info into short part
  145.     }
  146.                 
  147.     return ret;
  148. }
  149.  
  150.  
  151. void FillSFNInfo ( _lfnfind_t *fileinfo )
  152. {
  153.     fileinfo->bIsLong=1;
  154.     fileinfo->name=fileinfo->LFN.cFileName;
  155.     fileinfo->SFN.attrib=(char)fileinfo->LFN.dwFileAttributes; //whatever fits
  156.     fileinfo->SFN.size=fileinfo->LFN.nFileSizeLow;  //low 32 bits of 64-bit filesize
  157. }
  158.  
  159.  
  160. unsigned _LFN_findfirst( const char *filename, unsigned attrib, _lfnfind_t *fileinfo )
  161. {
  162.     //int MustMatchAttrs=0;         //we won't support this
  163.     int DateTimeFormat=1;           //use MS-DOS format
  164.     short fnSeg, fnOff;             //seg and offs of filename
  165.     short recSeg, recOff;           //seg and offs of FindData record
  166.     WIN32_FIND_DATA far * pLFN=&fileinfo->LFN;
  167.     const char far * pFilename=filename;
  168.     int errCode;
  169.     int Handle;
  170.     int ConversionCode;
  171.                 
  172.     fnSeg=_FP_SEG(pFilename);
  173.     fnOff=_FP_OFF(pFilename);
  174.     recSeg=_FP_SEG(pLFN);
  175.     recOff=_FP_OFF(pLFN);
  176.                 
  177.     _asm
  178.     {
  179.         mov ax, 0x714E            ; Find First File
  180.         //mov ch, MustMatchAttrs  ; must match attributes
  181.         //mov cl, attrib          ; search attributes
  182.         mov cx, attrib            ; real search attributes
  183.         mov dx, fnSeg             ; file to search for
  184.         mov ds, dx
  185.         mov dx, fnOff
  186.         mov di, recSeg            ; address of WIN32_FIND_DATA struct
  187.         mov es, di
  188.         mov di, recOff
  189.         mov si, DateTimeFormat    ; format for returned date and time
  190.         int 0x21
  191.         jc  error
  192.         mov [Handle], ax          ; search handle
  193.         mov [ConversionCode], cx  ; UNICODE to OEM/ANSI conversion ok?
  194.         mov errCode, 0
  195.         ja  exitpoint
  196.       error:
  197.         mov errCode, 1
  198.       exitpoint:
  199.     }
  200.                 
  201.     fileinfo->Handle=Handle;
  202.                 
  203.     return errCode;
  204. }
  205.  
  206.  
  207. unsigned _LFN_findnext( _lfnfind_t *fileinfo )
  208. {
  209.     short recSeg, recOff;           //seg and offs of FindData record
  210.     int DateTimeFormat=1;           //use MS-DOS format
  211.     int errCode;
  212.     int ConversionCode;
  213.     int Handle;
  214.     WIN32_FIND_DATA far * pLFN=&fileinfo->LFN;
  215.     
  216.     recSeg=_FP_SEG(pLFN);
  217.     recOff=_FP_OFF(pLFN);
  218.     Handle=fileinfo->Handle;
  219.                 
  220.     _asm
  221.     {
  222.         mov ax, 0x714F           ; Find Next File
  223.         mov bx, Handle           ; search handle from Find First File
  224.         mov di, recSeg           ; address of WIN32_FIND_DATA struct
  225.         mov es, di
  226.         mov di, recOff
  227.         mov si, DateTimeFormat   ; format for returned date and time
  228.         int 0x21
  229.         jc error
  230.         mov [ConversionCode], cx ; UNICODE to OEM/ANSI conversion ok?
  231.         mov errCode, 0
  232.         ja  exitpoint
  233.       error:
  234.         mov errCode, 1
  235.       exitpoint:
  236.     }
  237.                 
  238.     return errCode;
  239. }
  240.  
  241.  
  242. void _lfn_findclose ( _lfnfind_t * fileinfo)
  243. {
  244.     int Handle;
  245.                 
  246.     if (gSystem == FS_SHORT)
  247.         return;                      //nothing to do
  248.                                 
  249.     Handle=fileinfo->Handle;
  250.     _asm
  251.     {
  252.         mov ax, 0x71A1               ; find close
  253.         mov bx, Handle               ; search handle
  254.         int 0x21
  255.     }
  256. }
  257.  
  258.  
  259. int _lfn_chdir ( const char * dirname)
  260. {
  261.     int errCode;
  262.     const char far * pPath=dirname;
  263.     short pathOfs, pathSeg;
  264.                 
  265.     if (gSystem == FS_SHORT)
  266.     {
  267.         return _chdir (dirname);
  268.     }
  269.                 
  270.     pathOfs=_FP_OFF (pPath);
  271.     pathSeg=_FP_SEG (pPath);
  272.                 
  273.     _asm
  274.     {
  275.         mov ax, 0x713B    ; Change Directory
  276.         mov dx, pathSeg   ; address of path for new directory
  277.         mov ds, dx
  278.         mov dx, pathOfs
  279.         int 0x21
  280.         jc error
  281.         mov errCode, 0
  282.         ja exitpoint
  283.       error:
  284.         mov errCode, -1
  285.       exitpoint:
  286.     }
  287.                 
  288. #ifdef DOS_DEBUG_CODE
  289.     if (errCode)
  290.         printf ("couldn't change to %s\n", dirname);
  291. #endif
  292.  
  293.     return errCode;
  294. }
  295.  
  296.  
  297. char * _lfn_getcwd( char *buffer, int maxlen )
  298. {
  299.     return _lfn_getdcwd (0, buffer, maxlen);
  300. }
  301.  
  302.  
  303. char * _lfn_getdcwd( int drive, char *buffer, int maxlen )
  304. {
  305.     char far * lpBuf;
  306.     short bufSeg, bufOfs;
  307.     char dr=drive;
  308.     int errCode;
  309.                 
  310.     if (gSystem == FS_SHORT)
  311.     {
  312.         return _getdcwd (drive, buffer, maxlen);
  313.     }
  314.                 
  315.     if (!buffer)
  316.     {
  317.         buffer=malloc (maxlen+1);
  318.         assert (buffer);
  319.     }
  320.     strcpy (buffer, "@:\\");
  321.     *buffer=_getdrive()+'A'-1;
  322.     lpBuf=buffer+3;
  323.                 
  324.     bufSeg=_FP_SEG (lpBuf);
  325.     bufOfs=_FP_OFF (lpBuf);
  326.                 
  327.     _asm
  328.     {
  329.         mov ax, 0x7147      ; Get Current Directory
  330.         mov dl, dr          ; drive number
  331.         mov si, bufSeg      ; address of buffer for path
  332.         mov ds, si
  333.         mov si, bufOfs
  334.         int 0x21
  335.         jc error
  336.         mov errCode, 0
  337.         ja exitpoint
  338.       error:
  339.         mov errCode, -1
  340.       exitpoint:
  341.     }
  342.                 
  343.     if (errCode)
  344.         return NULL;
  345.     else
  346.         return buffer;
  347. }
  348.  
  349.  
  350. unsigned _lfn_open( const char *filename, unsigned mode, int *handle )
  351. {
  352.     int errCode;
  353.     const char far * lpFN=filename;
  354.     short fnSeg, fnOfs;
  355.     int Handle;                     //output -- file handle
  356.     int ModeAndFlags=mode;          //mode -- from mode argument
  357.     int Attributes=0;               //attributes -- ignored since we don't create
  358.     int Action=FILE_OPEN;           //open only
  359.     int AliasHint=0;
  360.     int ActionTaken;                //output -- ignore
  361.                 
  362.     if (gSystem == FS_SHORT)
  363.     {
  364.         return _dos_open (filename, mode, handle);
  365.     }
  366.                 
  367.     fnSeg=_FP_SEG (lpFN);
  368.     fnOfs=_FP_OFF (lpFN);
  369.                 
  370.     _asm
  371.     {
  372.         mov ax, 0x716C         ; Create or Open File
  373.         mov bx, ModeAndFlags   ; access and sharing modes and flags
  374.         mov cx, Attributes     ; file attributes
  375.         mov dx, Action         ; action to take
  376.         mov si, fnSeg          ; address of filename
  377.         mov ds, si
  378.         mov si, fnOfs
  379.         mov di, AliasHint      ; numeric tail for file's short name 
  380.         int 0x21
  381.         jc error
  382.         mov [Handle], ax       ; file handle
  383.         mov [ActionTaken], cx  ; action taken to open file
  384.         mov errCode, 0
  385.         ja exitpoint
  386.       error:
  387.         mov errCode, 1
  388.       exitpoint:
  389.     }
  390.                 
  391.     if (!errCode)
  392.         *handle=Handle;
  393.                                 
  394.     return errCode;
  395. }
  396.  
  397. #ifndef SEEK_BEG
  398. #define SEEK_BEG 0
  399. #endif
  400.  
  401. #ifndef SEEK_REL
  402. #define SEEK_REL 1
  403. #endif
  404.  
  405. #ifndef SEEK_END
  406. #define SEEK_END 2
  407. #endif
  408.  
  409.  
  410. int _lfn_eof (int handle)
  411. {
  412.     unsigned long oldPos;
  413.  
  414.     oldPos=_dos_seek (handle, 0, SEEK_REL);         //don't seek anywhere... just get pos
  415.     if (oldPos==_dos_seek (handle, 0, SEEK_END))    //seek to end; if it's the same
  416.         return 1;                                                                                       //return TRUE
  417.                 
  418.     _dos_seek (handle, oldPos, SEEK_BEG);           //seek back to beginning
  419.  
  420.     return 0;
  421. }
  422.  
  423. #pragma warning( default: 4704 )
  424.