Terminate-and-Stay-Resident (TSR) Program Example

Article translations Article translations
Article ID: 28568 - View products that this article applies to.
This article was previously published under Q28568
Expand all | Collapse all

SUMMARY

The following code example demonstrates using Microsoft C to write a terminate-and-stay-resident (TSR) program. The example also demonstrates using the following functions in the C run-time library:
   _dos_setvect
   _dos_getvect
   _dos_keep
   _chain_intr
   spawnXXX
				

MORE INFORMATION

DIRZAP.MAK
----------

DIRZAP.OBJ:     DIRZAP.C
          CL -AM -c DIRZAP.C
          LINK DIRZAP.OBJ;

DIRZAP.H
--------

/********************************************************************/ 
/*                                                                  */ 
/*                            DirZap.h                              */ 
/*                                                                  */ 
/*        This header file defines a global variable, macros,       */ 
/*        function pointers, and function prototypes needed         */ 
/*        in the DirZap.c program.                                  */ 
/*                                                                  */ 
/*                                                                  */ 
/********************************************************************/ 

/* Global Variable For Macro SHIFTL(x, n) */ 
long _ADDRESS;

/* Macro Definitions */ 
#define INT5  0x5
#define INT21 0x21
#define SHIFTL(x, n) (_ADDRESS = 0L, _ADDRESS = (long)(x), _ADDRESS << (n))
#define HIBYTE(x) (((unsigned)(x) >> 8) & 0xff)
#define REGPAK unsigned es, unsigned ds, unsigned di, unsigned si,\ 
               unsigned bp, unsigned sp, unsigned bx, unsigned dx,\ 
               unsigned cx, unsigned ax, unsigned ip, unsigned  cs,\ 
               unsigned flags

/* Function Pointers */ 
void (interrupt far *save_dir_adr)();
/* Saves address of the original interrupt service routine */ 

void (interrupt far *set_dir_adr)();
/* This function pointer gets set to the address of the new
   interrupt service routine 'set_dir' */ 

void (interrupt far *reset_dir_adr)();
/* This function pointer gets set to the address of the new
   interrupt service routine 'reset_dir' */ 

/* Function Declarations */ 
void cdecl interrupt far set_dir(REGPAK);
/* This is the new service routine which zaps the directory
   interrupt routines. */ 

void interrupt far reset_dir(void);
/* This routine toggles between setting and disabling the
   directory interrupt routines */ 

unsigned _get_memsize(void);
/* This function gets the number of bytes to keep resident */ 

short _set_shell(void);
/* Sets a DOS shell. */ 

DIRZAP.C
--------

/*******************************************************************/ 
/*                                                                 */ 
/*                        DirZap.c                                 */ 
/*                                                                 */ 
/*  This is an illustration of a Terminate-and-Stay-Resident       */ 
/*  program. It traps and disables the directory interrupts for    */ 
/*  MkDir, RmDir, and ChDir.  When DirZap is in memory you can     */ 
/*  toggle it on and off with the PrintScreen key.  When it is     */ 
/*  on you will not be able to change directories or make or       */ 
/*  remove any directories.                                        */ 
/*  The PrintScreen key and directories have nothing to do with    */ 
/*  TSR programming.  They were just randomly picked to create     */ 
/*  an application.  This program is not intended to be a complete */ 
/*  application.  It's intent is to demonstrate how to write a     */ 
/*  TSR.  You can take the concept used here and incorporate it    */ 
/*  in to your own program.                                        */ 
/*  Below is a summary of what this program does :                 */ 
/*   - Save the address of INT 21                                  */ 
/*   - Revector INT 21 to a routine that disables the directory    */ 
/*     operations.                                                 */ 
/*   - Revector the PrintScreen interrupt to a routine that will   */ 
/*     toggle DirZap on and off.                                   */ 
/*   - Execute a _dos_keep to make the program resident            */ 
/*                                                                 */ 
/*                                                                 */ 
/*   Copyright (c) Microsoft Corp 1988. All rights reserved.       */ 
/*                                                                 */ 
/*  To run:                                                        */ 
/*          1) Type DirZap at dos prompt                           */ 
/*          2) The PRINT SCREEN key now toggles                    */ 
/*             DirZap on and off but no memory                     */ 
/*             is freed.                                           */ 
/*                                                                 */ 
/*******************************************************************/ 
/* NOTE:                                                           */ 
/*                                                                 */ 
/* THIS PROGRAM, ITS USE, OPERATION AND SUPPORT IS PROVIDED "AS IS"*/ 
/* WITHOUT WARRANTY OF ANY  KIND, EITHER EXPRESSED OR IMPLIED,     */ 
/* INCLUDING, BUT  NOT LIMITED TO, THE IMPLIED WARRANTIES OF        */ 
/* MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE.          */ 
/* THE ENTIRE RISK  AS TO THE QUALITY AND  PERFORMANCE OF THIS     */ 
/* PROGRAM IS WITH THE USER. IN NO EVENT SHALL MICROSOFT BE LIABLE */ 
/* FOR ANY DAMAGES  INCLUDING, WITHOUT LIMITATION,  ANY LOST       */ 
/* PROFITS,  LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL     */ 
/* DAMAGES ARISING THE USE OR INABILITY TO USE SUCH PROGRAM, EVEN  */ 
/* IF MICROSOFT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES*/ 
/* OR FOR ANY CLAIM BY ANY OTHER PARTY.                            */ 
/*******************************************************************/ 

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include "dirzap.h"

