发信人: riffle()
整理人: wenbobo(2002-08-13 10:45:45), 站内信件
|
/* author : *** */
/*-------------------------------------------------------------------- --*/
// TSRINT.CPP
// 本模块和TEST.CPP、TSRINTER.CPP、TSR框架LIB一起做一个project,在larg e或
// huge模式下编译生成EXE文件以后,就具有驻留及退出驻留的功能了。
#include <DOS.H>
#include <STDIO.H>
#include <STDLIB.H>
#include <PROCESS.H>
#include "INTFRAME.H"
/*-------------------------------------------------------------------- --*/
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
/*-------------------------------------------------------------------- --*/
const int INT8 = 8;
/*-------------------------------------------------------------------- --*/
// 设置栈空间大小
extern unsigned int _stklen = 8192;
/*-------------------------------------------------------------------- --*/
// 保存旧的INT 8中断服务程序地址
static void interrupt ( *oldINT8Handler )( __CPPARGS );
static void SaveHardVector( void );
static int TsrCanExit( void );
static void IntA0CallBack( void );
static void testfunc( void );
/*-------------------------------------------------------------------- --*/
/********************************************************************* ***/
static void SaveHardVector( void )
{
oldINT8Handler = getvect( INT8 );
}
/********************************************************************* ***/
/********************************************************************* ***/
static int TsrCanExit( void )
{
if ( oldINT8Handler == getvect( INT8 ) )
return 1;
else
return 0;
}
/********************************************************************* ***/
/********************************************************************* ***/
static void IntA0CallBack( void )
{
// 进入中断时的功能号 AX == REMOVECMD,则退出驻留程序。
if ( OldAX() == REMOVECMD )
{
// 准备退出驻留成功
if ( PrepareExitTSR() )
// 则调用 exit 退出整个程序
exit( EXIT_SUCCESS );
else
// 否则将AX设置成 -1,表示退出驻留失败。
SetReturnAX( 0xFFFF );
}
else
{
switch( OldAX() )
{
// 检查是否已经安装?
case CHECKINTCMD:
// 设置 AX 内容为安装标志。
SetReturnAX( INSTALLEDSIGN );
break;
case 0x00F0:
// AX == 0X00F0 测试一下,可以用 DEBUG 进行试验。
testfunc();
break;
default:
break;
}
}
}
/********************************************************************* ***/
/********************************************************************* ***/
int Install( void )
{
unsigned int *uipKeepSize;
// DOS程序执行时,PSP所在段的段值减去1就是其MCB段址。
// MCB的地3,4字节表示该MAB的节(16字节)数。
uipKeepSize = ( unsigned int * )MK_FP( _psp - 1, 3 );
// 先记住INT 8的中断向量,这里是假设本程序需要使用INT 8中断服务程序。
// 当然也可以不在本模块中检查,而在使用INT 8的模块中的安装中断向量的
// 函数中登记类似TsrCanExit的函数。
SaveHardVector();
// 登记退出检查函数。该函数判断该驻留程序是否可以退出。
// 最多可以登记16个退出检查函数。
if ( RegisterExitCallBack( TsrCanExit ) )
{
// 设置所用软中断的中断号以及中断服务程序回调函数。
// 汇编模块中的中断服务程序将调用IntA0CallBack回调函数。
SetVector( INTERFACEINT, IntA0CallBack );
// 驻留(驻留程序占用的内存由当时的MCB决定)。
// 程序在keep之前应初始化好所有数据结构,其中包括需要使用new分配 内存的情况。
// 因为C程序(for dos)启动后,其所有的内存都在该进程拥有的MCB管辖 之下,其中
// 高端是堆区,并且还事先预留了大约1K的空间给new(或其他内存分配函 数,下同)
// 使用,如果new申请的内存比较大,程序将调用INT 21的4AH功能调整M CB所管辖的
// MAB大小,当然,这同时还要求DOS内核记录的当前PSP跟MCB的所有者( Owner)PSP
// 一致,不然,调用完INT 21以后,该MCB的Owner就会改成当前PSP了。 举个例子:
// 本程序使用的是软中断INT A0,驻留以后,另外一个程序(假设为APP吧 )调用INT A0
// 的某项服务,而INT A0中断服务程序在提供该项功能时没有切换PSP, 并且使用new
// 分配较大内存,导致调用了INT 21的4A号功能,那么该MCB的Owner就被 换成了APP了,
// 并将随着APP的退出而被整个释放!
// 从这里也可以看出,驻留以后是在也不能使用new的,除非再截获INT 21的4A号功能,
// 作些支持。
keep( 0, uipKeepSize[ 0 ] );
//这句已经没有意义,只是为了消除警告用的。
return 1;
}
else
//登记失败,返回0
return 0;
}
/********************************************************************* ***/
/********************************************************************* ***/
static void testfunc( void )
{
char s[ 500 ];
s[ 499 ] = 3;
printf( "%p\n", &s[ 0] );
}
/********************************************************************* ***/
/********************************************************************* ***/
/********************************************************************* ***/
-- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.39.56]
|
|