Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

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


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

↑ Back to the top


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       */ }

↑ Back to the top


Keywords: KB28568, kb16bitonly

↑ Back to the top

Article Info
Article ID : 3999064
Revision : 5
Created on : 8/20/2020
Published on : 8/20/2020
Exists online : False
Views : 80