Microsoft KB Archive/28568

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

Article ID: 28568

Article Last Modified on 12/1/2003

-

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

-



This article was previously published under Q28568





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 */ unsigned bp, unsigned sp, unsigned bx, unsigned dx,\ unsigned cx, unsigned ax, unsigned ip, unsigned cs,\ unsigned flags
 * 1) define INT5 0x5
 * 2) define INT21 0x21
 * 3) define SHIFTL(x, n) (_ADDRESS = 0L, _ADDRESS = (long)(x), _ADDRESS << (n))
 * 4) define HIBYTE(x) (((unsigned)(x) >> 8) & 0xff)
 * 5) define REGPAK unsigned es, unsigned ds, unsigned di, unsigned si,\

/* 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 &quot;AS IS&quot;*/ /* 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. */ /*******************************************************************/


 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) include &quot;dirzap.h&quot;

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 (&quot;DirZap is now memory resident&quot;); /* 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 query words: kbinf 1.00 1.50 5.10 6.00 6.00a 6.00ax 7.00

Keywords: kb16bitonly KB28568

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.