extern unsigned _psp;           /* _psp = segment address of PSP   */ 
unsigned far    *psp_pointer;   /* To retrieve the memsize to stay */ 
                                /* resident                        */ 
short           hot_key=1;      /* To toggle dirzap on and off     */ 

void main(void)
{

      /***************************************/ 
      /*                                     */ 
      /* Revector the directory interrupts   */ 
      /*                                     */ 
      /***************************************/ 
      save_dir_adr = _dos_getvect(INT21); /* Save original address  */ 
      set_dir_adr  = set_dir;            /* Get addr of new routine */ 

      /***************************************/ 
      /*                                     */ 
      /* Revector the PRINT SCREEN interrupt */ 
      /*                                     */ 
      /***************************************/ 
      reset_dir_adr = reset_dir;          /* Get addr of new routine*/ 
      _dos_setvect (INT5, reset_dir_adr); /* Revector to new routine*/ 


      /***************************************/ 
      /*                                     */ 
      /*      Become memory resident.        */ 
      /*                                     */ 
      /***************************************/ 
      _dos_keep(0, _get_memsize());

      printf ("DirZap is now memory resident");  /* Inform the user */ 

}

void cdecl interrupt far set_dir(REGPAK)
{
/********************************************************************/ 
/*                                                                  */ 
/*  DS:DX points to the string entered by the user for MkDir, RmDir */ 
/*  and ChDir.  This function makes that string null so that        */ 
/*  the user will no longer be able to make, remove, or change      */ 
/*  directories.                                                    */ 
/*  WARNING: When compiled at high warning levels, several warnings */ 
/*  are generated. This is because several elements of REGPAK are   */ 
/*  not referenced. These warnings should be ignored.               */ 
/*                                                                  */ 
/********************************************************************/ 

   if (HIBYTE(ax) == 0x39 || HIBYTE(ax) == 0x3A || HIBYTE(ax) == 0x3B)
      dx=0;
   _chain_intr(save_dir_adr);
}

void interrupt far reset_dir()
{
   /****************************************************************/ 
   /*                                                              */ 
   /*  This function is used to toggle DirZap on and off.          */ 
   /*                                                              */ 
   /****************************************************************/ 

   if (hot_key)
   {
      hot_key=0;
      _dos_setvect(INT21, save_dir_adr);  /* Reset initial vector  */ 
   }
   else
   {
      hot_key=1;
      _dos_setvect(INT21, set_dir_adr);   /* Install DirZap again  */ 
      _chain_intr(set_dir_adr);    /* Chain to the Zapper function */ 
   }
}

unsigned _get_memsize()
{
   psp_pointer = (int far *) SHIFTL(_psp, 16); /* Get segment of the*/ 
                                               /* PSP               */ 
   return(psp_pointer[1] - _psp);            /* Amount of memory to */ 
                                             /* stay resident       */ 
}
				

Properties

Article ID: 28568 - Last Review: December 1, 2003 - Revision: 2.0
APPLIES TO
  • Microsoft C Professional Development System 5.1
  • Microsoft C Professional Development System 6.0
  • Microsoft C Professional Development System 6.0a
  • Microsoft C Professional Development System 6.0a
  • Microsoft C/C++ Professional Development System 7.0
  • Microsoft Visual C++ 1.0 Professional Edition
  • Microsoft Visual C++ 1.5 Professional Edition
Keywords: 
kb16bitonly KB28568
Retired KB Content Disclaimer
This article was written about products for which Microsoft no longer offers support. Therefore, this article is offered "as is" and will no longer be updated.

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com