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. |