Terminate-and-Stay-Resident (TSR) Program ExampleLast reviewed: July 17, 1997Article ID: Q28568 |
5.10 6.00 6.00a 6.00ax 7.00 | 1.00 1.50
MS-DOS | WINDOWSkbprg
The information in this article applies to:
SUMMARYThe 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 */ } |
Additional reference words: kbinf 1.00 1.50 5.10 6.00 6.00a 6.00ax 7.00
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |