home *** CD-ROM | disk | FTP | other *** search
/ Computer Installation Guide - Dragon Clan Series / CD2.iso / DOSTOOLS / PMODEW / EXAMPLES.ZIP / EXAMPLE3.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-06  |  4.0 KB  |  132 lines

  1. /*****************************************************************************
  2.  
  3.  NOTE: As of v1.22, PMODE/W passes INT 1Ch up when hooked in protected mode.
  4.        This method of hooking 1Ch is no longer necessary, however it still
  5.        serves as a good example of how to setup a real mode callback.
  6.  
  7.   This is an example of how to set up a real mode callback and hook the BIOS
  8. timer tick interrupt (INT 1Ch) in protected mode. For speed purposes, PMODE/W
  9. does not normally pass this interrupt up to protected mode automatically from
  10. real mode. Therefore, it must be hooked in real mode first and then passed up
  11. to protected mode by way of a DPMI callback. In this example, a character is
  12. incremented in the upper right hand corner of the screen on every tick (in
  13. protected mode). This will ONLY work under PMODE/W if there are DPMI callbacks
  14. available (specified in PMWSETUP). If PMODE/W is running under the control of
  15. a DPMI host, the DPMI host must provide PMODE/W with real mode callbacks.
  16. Under DOS/4GW this is not necessary since DOS/4GW passes up 1Ch all the time.
  17. PMODE/W does not pass it up in order to prevent redundant mode switches which
  18. consequently slow down the system. Hooking INT 8 for timing is a much better
  19. idea.
  20.  
  21. *****************************************************************************/
  22.  
  23. #include <stdio.h>
  24. #include <dos.h>
  25.  
  26. void (__interrupt __far timerproc) (void);
  27.  
  28. #pragma aux intp =\
  29.         "push eax",\
  30.         "mov ax,[esi]",\
  31.         "mov es:[edi+2ah],ax",\
  32.         "mov ax,[esi+2]",\
  33.         "mov es:[edi+2ch],ax",\
  34.         "mov ax,[esi+4]",\
  35.         "mov es:[edi+20h],ax",\
  36.         "add word ptr es:[edi+2eh],6",\
  37.         "pop eax",\
  38.         "int 1ch",\
  39.         "iretd",\
  40.         modify [eax];
  41.  
  42. void main (void)
  43. {
  44.   union REGS r;
  45.   unsigned   rmvector;
  46.  
  47.   r.x.eax = 0x205;
  48.   r.h.bl = 0x1c;
  49.   r.x.ecx = FP_SEG (timerproc);
  50.   r.x.edx = FP_OFF (timerproc);
  51.   int386 (0x31, &r, &r);                /* Hook Protected Mode INT 1Ch */
  52.  
  53.   setpassup_1C (&rmvector);             /* Initialize 1Ch Passup Handler */
  54.   getch ();
  55.   resetpassup_1C (&rmvector);           /* Reset 1Ch Passup Handler */
  56. }
  57.  
  58. void (__interrupt __far timerproc) (void)
  59. {
  60.   static char *vidmem = (char *)0xb8000;
  61.  
  62.   vidmem[158] ++;
  63. }
  64.  
  65. int setpassup_1C (unsigned *oldvector)
  66. {
  67.   void int1C_handler (void);
  68.  
  69.   union REGS   pr;
  70.   struct SREGS psr;
  71.  
  72.   unsigned short cbseg, cboff;
  73.   char           regbuf[0x32];
  74.  
  75.   pr.x.eax = 0x303;
  76.   psr.ds = FP_SEG (int1C_handler);
  77.   pr.x.esi = FP_OFF (int1C_handler);
  78.   psr.es = FP_SEG (regbuf);
  79.   pr.x.edi = FP_OFF (regbuf);
  80.   int386x (0x31, &pr, &pr, &psr);       /* Allocate A Realmode Callback */
  81.  
  82.   if (pr.x.cflag != 0)                  /* Exit If Error Allocating Callback */
  83.     return -1;
  84.  
  85.   cbseg = (unsigned short)pr.x.ecx;
  86.   cboff = (unsigned short)pr.x.edx;
  87.  
  88.   pr.x.eax = 0x200;
  89.   pr.h.bl = 0x1c;
  90.   int386 (0x31, &pr, &pr);              /* Save The Realmode INT 1Ch Vector */
  91.  
  92.   *((unsigned short *)oldvector+1) = pr.x.ecx;
  93.   *((unsigned short *)oldvector) = pr.x.edx;
  94.  
  95.   pr.x.eax = 0x201;
  96.   pr.h.bl = 0x1c;
  97.   pr.x.ecx = cbseg;
  98.   pr.x.edx = cboff;
  99.   int386 (0x31, &pr, &pr);              /* Point INT 1Ch To Callback Address */
  100.  
  101.   return 0;
  102. }
  103.  
  104. int resetpassup_1C(unsigned *oldvector)
  105. {
  106.   union REGS pr;
  107.  
  108.   pr.x.eax = 0x201;
  109.   pr.h.bl = 0x1c;
  110.   pr.x.ecx = *((unsigned short *)oldvector+1);
  111.   pr.x.edx = *((unsigned short *)oldvector);
  112.   int386 (0x31, &pr, &pr);              /* Reset Old Realmode INT 1Ch Vector */
  113.  
  114.   return 0;
  115. }
  116.  
  117. /* This handler is called by the realmode INT 1Ch by way of a DPMI callback.
  118.    It takes the return address & flags from the realmode stack (DS:ESI) and
  119.    places them into the DPMI register structure (ES:EDI) so that the routine
  120.    may return to the proper place on termination. It then initiates an INT 1Ch
  121.    in protected mode before returning control with an IRETD */
  122.  
  123. #pragma off (check_stack);
  124.  
  125. void int1C_handler (void)
  126. {
  127.   intp ();
  128. }
  129.  
  130. #pragma on (check_stack);
  131.  
  132.