An update, including source code, and patches for Glockenspiel...
Documentation for bug in MSC 6.0 regarding open file handles
------------------------------------------------------------
A problem was reported to me, about MSC 6.0 not being able to
compile a program with 5 nested include header files (it's
documented as being able to do 9). About 20 hours of work
later, here is why:
There is a bug in the MSC 6.0 runtime library, e.g. the file
LLIBCEP.LIB. The bug is that in the open() function (which
is called by fopen), they first of all call DosOpen, and then
check that the file handle returned by DosOpen is less than
their internal limit of the number of FILE handles they can
cope with. This is an invalid test. They should only be
testing to make sure that the user doesn't try to open more
files than they have in their array (ie 20 normally). DosOpen()
is quite within it's rights to return 3279-3298 as it's first
20 file handles (leastways, I can't find any documentation to
the contrary). And device drivers can potentially eat up all
the numbers from 3-20 as far as I am aware (0, 1 and 2 are
reserved for stdin, stdout and stderr), as far as I am aware.
What this means, is that every single program that is *linked*
with the MSC 6.0 library, has this anomaly in it. This includes
the MSC 6.0 compiler itself! Specifically, C1.EXE, which is in
charge of including all the header files, will potentially give
you headaches in this regard.
If you want your own MSC 6.0 programs to not suffer from this
restriction, you have the following choices:
1. Patch LLIBCEP.LIB and compile your program normally.
2. Compile your program normally, then patch the resulting executable.
3. Link with the multitasking library, which has a restriction of
40, instead of the normal 20, which will probably get you over
the immediate problems.
4. Modify CRT0DAT.ASM and _FILE.C as documented in the README.DOC
that comes with MSC 6.0.
I would expect that no-one is using MSC 6.0 for their new development
anyway (and worried about the file handle problem), so this is of
little interest.
If you want someone else's executable to not have the file handle
problem, you have the following choice:
1. Patch the executable.
If you want to be able to have 9 nested include files, and you have
device drivers taking up your lower-numbered handles, you have the
following choice:
1. Patch C1.EXE (it's just the same as any other application).
Note that after doing these patches, although you remove the bug,
you will STILL potentially have to run a program, e.g. "fh", to
increase the number of file handles, because, e.g. the device
driver might be using numbers 10-20 AND not have done a
DosSetMaxFH(), meaning that the application is now down to just
a few file handles.
Patching the executable, and running FH, an MSC 6.0-compiled
(actually, linked) program will have a limit of 17 files that
can be opened, plus the 3 standard streams, just as NFILE would
have you believe.
Unfortunately MSC 6.0 checks the file handle < _NFILE in three
separate locations - open(), read() and write(). There may be
others, too. At time of writing, the only requirement was to
get C1.EXE patched, so that is well documented below, but I only
zapped open() and read() to achieve that purpose. If you want
to do the full patching of your own executables (or the LIB file),
then here is a very brief summary:
Look for E9xxxx E98C00 8B46FE 3B06xxxx 720D. Change that 720D
to EB0D, to do an unconditional jump, to fix open(). Look for
8B5E06 3B1Exxxx 7208. Change that 72 to an EB and you will have
fixed the write() function. Look for 8B5E06 3B1Exxxx 733F.
Change the 733F to 9090. The "xx" are addresses that change due
to relocation. There might be others.
One other thing to note, is that if you go into cvp (Codeview),
and do a file, OS-shell, it somehow manages to clear the device
drivers out of all the low-numbered file handles, which means
that you don't need to patch anything, you simply run cvp as
your main shell! I don't know why this does that, or more
importantly, how to write a program a lot smaller than cvp, that
both increases the number of file handles AND clears the low
numbered file handles. If anyone knows how to do the latter,
could you please contact Paul Edwards at 3:711/934{at}fidonet.
Meanwhile, here are some zaps to fix LLIBCEP.LIB in MSC 6.00:
zap llibcep.lib 0x5d27 0xeb (open)
zap llibcep.lib 0x621d 0xeb (write)
zap llibcep.lib 0x5f92 0x90 (read)
zap llibcep.lib 0x5f93 0x90 (read)
To fix c1.exe:
Look for FE3B0661 3E720D50 9ABF2C00 (6.00)
xx xx xx
51 3D D7 (6.00A)
That "72" needs to change to EB
Look for 8B5E063B 1E613E73 418B4E0A (6.00)
xxxx
513D (6.00A)
That "7341" needs to change to "9090"
Stuff with "xx" below it is subject to change, due to relocation.
Anything listed below is a known variation. There may be others
too, so you'll have to do a partial match. Have fun. :-)
On c1.exe (from MSC 6.00), dated 1990-02-15, size 145381 bytes,
this translates to:
zap c1.exe 0x183a9 0xeb
zap c1.exe 0x19703 0x90
zap c1.exe 0x19704 0x90
On c1.exe (from MSC 6.00A), dated 1990-08-15, size 146928 bytes,
this translates to:
zap c1.exe 0x187c1 0xeb
zap c1.exe 0x19b1b 0x90
zap c1.exe 0x19b1c 0x90
P.S. Here are some zaps for GCPP.EXE, Glockenspiel's C++ compiler,
version 2.0 c, dated 1990-09-05, size 53240 bytes, which unfortunately
is linked with MSC 6.0 too!
zap gcpp.exe 0x908b 0xeb
zap gcpp.exe 0x91c1 0x90
zap gcpp.exe 9x91c2 0x90
And Glockenspiel's C++ compiler version 2.0 D, size 84144 bytes...
zap gcpp.exe 0xbbed 0xeb
zap gcpp.exe 0xbd23 0x90
zap gcpp.exe 0xbd24 0x90
P.P.S. Here's the faulty source code!
call DOSOPEN ; try to open
or ax,ax ; did it work?
jz CheckHandle ; yes, go on
;Open error
cmp ax,ERROR_OPEN_FAILED
jne jmp_dosret ;return error
.....
;Open was successful
CheckHandle:
; Check to see that the handle returned is in the range supported
; by the compiler. If not, return no more files error.
mov ax,[Fh]
cmp ax,__nfile ; is file handle out of range?
jb OpenOk ; nope, its ok
@EOT:
---
* Origin: X (3:711/934.9)
|