www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/07/21/04:20:53

Date: Tue, 21 Jul 1998 11:18:19 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: Jin <GoldCode AT yahoo DOT com>
cc: djgpp AT delorie DOT com
Subject: Re: Problem hooking DOS int 21h
In-Reply-To: <35B3B157.1D3F3DE@yahoo.com>
Message-ID: <Pine.SUN.3.91.980721111757.6992J-100000@is>
MIME-Version: 1.0

On Mon, 20 Jul 1998, Jin wrote:

> In the following program, `test.c',  I do nothing than intercepting DOS
> interrupt and then passing it back to DOS without any change.  But I
> cannot get it work under Window95.  It seems whenever you chain into DOS
> in DJGPP,  functions that executing other program,   like spawn*. exec*
> and system(), cease to work.  But other functions work fine.

I will point out several programmatical errors below.  But before I do
that, you should know that IMHO this approach is a dead end: you
cannot do anything useful by hooking DOS from a DJGPP program, at
least not easily.

The main reasons for that are:

    1) DJGPP's real-mode callbacks are non-reentrant.  This means that
       if a nested DOS call happens, your program will crash at best,
       or take the system down with it at worst.  It also means that
       your program cannot do any DOS I/O while in the callback,
       without some trickery.

    2) You cannot allow paging in any code which is called by the
       callback, because that would trigger a nested DOS call (by the
       DPMI server), and you are back at reason no. 1 above.

No. 2 above, and various other considerations mean in practice that
a program which uses this technique needs to lock all of its memory.
This would be bad enough, but you still need to overcome the first
problem.

In addition, specifically for you case (capturing screen output), it's
not easy to know whether a given DOS call will output to the screen.

That said, there are a lot of useful applications for this idea, if
you can make it happen.  So please go ahead if you need it badly and
feel like trying to handle the difficulties.

> static
> void call_dos(_go32_dpmi_registers *r)
> {
>  r->x.cs = old_int21_vector.rm_segment;
>  r->x.ip = old_int21_vector.rm_offset;
>  _go32_dpmi_simulate_fcall_iret(r);
> }

In the above function, you need to zero-out the r->ss, r->sp, and
r->x.flags members before calling the simulate_fcall function,
otherwise the DPMI host will use the (possibly garbled) values for the
stack and flags.

>     my_int21_info.pm_offset = (int) call_dos;
                                ^^^^^
This should be (unsigned long), to be safe.

As to the main problem: why does it stop working after `spawn*', I
think this is due to reason no. 1 above.  When the DOS Exec function
is called, it causes a cascade of other DOS functions (like find the
executable image on disk, read it into memory, etc.).  All of these
happen while the Exec call didn't return yet.  So you get the nested
calls to your callback, which won't work.

What you need to do to overcome this is to either modify the DJGPP
real-mode callback support to make it reentrant, or to chain to DOS
instead of CALLing it in your callback (since the DJGPP real-mode
callbacks don't support chaining, you will need to add that).

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019