Node:RMCB,
Next:Hardware interrupts,
Previous:Above 1MB,
Up:Low-level
Q: How can I make any real-mode service call my function? E.g., the
mouse driver has a provision (function 0Ch) to call a user-defined handler
when certain events occur, which expects a far pointer to my function in
the ES:DX register pair.
A: Those services expect a real-mode function, so you should wrap
your protected-mode function with a real-mode wrapper. To this end, call
either the _go32_dpmi_allocate_real_mode_callback_retf
or the
_go32_dpmi_allocate_real_mode_callback_iret
library function, as
required by the real-mode service you want to hook, and pass the
segment
and offset
members it returns to the service you
want (in the above example, Int 33h function 0Ch) by calling
__dpmi_int
.
Here's a code fragment that shows how to do this34:
#include <dpmi.h> #include <go32.h> static __dpmi_regs callback_regs; static _go32_dpmi_seginfo callback_info; int install_mouse_handler (unsigned mask, void (*func)(__dpmi_regs *)) { __dpmi_regs r; callback_info.pm_offset = (long)func; if (_go32_dpmi_allocate_real_mode_callback_retf(&callback_info, &callback_regs)) return -1; /* failure */ r.x.ax = 0xc; r.x.cx = mask; r.x.es = callback_info.rm_segment; r.x.dx = callback_info.rm_offset; __dpmi_int (0x33, &r); return (r.x.flags & 1) ? -1 : 0; }
The handler (func
in the above example) will be called with a
pointer to a __dpmi_regs
structure which is filled by values
found in the CPU registers when the mouse driver calls the handler. See
the docs in the library reference Info file for further details about
allocating wrapper functions.
Additional considerations apply if your callback is a C++ class member function. First, you need to remember that member functions expect a hidden extra first parameter. Second, if the function is virtual, you will need to lock the class's virtual table. Third, you need to lock the object itself, not only the method you call on it.