Node:RMCB, Next:, Previous:Above 1MB, Up:Low-level

18.8 How to make DOS/BIOS call your function

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.