File creation using Long Filenames in DOS32

new topic     » topic index » view thread      » older message » newer message

While poking about with some generic test code, I was
getting errors when trying to save my output file...Every
time.  Upon closer inspection, the cause became obvious.
One of the directories in my output path was a 'long
filename'.  I figured somebody'd surely solved that problem
by now, but I did a search of the mailing list, archive, and
recent-user-contributions and couldn't find it.  However, I
did find doswrap.e by Jacques Deschenes, which helped me
figure it out.
   So here it is.  This code redefines open() so that it
will work with long filenames on versions of DOS >= 7.0.
When run on earlier versions of DOS, the original version
of open() will be called, which truncates any long
filenames when creating new files.  (Which causes an
"unable to create file" error if one of the parent directories
of the file is an LFN.  But that shouldn't be a problem
on versions of DOS prior to 7.0.)
   It's a hack, not exactly efficient, and not guaranteed.
But it works for me...so far.  If you find any bugs in it,
please let me know.  (Tested on Win98, but not NT or 95 yet)

----------------------------------------------------------------

----------------------------------------------------------------
--LFNopen.e
--
--By: FaIkon1313 at aol.com
--Date: January 31, 1999 (finished at 03:00 a.m., of course :)
--Platform: DOS32
--
----------------------------------------------------------------
without warning
include machine.e

global constant READ = 0, WRITE = 1, READ_WRITE=2
global constant LFN_OPEN = 1, LFN_TRUNC = 2, LFN_CREATE = 16

global function DosVer()
   sequence reg_list
   reg_list = repeat(0,10)
   reg_list[REG_AX] = #3000
   reg_list = dos_interrupt( #21, reg_list )
   return( remainder( reg_list[REG_AX], 256 ) + floor( reg_list[REG_AX]/256 )
/ 100 )
end function

global function DosClose( integer Handle )
   -- close a file open with DosOpen()
   -- return 1 if success else return 0
   sequence regs
   regs = repeat( 0,10 )
   regs[REG_AX] = #3E00
   regs[REG_BX] = Handle
   regs = dos_interrupt( #21,regs )
   if and_bits( regs[REG_FLAGS], 1 ) then
      return( 0 )
   end if
   return( 1 )
end function -- DosClose()

global function DosOpenLong( sequence FileName, integer Mode,
                             integer Attributes, integer Action, integer DN )
   -- use DOS function #716C to open/create a file
   -- return file handle or -1 if error
   -- mode is 0 = read only
   --         1 = write only
   --         2 = read/write
--Bitfields for Windows95 long-name open action:

--Bit(s)  Description     (Table 01781)
--0      open file (fail if file does not exist)
--1      truncate file if it already exists (fail if file does not exist)
--4      create new file if file does not already exist (fail if exists)

--Note: The only valid combinations of multiple flags are bits 4&0 and 4&1

   atom NameBuffer
   sequence regs
   regs = repeat( 0,10 )
   if DosVer() < 7 then
       return( -1 )
   end if
   NameBuffer = allocate_low( length( FileName ) +1 )
   if not NameBuffer then
       return( -1 )
   end if
   poke( NameBuffer, FileName & 0 )
   regs[REG_AX] = #716C
   regs[REG_BX] = Mode
   regs[REG_CX] = Attributes
   regs[REG_DX] = Action
   regs[REG_DS] = floor( NameBuffer / 16 )  --address segment
   regs[REG_SI] = remainder( NameBuffer, 16 )  -- offset
   regs[REG_DI] = DN        --disambiguation number
   regs = dos_interrupt( #21, regs )
   free_low( NameBuffer )
   if and_bits( regs[REG_FLAGS], 1 ) then
       return( -1 ) -- fail to open
   end if
   return regs[REG_AX]  -- return file handle
end function

global function LFNopen( sequence filename, sequence mode )
   integer tfn
--   puts( 1, "\nLFNO called." )
   if ( not find( mode, {"r","rb","w","wb","u","ub","a","ab"} ) ) or
      ( DosVer() < 7 )then
      return( -1 )
   end if
   if ( mode[1] = 'w' ) or ( mode[1] = 'a' ) then
      --use LFN_OPEN as well as LFN_CREATE so that we
      --won't get an error if it already exists
      tfn = DosOpenLong( filename, WRITE, 0, or_bits( LFN_OPEN, LFN_CREATE ),
1 )
      if ( tfn < 0 ) then
         --unable to create file
         return( -1 )
      end if
      tfn = DosClose( tfn )
   end if
   --now it exists, we can try to open it
   return( open( filename, mode ) )
end function

function original_open( sequence filename, sequence mode )
--   puts( 1, "\nOO called." )
   return( open( filename, mode ) )
end function
constant ORIGINAL_OPEN = routine_id( "original_open" )

global function open( sequence filename, sequence mode )
   if DosVer() < 7 then
      --no long filename support, use original
      return call_func( ORIGINAL_OPEN, { filename, mode } )
   else
      return( LFNopen( filename, mode ) )
   end if
end function

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu