Date: Tue, 21 Jul 1998 11:18:19 +0300 (IDT) From: Eli Zaretskii To: Jin cc: djgpp AT delorie DOT com Subject: Re: Problem hooking DOS int 21h In-Reply-To: <35B3B157.1D3F3DE@yahoo.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk 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).