精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>DOS编程>>DOS中断驻留框架(3/6)

主题:DOS中断驻留框架(3/6)
发信人: riffle()
整理人: wenbobo(2002-08-13 10:45:45), 站内信件
/* author : *** */
/*--------------------------------------------------------------------
--*/

// TSRFRAME.CPP
//本模块和INTFRAME.ASM一起做一个project,在large或huge模式下编译成LIB。


#include <DOS.H>
#include <STDIO.H>
#include <STDLIB.H>
#include <PROCESS.H>
#include "INTFRAME.H"

/*--------------------------------------------------------------------
--*/

extern "C"
{
extern void SetVectorI( int VerctorNum, void far *FunPtr );
}

/*--------------------------------------------------------------------
--*/

const int MAXCANEXITCALLBACK = 16;
static unsigned int CanExitCallBackRegisterPtr = 0;
static int ( *CanExitCallBack[ MAXCANEXITCALLBACK ] )( void ) =
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };

/*--------------------------------------------------------------------
--*/

static void InitExitTSR( void );
static int TsrCanExit( void );

/*--------------------------------------------------------------------
--*/
/*********************************************************************
***/
static void InitExitTSR( void )
{
  unsigned int *Exe22Int;
  union REGS regs;
  struct SREGS sregs;
  unsigned int uiReturnSeg = FP_SEG( GetIntReturnAddr() );
  unsigned int uiReturnOfs = FP_OFF( GetIntReturnAddr() );

  // 设置PSP中INT 22的地址为GetIntReturnAddr(),即TSR程序返回DOS之前先

  // GetIntReturnAddr()
  // PSP 段地址偏移 0X0A 处存放该进程返回DOS时的返回地址。程序执行exit

  // 令时最终将转向此处,这是INT 21内核规定的。
  // 这里取的是中断服务程序中IRET指令前面的地址。
  // 这样,当调用软中断使整个驻留程序退出时,DOS在完成关闭该进程所有打

  // 的文件,释放它所占用的内存,等等所有清理工作之后,最后返回到此处,

  // 后恢复各个寄存器,最后IRET,就象执行一个普通的软中断一样。
  Exe22Int = ( unsigned int * )MK_FP( _psp, 0x0a );
  Exe22Int[ 0 ] = uiReturnOfs;
  Exe22Int[ 1 ] = uiReturnSeg;

  // 设置INT 22、23、24中断向量是为了安全起见。
  // 设置中断向量INT 22
  regs.h.ah = 0x25;
  regs.h.al = 0x22;
  regs.x.dx = uiReturnOfs;
  sregs.ds = uiReturnSeg;
  intdosx( &regs, &regs, &sregs );

  // 设置中断向量INT 23
  regs.h.ah = 0x25;
  regs.h.al = 0x23;
  regs.x.dx = uiReturnOfs;
  sregs.ds = uiReturnSeg;
  intdosx( &regs, &regs, &sregs );
}
/*********************************************************************
***/

/*********************************************************************
***/
static int TsrCanExit( void )
{
  // 反向逐个调用已经登记的驻留退出检查函数,各驻留退出检查函数返回1表

  // 示可以退出驻留,否则不能退出驻留。
  for( int i = CanExitCallBackRegisterPtr - 1; i >= 0; i-- )
    if ( CanExitCallBack[ i ] != NULL )
      if ( !CanExitCallBack[ i ]() )
        // 有一个函数表明不能退出驻留,则返回0,表示不能退出驻留。
return 0;

  // 所有检查函数都表示能退出驻留则返回1,表示可以退出驻留。
  return 1;
}
/*********************************************************************
***/

/*********************************************************************
***/
int PrepareExitTSR( void )
{
  检查是否能退出驻留
  if ( TsrCanExit() )
    {
      // 取当前的PSP
      SaveCurPSP();
      // 设置TSR的返回地址
      InitExitTSR();
      // 将PSP设置成TSR的PSP
      SetPSP( _psp );
      // 返回1,表示可以退出驻留。
      return 1;
    }
  else
    // 否则返回0,表示不能退出驻留。
    return 0;
}
/*********************************************************************
***/

/*********************************************************************
***/
int RegisterExitCallBack( int ( *ExitCallBack )( void ) )
{
  // 以栈的方式(后进先出)登记退出检查函数。
  if ( CanExitCallBackRegisterPtr < MAXCANEXITCALLBACK )
{
CanExitCallBack[ CanExitCallBackRegisterPtr ] = ExitCallBack;
CanExitCallBackRegisterPtr++;
// 登记成功,返回1。
return 1;
}
else
// 登记失败,返回0。
return 0;
}
/*********************************************************************
***/

/*********************************************************************
***/
void SetVector( int VerctorNum, void far *FunPtr )
{
设置中断向量及回调函数。
SetVectorI( VerctorNum, FunPtr );
}
/*********************************************************************
***/
/*********************************************************************
***/
/*********************************************************************
***/

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.39.56]

[关闭][返回]