📄 tsrexamp.c
字号:
/*
TSREXAMP.C
by Raymond J. Michels
with revisions by Tim Paterson
and Andrew Schulman
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
#include "tsr.h"
#define STACK_SIZE 8192 /* must be 16 byte boundaray */
#define SET_DTA 0x1a /* SET Disk Transfer Address */
#define GET_DTA 0x2f /* GET Disk Transfer Address */
#define DOS_EXIT 0x4C /* DOS terminate (exit) */
#define KEYBOARD_PORT 0x60 /* KEYBOARD Data Port */
#define PSP_TERMINATE 0x0A /* Termination addr. in our PSP */
#define PSP_PARENT_PSP 0x16 /* Parent's PSP from our PSP */
#define PSP_ENV_ADDR 0x2c /* environment address from PSP */
#define HOT_KEY 32 /* Hot Key along with ALT (D)*/
#define RIGHT_SHIFT 1
#define LEFT_SHIFT 2
#define CTRL_KEY 4
#define ALT_KEY 8
#define MULTIPLEX_ID 0xC0
#define INSTALL_CHECK 0x00
#define INSTALLED 0xFF
#define DEINSTALL 0x01
#define PARAGRAPHS(x) ((FP_OFF(x) + 15) >> 4)
unsigned char multiplex_id = MULTIPLEX_ID;
char far *stack_ptr; /* pointer to TSR stack */
unsigned ss_save; /* slot for stack segment register */
unsigned sp_save; /* slot for stack pointer register */
int tsr_already_active = 0; /* true if TSR active */
int popup_while_dos_busy = 0; /* true if hot key hit while dos busy */
int int_28_in_progress = 0; /* true if INT 28 in progress */
int unsafe_flag = 0; /* true if INT 13 in progress */
unsigned keycode;
unsigned foreground_psp; /* PSP of process we've interrupted */
unsigned foreground_dta_seg; /* DTA of process we've interrupted */
unsigned foreground_dta_off;
char buf[20]; /* work buffer */
unsigned long TerminateAddr; /* used during de-install */
union REGS regs; /* register work structures */
struct SREGS sregs;
struct ExtErr ErrInfo; /* save area for extended error info */
int hot_key; /* keycode for activation */
int shift_key; /* shift status bits (alt, ctrl..) */
int user_key_set = 0;
/* Save areas for old interrupt pointers */
INTVECT old_int8, old_int9, old_int10, old_int13, old_int1b, old_int23;
INTVECT old_int24, old_int28, old_int2f;
#ifdef DOS_SWAP
extern int dos_critical; /* used by DOSSWAP.C */
INTVECT old_int2a;
void interrupt far new_int2a(INTERRUPT_REGS);
#endif
/* PROTOTYPES FOR THIS MODULE */
void interrupt far new_int8(INTERRUPT_REGS);
void interrupt far new_int9(INTERRUPT_REGS);
extern void interrupt far new_int13(void); /* in TSRUTIL.ASM */
void interrupt far new_int1b(INTERRUPT_REGS);
void interrupt far new_int23(INTERRUPT_REGS);
void interrupt far new_int24(INTERRUPT_REGS);
void interrupt far new_int28(INTERRUPT_REGS);
void interrupt far new_int2f(INTERRUPT_REGS);
void tsr_function(void);
void tsr_exit(void);
void usage(char *);
int UnlinkVect(int Vect, INTVECT NewInt, INTVECT OldInt);
void parse_cmd_line(int argc, char *argv[]);
void main(int argc,char *argv[]);
/*********
* TIMER INTERRUPT HANDLER
*********/
void interrupt far new_int8(INTERRUPT_REGS r)
{
#ifdef DOS_SWAP
if (!tsr_already_active && popup_while_dos_busy &&
!dos_critical && !unsafe_flag)
#else
if (!tsr_already_active && popup_while_dos_busy &&
!DosBusy() && !unsafe_flag)
#endif
{
popup_while_dos_busy = 0;
tsr_already_active = 1;
(*old_int8)(); /* process timer tick */
_enable(); /* turn interrupts back on */
tsr_function();
tsr_already_active = 0;
}
else
(*old_int8)(); /* process timer tick */
}
/**********
* KEYBOARD INTERRUPT HANDLER
**********/
void interrupt far new_int9(INTERRUPT_REGS r)
{
if (! tsr_already_active)
{
if ((keycode = inp(KEYBOARD_PORT)) != hot_key)
_chain_intr(old_int9);
if ((_bios_keybrd(_KEYBRD_SHIFTSTATUS) &
shift_key) == shift_key)
{
#ifdef USES_DISK
if (!unsafe_flag)
{
#endif
popup_while_dos_busy = 0;
tsr_already_active = 1;
(*old_int9)(); /* send key to old int routine */
tsr_function();
tsr_already_active = 0;
#ifdef USES_DISK
}
else
{
popup_while_dos_busy = 1;
_chain_intr(old_int9);
}
#endif
}
else
_chain_intr(old_int9);
}
else
_chain_intr(old_int9);
}
/*********
* CTRL-BREAK INTERRUPT HANDLER
*********/
void interrupt far new_int1b(INTERRUPT_REGS r)
{
/* do nothing */
}
/**********
* CTRL-C INTERRUPT HANDLER
**********/
void interrupt far new_int23(INTERRUPT_REGS r)
{
/* do nothing */
}
/**********
* CRTITICAL ERROR INTERRUPT HANDLER
**********/
void interrupt far new_int24(INTERRUPT_REGS r)
{
if (_osmajor >= 3)
r.ax = 3; /* fail dos function */
else
r.ax = 0;
}
/**********
* DOS IDLE INTERRUPT HANDLER
**********/
void interrupt far new_int28(INTERRUPT_REGS r)
{
int_28_in_progress++;
#ifdef DOS_SWAP
if (popup_while_dos_busy && !dos_critical
&& !tsr_already_active && !unsafe_flag)
#else
if (popup_while_dos_busy && (!Int28DosBusy())
&& !tsr_already_active && !unsafe_flag)
#endif
{
tsr_already_active = 1;
tsr_function();
tsr_already_active = 0;
}
int_28_in_progress--;
_chain_intr(old_int28);
}
#ifdef DOS_SWAP
/*********
* DOS INTERNAL INTERRUPT HANDLER
*********/
void interrupt far new_int2a(INTERRUPT_REGS r)
{
switch (r.ax & 0xff00)
{
case 0x8000: /* start critical section */
dos_critical++;
break;
case 0x8100: /* end critical section */
case 0x8200: /* end critical section */
if (dos_critical) /* don't go negative */
dos_critical--;
break;
default:
break;
}
_chain_intr(old_int2a);
}
#endif
/*********
* DOS MULTIPLEX INTERRUPT HANDLER
*********/
void interrupt far new_int2f(INTERRUPT_REGS r)
{
unsigned ah = r.ax >> 8;
unsigned al = r.ax & 0xFF;
if (ah == multiplex_id)
{
if (al == INSTALL_CHECK)
r.ax |= INSTALLED;
else if (al == DEINSTALL)
{
// because of stack swap, pass arg in static variable.
TerminateAddr = ((long)r.bx << 16) + r.dx;
if (! tsr_already_active) /* don't exit if we're active */
{
_enable(); /* STI */
tsr_exit();
// If we got here, we weren't able to unlink
r.ax = 0xFFFF; //let caller know we're still there
// MSC 6.0 /Ox optimizes the above instruction away
// get it back by using the value in ax
tsr_already_active = -r.ax;
// set to 1 to prevent any more action
}
}
}
else
_chain_intr(old_int2f);
}
/**********
* TSR ACTIVE SECTION
**********/
void tsr_function()
{
set_stack();
#ifdef DOS_SWAP
if (SaveDosSwap() && !int_28_in_progress)
#else
if (DosBusy() && !int_28_in_progress)
#endif
popup_while_dos_busy = 1; /* set flag: next INT 8,28 activates us */
else
{
popup_while_dos_busy = 0;
/* save old interrupt-CTRL-BREAK, CTRL-C and CRIT ERROR */
old_int1b = _dos_getvect(0x1b);
old_int23 = _dos_getvect(0x23);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -