home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / ISC366.ZIP / ISC / ISC.CPP next >
C/C++ Source or Header  |  1993-09-01  |  11KB  |  401 lines

  1. ///////////////////////////////////////////////////////////////////////////
  2. //                                                                       //
  3. //            File: Isc.cpp                                              //
  4. //            started on: 5/2/92                                         //
  5. //                                                                       //
  6. ///////////////////////////////////////////////////////////////////////////
  7. //                                                                       //
  8. //                             V3.66                                     //
  9. //                           ---------                                   //
  10. //                                                                       //
  11. ///////////////////////////////////////////////////////////////////////////
  12. //                                                                       //
  13. //                      by Ofer Laor (AKA LeucroTTA)                     //
  14. //                                                                       //
  15. ///////////////////////////////////////////////////////////////////////////
  16.  
  17. #include "isc.h";    // ISC.
  18. #include <dos.h>     // MK_FP, keep, setvect, getvect.
  19.  
  20. #ifndef __NOT_TSR__
  21.         #include <alloc.h>   // heapwalk.
  22. #endif
  23.  
  24. // static variables...
  25. char *ISC::StackFrame;
  26. unsigned long ISC::StackFrameLen= 3000; //default stack len.
  27. int ISC::ISCcount= 0;
  28.  
  29. // overload this function to handle software interrupts...
  30. //
  31. void ISC::isr (IREGS& /* regs */)
  32. {
  33.      // by default this function will make a stack frame of 3000 bytes
  34.      // for the hardware isr's to use.
  35.  
  36.      static unsigned char recursive= 0;
  37.      static unsigned old_ss, old_sp;
  38.      static ISC* me;
  39.  
  40.      if (recursive) {
  41.         isr();
  42.         return;
  43.      }
  44.      // put up a new stack frame...
  45.      recursive++;
  46.  
  47.      disable();
  48.  
  49.      me= this; // remember this...
  50.  
  51.      //This code moves the stack to another plane, please do not single
  52.      //  step through this code (Turbo Debugger might not survive having lost
  53.      //  some of it's variables)!
  54.  
  55.      old_ss= _SS;
  56.      old_sp= _SP;
  57.  
  58.      _SS= FP_SEG(&StackFrame[StackFrameLen-1]);
  59.      _SP= FP_OFF(&StackFrame[StackFrameLen-1]);
  60.  
  61.      //On this new Stack Frame You may not use local functions except in this
  62.      //  context:- me->local_function(); - this is because this function's
  63.      //  "this" is in the old stack frame!!! Also use static variables only
  64.      //  (the automatic ones are in the old stack frame context). These points
  65.      //  are only relevant IN THIS ONE FUNCTION:- you can easily call another
  66.      //  local function to do all the stuff for you (me->do_it() may use
  67.      //  automatic variables!!!).
  68.  
  69.  
  70.      // call my isr routine...
  71.      me->isr();
  72.  
  73.      disable();
  74.  
  75.      _SS= old_ss;
  76.      _SP= old_sp;
  77.  
  78.      recursive--;
  79. }
  80.  
  81. // overload this function to handle hardware interrupts...
  82. //
  83. void ISC::isr (void)
  84. {
  85.     old_vect(); // default will not work on software interrupts!!!
  86. }
  87.  
  88.  
  89. // ISCThunk.ASM routines.
  90. //
  91. extern "C" {
  92.        void far * far ThunkSet(void far *);
  93.        unsigned far   ThunkSize(void);
  94.        void far * far ThunkGetID(void);
  95. }
  96.  
  97. // this is the dispatcher called by asm code to call the correct object's
  98. // isr functions.
  99. void interrupt ISCDispatch(unsigned bp, unsigned di, unsigned si,
  100.                            unsigned ds, unsigned es, unsigned dx,
  101.                            unsigned cx, unsigned bx, unsigned ax,
  102.                            unsigned ip, unsigned cs, unsigned flags)
  103. {
  104.    ISC* isc= (ISC *)ThunkGetID();
  105.  
  106.    IREGS regs;
  107.  
  108.    regs.x.bp= bp;
  109.    regs.x.di= di;
  110.    regs.x.si= si;
  111.    regs.x.ds= ds;
  112.    regs.x.es= es;
  113.    regs.x.dx= dx;
  114.    regs.x.cx= cx;
  115.    regs.x.bx= bx;
  116.    regs.x.ax= ax;
  117.    regs.x.ip= ip;
  118.    regs.x.cs= cs;
  119.    regs.x.flags= flags;
  120.  
  121.    // software dispatch();
  122.  
  123.    isc->isr(regs); // software later...
  124.  
  125.    bp= regs.x.bp;
  126.    di= regs.x.di;
  127.    si= regs.x.si;
  128.    ds= regs.x.ds;
  129.    es= regs.x.es;
  130.    dx= regs.x.dx;
  131.    cx= regs.x.cx;
  132.    bx= regs.x.bx;
  133.    ax= regs.x.ax;
  134.    ip= regs.x.ip;
  135.    cs= regs.x.cs;
  136.    flags= regs.x.flags;
  137. }
  138.  
  139. // ■ returns a pointer to a new thunk.
  140. void far * ISC::GetLocalRoutine(void)
  141. {
  142.  
  143.     if (InitFlag)
  144.        return NULL;
  145.  
  146.     void far *newThunk;
  147.     void far *oldThunk= ThunkSet((void far *)this);
  148.     newThunk= new char[ThunkSize()];
  149.  
  150.     if (newThunk== NULL)
  151.        return NULL;
  152.  
  153.     InitFlag++; // initiated. (to prevent a class to hook more
  154.  
  155.     for (int i= 0; i< ThunkSize(); i++)
  156.         ((char far *)newThunk)[i]= ((char far *)oldThunk)[i];
  157.  
  158.     NewServerPtr= (char *) newThunk;
  159.  
  160.     return newThunk;
  161. }
  162.  
  163.  
  164. // this routine hooks isr onto the interrupt passed as an argument to it.
  165. //
  166. void ISC::activate(const int int_num)
  167. {
  168.     if (int_num==NULL)
  169.        return;
  170.  
  171.     interrupt_num= int_num;
  172.  
  173.     old_vect= getvect(interrupt_num);              // remember old vector.
  174.  
  175.     setvect(interrupt_num, (void interrupt (*)(...))GetLocalRoutine());  // set up the asm. server
  176. }
  177.  
  178.  
  179. // this function deactivates the interrupt.
  180. //
  181. void ISC::deactivate(void)
  182. {
  183.     if ((interrupt_num== NULL) || !InitFlag)  // activate did not work.
  184.        return;
  185.  
  186.     if (!this) // illegal this!!!
  187.        return;
  188.  
  189.     InitFlag= 0;  // allow activation.
  190.  
  191.     setvect(interrupt_num, old_vect);
  192.  
  193.     if (NewServerPtr)
  194.        delete NewServerPtr;
  195.  
  196.     NewServerPtr= NULL;
  197. }
  198.  
  199.  
  200.  
  201. #ifndef __NOT_TSR__
  202.  
  203. // this routine Terminates but keeps the program resident.
  204. //      note:- this method of staying resident dissallows new
  205. //      allocation from the heap (past heaplen)- during interrupt processing,
  206. //      that is because the end of the heap (during the call to
  207. //      this function) is DISCARDED!!!
  208. //
  209. // ■ does not return anything if successful.
  210. // ■ returns 1 if HEAP problem occured.
  211. // ■ returns 2 if KEEP was not successful.
  212. int ISC::TSR(const int exit_code, const unsigned long heaplen)
  213. {
  214.     struct heapinfo hi;
  215.     void *hp;
  216.     unsigned hlen;
  217.  
  218.  
  219.     hp= new char[hlen= 5]; // dummy heap value;
  220.  
  221.     if (heapcheck()== _HEAPCORRUPT)
  222.        return 1;
  223.  
  224.     hi.ptr= NULL;
  225.     while (heapwalk(&hi)== _HEAPOK) {
  226.           if (hi.in_use) {
  227.              if ((void huge *)hi.ptr> (void huge *)hp)
  228.                 hp= hi.ptr;
  229.                 hlen= (unsigned)hi.size;
  230.           }
  231.     }
  232.  
  233.  
  234.     if (heapwalk(&hi)!= _HEAPEND)
  235.        return 1;
  236.  
  237.  
  238.     keep (exit_code, (FP_OFF((void far *)hp)>> 4) + FP_SEG((void far *)hp) -
  239.                      _psp+ 1+ (((unsigned)heaplen)>> 4)+ (hlen>> 4));
  240.  
  241.     return 2;
  242. }
  243.  
  244. // this function determines if this Tsr is already resident.
  245. //      it returns 0 if not, 1 is already resident.
  246. // note- is_TSR utilizes the name space of the MCB,
  247. //       Dos 4.0 and up use that area to store the application name,
  248. //       so you can put a diffrent app_name than yourself resident) and you
  249. //       can check if other apps you need are currently running (put their
  250. //       exe's name - whithout extention).
  251. //
  252. // ■ returns 0 if not resident.
  253. // ■ returns 1 if already resident.
  254. int ISC::is_TSR(const char* app_name)
  255. {
  256.     static unsigned far *segmptr; // far ptr to seg. address of MCB.
  257.  
  258.     struct MCB {
  259.            char chain;          // 'Z' for last 'M' for others.
  260.            unsigned pid;        // pid of owner.
  261.            unsigned psize;      // size of MCB data area.
  262.            char reserved[3];    // unknown.
  263.            char name[8];        // name of task.
  264.     };
  265.  
  266.     static MCB huge *mcbPtr;
  267.     static unsigned my_pid, seg, off;
  268.     static int i;
  269.  
  270.     // insert my id into my code mcb.
  271.     seg= _psp- 1;
  272.  
  273.     mcbPtr= (MCB huge *)MK_FP(seg, 0);
  274.  
  275.     for (i= 0; i< 8; i++)
  276.         mcbPtr->name[i]= app_name[i];
  277.  
  278.     my_pid= mcbPtr->pid;
  279.  
  280.     // could not get int86x to work properly - so I did this...
  281.  
  282.     asm {
  283.         push es
  284.         push bx
  285.  
  286.         mov ah, 52h
  287.         int 21h
  288.  
  289.         mov dx, es
  290.         mov ax, bx
  291.  
  292.         pop bx
  293.         pop es
  294.     }
  295.  
  296.     seg= _DX;
  297.     off= _AX- 2;
  298.  
  299.     segmptr= (unsigned far *) MK_FP(seg, off);  // now I have the address where
  300.                                                 // segmptr is supposed to be!
  301.     seg= *segmptr; // keep seg.
  302.  
  303.     unsigned out_flag= 0;
  304.     do {
  305.  
  306.  
  307.         // set mcbPtr to point to segmptr.
  308.         //
  309.         segmptr= (unsigned far *) MK_FP(seg, 0);
  310.         mcbPtr= (MCB huge *)segmptr;
  311.  
  312.         // check see what pid it is.
  313.         //
  314.         switch (mcbPtr->pid) {
  315.  
  316.                case 0:
  317.                     // empty MCB.
  318.                case 8:
  319.                     // command com.
  320.                     break;
  321.                default:
  322.  
  323.                     // check for a code MCB block.
  324.                     //
  325.                     if (mcbPtr->pid!= seg+ 1)
  326.                        break;
  327.  
  328.                     // if it isn't my own pid.
  329.                     //
  330.                     if (mcbPtr->pid!= my_pid) {
  331.  
  332.                        // now match application names.
  333.                        //
  334.                        for (i= 0; i< 8 && (app_name[i]); i++)
  335.                            if (mcbPtr->name[i]!= app_name[i])
  336.                               break;
  337.  
  338.                        // if names matched, exit!!!
  339.                        if (i== 8 || (mcbPtr->name[i]== app_name[i]))
  340.                           out_flag++;
  341.  
  342.                        break;
  343.                     }
  344.  
  345.                     break;
  346.         }
  347.  
  348.         // check for end of chain.
  349.         //
  350.         if (mcbPtr->chain=='Z')
  351.            return 0;            // if here, not resident.
  352.  
  353.         // next mcb
  354.         seg+= mcbPtr->psize+ 1;
  355.     } while (!out_flag);
  356.  
  357.     return 1; // if here-> resident.
  358. }
  359.  
  360. #endif
  361.  
  362.  
  363. // new from V3.6- will reallocate the hardware interrupt stack...
  364. //  default stackLen will be 3000 bytes...
  365. // ■ returns 1 on success.
  366. // ■ returns 0 on failure.
  367. int ISC::reallocStack(unsigned StackLen)
  368. {
  369.     StackFrameLen= StackLen;
  370.  
  371.     delete[] StackFrame;
  372.  
  373.     StackFrame= new char[StackLen];
  374.  
  375.     return (StackFrame)?1:0;
  376. }
  377.  
  378. ISC::ISC (void)
  379. {
  380.     NewServerPtr= NULL;
  381.     InitFlag= 0; // not initiated yet.
  382.  
  383.     ISCcount++;
  384.  
  385.     // put up a stack frame if not already up.
  386.     if ((!StackFrame) && (StackFrameLen)) {
  387.        StackFrame= new char[(unsigned)StackFrameLen];
  388.     }
  389. };
  390.  
  391. ISC::~ISC (void)
  392. {
  393.     deactivate();
  394.  
  395.     // kill stack if no more ISCs are present.
  396.     if (--ISCcount<= 0) {
  397.        delete[] StackFrame;
  398.        StackFrame= NULL;
  399.     }
  400. };
  401.