home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////
- // //
- // File: Isc.cpp //
- // started on: 5/2/92 //
- // //
- ///////////////////////////////////////////////////////////////////////////
- // //
- // V3.66 //
- // --------- //
- // //
- ///////////////////////////////////////////////////////////////////////////
- // //
- // by Ofer Laor (AKA LeucroTTA) //
- // //
- ///////////////////////////////////////////////////////////////////////////
-
- #include "isc.h"; // ISC.
- #include <dos.h> // MK_FP, keep, setvect, getvect.
-
- #ifndef __NOT_TSR__
- #include <alloc.h> // heapwalk.
- #endif
-
- // static variables...
- char *ISC::StackFrame;
- unsigned long ISC::StackFrameLen= 3000; //default stack len.
- int ISC::ISCcount= 0;
-
- // overload this function to handle software interrupts...
- //
- void ISC::isr (IREGS& /* regs */)
- {
- // by default this function will make a stack frame of 3000 bytes
- // for the hardware isr's to use.
-
- static unsigned char recursive= 0;
- static unsigned old_ss, old_sp;
- static ISC* me;
-
- if (recursive) {
- isr();
- return;
- }
- // put up a new stack frame...
- recursive++;
-
- disable();
-
- me= this; // remember this...
-
- //This code moves the stack to another plane, please do not single
- // step through this code (Turbo Debugger might not survive having lost
- // some of it's variables)!
-
- old_ss= _SS;
- old_sp= _SP;
-
- _SS= FP_SEG(&StackFrame[StackFrameLen-1]);
- _SP= FP_OFF(&StackFrame[StackFrameLen-1]);
-
- //On this new Stack Frame You may not use local functions except in this
- // context:- me->local_function(); - this is because this function's
- // "this" is in the old stack frame!!! Also use static variables only
- // (the automatic ones are in the old stack frame context). These points
- // are only relevant IN THIS ONE FUNCTION:- you can easily call another
- // local function to do all the stuff for you (me->do_it() may use
- // automatic variables!!!).
-
-
- // call my isr routine...
- me->isr();
-
- disable();
-
- _SS= old_ss;
- _SP= old_sp;
-
- recursive--;
- }
-
- // overload this function to handle hardware interrupts...
- //
- void ISC::isr (void)
- {
- old_vect(); // default will not work on software interrupts!!!
- }
-
-
- // ISCThunk.ASM routines.
- //
- extern "C" {
- void far * far ThunkSet(void far *);
- unsigned far ThunkSize(void);
- void far * far ThunkGetID(void);
- }
-
- // this is the dispatcher called by asm code to call the correct object's
- // isr functions.
- void interrupt ISCDispatch(unsigned bp, unsigned di, unsigned si,
- unsigned ds, unsigned es, unsigned dx,
- unsigned cx, unsigned bx, unsigned ax,
- unsigned ip, unsigned cs, unsigned flags)
- {
- ISC* isc= (ISC *)ThunkGetID();
-
- IREGS regs;
-
- regs.x.bp= bp;
- regs.x.di= di;
- regs.x.si= si;
- regs.x.ds= ds;
- regs.x.es= es;
- regs.x.dx= dx;
- regs.x.cx= cx;
- regs.x.bx= bx;
- regs.x.ax= ax;
- regs.x.ip= ip;
- regs.x.cs= cs;
- regs.x.flags= flags;
-
- // software dispatch();
-
- isc->isr(regs); // software later...
-
- bp= regs.x.bp;
- di= regs.x.di;
- si= regs.x.si;
- ds= regs.x.ds;
- es= regs.x.es;
- dx= regs.x.dx;
- cx= regs.x.cx;
- bx= regs.x.bx;
- ax= regs.x.ax;
- ip= regs.x.ip;
- cs= regs.x.cs;
- flags= regs.x.flags;
- }
-
- // ■ returns a pointer to a new thunk.
- void far * ISC::GetLocalRoutine(void)
- {
-
- if (InitFlag)
- return NULL;
-
- void far *newThunk;
- void far *oldThunk= ThunkSet((void far *)this);
- newThunk= new char[ThunkSize()];
-
- if (newThunk== NULL)
- return NULL;
-
- InitFlag++; // initiated. (to prevent a class to hook more
-
- for (int i= 0; i< ThunkSize(); i++)
- ((char far *)newThunk)[i]= ((char far *)oldThunk)[i];
-
- NewServerPtr= (char *) newThunk;
-
- return newThunk;
- }
-
-
- // this routine hooks isr onto the interrupt passed as an argument to it.
- //
- void ISC::activate(const int int_num)
- {
- if (int_num==NULL)
- return;
-
- interrupt_num= int_num;
-
- old_vect= getvect(interrupt_num); // remember old vector.
-
- setvect(interrupt_num, (void interrupt (*)(...))GetLocalRoutine()); // set up the asm. server
- }
-
-
- // this function deactivates the interrupt.
- //
- void ISC::deactivate(void)
- {
- if ((interrupt_num== NULL) || !InitFlag) // activate did not work.
- return;
-
- if (!this) // illegal this!!!
- return;
-
- InitFlag= 0; // allow activation.
-
- setvect(interrupt_num, old_vect);
-
- if (NewServerPtr)
- delete NewServerPtr;
-
- NewServerPtr= NULL;
- }
-
-
-
- #ifndef __NOT_TSR__
-
- // this routine Terminates but keeps the program resident.
- // note:- this method of staying resident dissallows new
- // allocation from the heap (past heaplen)- during interrupt processing,
- // that is because the end of the heap (during the call to
- // this function) is DISCARDED!!!
- //
- // ■ does not return anything if successful.
- // ■ returns 1 if HEAP problem occured.
- // ■ returns 2 if KEEP was not successful.
- int ISC::TSR(const int exit_code, const unsigned long heaplen)
- {
- struct heapinfo hi;
- void *hp;
- unsigned hlen;
-
-
- hp= new char[hlen= 5]; // dummy heap value;
-
- if (heapcheck()== _HEAPCORRUPT)
- return 1;
-
- hi.ptr= NULL;
- while (heapwalk(&hi)== _HEAPOK) {
- if (hi.in_use) {
- if ((void huge *)hi.ptr> (void huge *)hp)
- hp= hi.ptr;
- hlen= (unsigned)hi.size;
- }
- }
-
-
- if (heapwalk(&hi)!= _HEAPEND)
- return 1;
-
-
- keep (exit_code, (FP_OFF((void far *)hp)>> 4) + FP_SEG((void far *)hp) -
- _psp+ 1+ (((unsigned)heaplen)>> 4)+ (hlen>> 4));
-
- return 2;
- }
-
- // this function determines if this Tsr is already resident.
- // it returns 0 if not, 1 is already resident.
- // note- is_TSR utilizes the name space of the MCB,
- // Dos 4.0 and up use that area to store the application name,
- // so you can put a diffrent app_name than yourself resident) and you
- // can check if other apps you need are currently running (put their
- // exe's name - whithout extention).
- //
- // ■ returns 0 if not resident.
- // ■ returns 1 if already resident.
- int ISC::is_TSR(const char* app_name)
- {
- static unsigned far *segmptr; // far ptr to seg. address of MCB.
-
- struct MCB {
- char chain; // 'Z' for last 'M' for others.
- unsigned pid; // pid of owner.
- unsigned psize; // size of MCB data area.
- char reserved[3]; // unknown.
- char name[8]; // name of task.
- };
-
- static MCB huge *mcbPtr;
- static unsigned my_pid, seg, off;
- static int i;
-
- // insert my id into my code mcb.
- seg= _psp- 1;
-
- mcbPtr= (MCB huge *)MK_FP(seg, 0);
-
- for (i= 0; i< 8; i++)
- mcbPtr->name[i]= app_name[i];
-
- my_pid= mcbPtr->pid;
-
- // could not get int86x to work properly - so I did this...
-
- asm {
- push es
- push bx
-
- mov ah, 52h
- int 21h
-
- mov dx, es
- mov ax, bx
-
- pop bx
- pop es
- }
-
- seg= _DX;
- off= _AX- 2;
-
- segmptr= (unsigned far *) MK_FP(seg, off); // now I have the address where
- // segmptr is supposed to be!
- seg= *segmptr; // keep seg.
-
- unsigned out_flag= 0;
- do {
-
-
- // set mcbPtr to point to segmptr.
- //
- segmptr= (unsigned far *) MK_FP(seg, 0);
- mcbPtr= (MCB huge *)segmptr;
-
- // check see what pid it is.
- //
- switch (mcbPtr->pid) {
-
- case 0:
- // empty MCB.
- case 8:
- // command com.
- break;
- default:
-
- // check for a code MCB block.
- //
- if (mcbPtr->pid!= seg+ 1)
- break;
-
- // if it isn't my own pid.
- //
- if (mcbPtr->pid!= my_pid) {
-
- // now match application names.
- //
- for (i= 0; i< 8 && (app_name[i]); i++)
- if (mcbPtr->name[i]!= app_name[i])
- break;
-
- // if names matched, exit!!!
- if (i== 8 || (mcbPtr->name[i]== app_name[i]))
- out_flag++;
-
- break;
- }
-
- break;
- }
-
- // check for end of chain.
- //
- if (mcbPtr->chain=='Z')
- return 0; // if here, not resident.
-
- // next mcb
- seg+= mcbPtr->psize+ 1;
- } while (!out_flag);
-
- return 1; // if here-> resident.
- }
-
- #endif
-
-
- // new from V3.6- will reallocate the hardware interrupt stack...
- // default stackLen will be 3000 bytes...
- // ■ returns 1 on success.
- // ■ returns 0 on failure.
- int ISC::reallocStack(unsigned StackLen)
- {
- StackFrameLen= StackLen;
-
- delete[] StackFrame;
-
- StackFrame= new char[StackLen];
-
- return (StackFrame)?1:0;
- }
-
- ISC::ISC (void)
- {
- NewServerPtr= NULL;
- InitFlag= 0; // not initiated yet.
-
- ISCcount++;
-
- // put up a stack frame if not already up.
- if ((!StackFrame) && (StackFrameLen)) {
- StackFrame= new char[(unsigned)StackFrameLen];
- }
- };
-
- ISC::~ISC (void)
- {
- deactivate();
-
- // kill stack if no more ISCs are present.
- if (--ISCcount<= 0) {
- delete[] StackFrame;
- StackFrame= NULL;
- }
- };
-