/*--------------------------------------------------------------------------*/
/*	Program name: 4_3_7.C                                               */
/*	Compile mode: Tiny                                                  */
/*	Image   file: 4_3_7.COM                                             */
/*	Remove  tool: REMOVE.COM                                            */
/*	Note        : This program can record file name and change name.    */
/*                    And it can read sector data from file and write them  */
/*                    to file.                                              */
/*		      It is a protection broken TSR program.                */
/*                    All right reserved !!                                 */
/*--------------------------------------------------------------------------*/


#include	<stdio.h>
#include	<stdarg.h>
#include	<string.h>
#include	<dos.h>
#include	<fcntl.h>
#include	<io.h>

unsigned	int	TSR_SS;
unsigned	int	TSR_SP;
unsigned	int	TSR_DTA_SEG;
unsigned	int	TSR_DTA_OFF;
unsigned	int	TSR_PSP;
unsigned	int	OLD_SS;
unsigned	int	OLD_SP;
unsigned	int	OLD_DTA_SEG;
unsigned	int	OLD_DTA_OFF;
unsigned	int	OLD_PSP;
unsigned	int	Busy;
char		far	*InDos;
extern	void	far	*_heapbase;



void	interrupt	(*OldInt09)(void);
void	interrupt	(*OldInt13)(void);
void	interrupt	(*OldInt21)(void);
void	interrupt	(*OldInt28)(void);
void	interrupt	(*OldInt60)(void);
void	interrupt	NewInt09(void);
void	interrupt	NewInt13( unsigned BP,unsigned DI,unsigned SI,
				  unsigned DS,unsigned ES,unsigned DX,
				  unsigned CX,unsigned BX,unsigned AX,
				  unsigned IP,unsigned CS,unsigned FLAGS );
void	interrupt	NewInt21( unsigned BP,unsigned DI,unsigned SI,
				  unsigned DS,unsigned ES,unsigned DX,
				  unsigned CX,unsigned BX,unsigned AX,
				  unsigned IP,unsigned CS,unsigned FLAGS );
void	interrupt	NewInt28(void);
void	interrupt	NewInt60(void);

int	Printf(char *fmt, ... );
void	Activate(void);
void	Dump_msg(void);
void	load_reg(void);


struct	Reg_buf	{	unsigned	ax_1,bx_1,cx_1,dx_1;
			unsigned	ax_2,bx_2,cx_2,dx_2;
			unsigned	flag_2,bytes,names;
		}	reg_buf[100];
char	name_buf[0x1000];
int	reg_count;
int	load_count;
int	dummy_read;

#define	KeyState	*((int far *)0x00400017)
#define	KeySelect	0x0005

/*----------------- Utilities ----------------------------------------------*/

int	Printf(char *fmt, ... )
{	va_list	argptr;
	char	str[140];
	int	cnt,i;
	union	REGS	reg;

	va_start(argptr,format);	/* Get the parameter		*/

	cnt=vsprintf(str,fmt,argptr);	/* Put output string in str[]	*/
	for(i=0;i<cnt;i++)		/* Use INT 10H to display string*/
	{	reg.h.ah=0x0E;
		reg.h.al=str[i];
		reg.h.bh=0;
		reg.h.bl=5;
		int86(0x10,&reg,&reg);
	}

	va_end(argptr);			/* va function end		*/
	return(cnt);
}

void	Dump_msg(void)
{	int		i,j,len;
	unsigned	*ptr;

	Printf( "\n\r AX    BX    CX    DX    AX    BX    CX    DX   "
		"FLAG  BYTE  NAME\n\r");
	for(i=0,ptr=(unsigned *)reg_buf;i<reg_count;i++)
	{	for(j=0;j<sizeof(reg_buf[0])/2;j++,ptr++)
			Printf("%04X  ",*ptr);
		Printf("\n\r");
		if ((i+1)%2==0)Printf("\n\r");
	}


	Printf("\n\r");
	for(i=0;(len=strlen(name_buf+i))!=0;i+=len+1)
		Printf("%s\n\r",name_buf+i);
}

/*----------------- NewInt09 -----------------------------------------------*/

void	interrupt	NewInt09(void)
{
	(*OldInt09)();			/* Execute old ISR		*/

	disable();			/* Disable interrupt !!		*/
	if (Busy)	return;		/* Test Busy semaphore		*/
	Busy=1;				/* Set  Busy semaphore		*/
	enable();			/* Enable  interrupt !!		*/

	if ( ( (KeyState & KeySelect) != KeySelect) || (*InDos) )
	{	Busy=0;			/* If hot key is not pressed	*/
		return;			/* or DOS is busy then return	*/
	}

	Activate();			/* Do the TSR routine		*/

	Busy=0;				/* Reset Busy semaphore		*/
	return;				/* Return to interrupted program*/
}

void	Activate(void)
{	register	unsigned	Temp_DS;

	OLD_SS=_SS;			/* Save old stack segment	*/
	OLD_SP=_SP;			/* Save old stack pointer	*/

	disable();			/* Disable interrupt to switch	*/
	_SS=TSR_SS;			/* stack to TSR's own		*/
	_SP=TSR_SP;			/*				*/
	enable();			/* Switch done			*/


	_AH=0x2F;			/* Get old DTA address		*/
	geninterrupt(0x21);		/*				*/
	OLD_DTA_SEG=_ES;		/* Save it in OLD_DTA_SEG and	*/
	OLD_DTA_OFF=_BX;		/* OLD_DTA_OFF			*/

	_DX=TSR_DTA_OFF;		/* Use DOS function call to	*/
	Temp_DS=_DS;			/* switch DTA to TSR's own	*/
	_DS=TSR_DTA_SEG;		/* Note: _DS will be destoried	*/
	_AH=0x1A;			/*       so it must be save in	*/
	geninterrupt(0x21);		/*       Temp_DS, and restore	*/
	_DS=Temp_DS;			/*       it after calling	*/


	if (!*InDos)			/* If DOS is idle then switch	*/
	{	_AH=0x51;		/* PSP to TSR its own		*/
		geninterrupt(0x21);	/*				*/
		OLD_PSP=_BX;		/*				*/
		_BX=TSR_PSP;		/*				*/
		_AH=0x50;		/*				*/
		geninterrupt(0x21);	/*				*/
	}


	Dump_msg();			/* Dump name buffer		*/


	if (!*InDos)			/* If DOS is idle then restore	*/
	{	_BX=OLD_PSP;		/* calling program's psp	*/
		_AH=0x50;		/*				*/
		geninterrupt(0x21);	/*				*/
	}

	_DX=OLD_DTA_OFF;		/* Restore old DTA		*/
	Temp_DS=_DS;
	_DS=OLD_DTA_SEG;
	_AH=0x1A;
	geninterrupt(0x21);
	_DS=Temp_DS;


	disable();			/* Restore old stack		*/
	_SS=OLD_SS;
	_SP=OLD_SP;
	enable();

	return;				/* Activate routine end		*/
}

/*----------------- NewInt13 -----------------------------------------------*/

void	interrupt	NewInt13( unsigned BP,unsigned DI,unsigned SI,
				  unsigned DS,unsigned ES,unsigned DX,
				  unsigned CX,unsigned BX,unsigned AX,
				  unsigned IP,unsigned CS,unsigned FLAGS )
{	static	union	REGS	regs;
	static	struct	SREGS	sregs;
	static	int	fh;
	static	char	reg_file[]="REGISTER.DAT";
	static	char	fake_file[]="A_SECTOR.DAT";
	static	char	sector_file[]="A_SECTOR.DAT";


	if ((DX%256!=0)||(AX/256==0)||(*InDos)||(Busy))	goto	i13_done;

	Busy=1;

	regs.x.ax=AX;
	regs.x.bx=BX;
	regs.x.cx=CX;
	regs.x.dx=DX;
	regs.x.si=SI;
	regs.x.di=DI;
	regs.x.flags=FLAGS;
	sregs.es=ES;
	sregs.ds=DS;

	OLD_SS=_SS;
	OLD_SP=_SP;

	disable();
	_SS=TSR_SS;
	_SP=TSR_SP;
	enable();




	if (dummy_read)
	{	if ((reg_buf[load_count].ax_1&0xff00)==0x0200)
		{
			/*------Get file name and open it-------*/

			*((int *)fake_file)=reg_buf[load_count].names;
			fh=_open(fake_file,O_RDONLY);

			/*------Read sector data from file------*/

			_SI=_DS;
			_CX=reg_buf[load_count].bytes;
			_BX=fh;
			_DX=regs.x.bx;
			_DS=sregs.es;
			_AH=0x3F;
			geninterrupt(0x21);
			_DS=_SI;

			/*------Close file----------------------*/

			_close(fh);
		}
		/*------Set register to proper value----*/

		regs.x.ax=reg_buf[load_count].ax_2;
		regs.x.bx=reg_buf[load_count].bx_2;
		regs.x.cx=reg_buf[load_count].cx_2;
		regs.x.dx=reg_buf[load_count].dx_2;
		regs.x.flags=reg_buf[load_count].flag_2;

		/*------Adjust load count---------------*/

		load_count++;
		if (load_count>=reg_count)	load_count=0;

	}
	else	/*------Get sector data from disk-------*/
	{
		/*------Record register values----------*/

		reg_buf[reg_count].ax_1=regs.x.ax;
		reg_buf[reg_count].bx_1=regs.x.bx;
		reg_buf[reg_count].cx_1=regs.x.cx;
		reg_buf[reg_count].dx_1=regs.x.dx;
		int86x(0x13,&regs,&regs,&sregs);
		reg_buf[reg_count].ax_2=regs.x.ax;
		reg_buf[reg_count].bx_2=regs.x.bx;
		reg_buf[reg_count].cx_2=regs.x.cx;
		reg_buf[reg_count].dx_2=regs.x.dx;
		reg_buf[reg_count].flag_2=regs.x.flags;

		/*------Get file name and transfer size-*/

		if ((reg_buf[reg_count].ax_1&0xff00)==0x0200)
		{	reg_buf[reg_count].bytes=((unsigned int)128
				<<(*((char far *)0x00000525)))*
				(reg_buf[reg_count].ax_1&0xff);
			reg_buf[reg_count].names=*((int *)sector_file);
		}

		/*------Write register values to file---*/

		fh=_creat(reg_file,FA_ARCH);
		reg_count=(reg_count+1)*sizeof(reg_buf[0]);
		_write(fh,&reg_count,2);
		_write(fh,reg_buf,reg_count);
		reg_count=reg_count/sizeof(reg_buf[0])-1;
		_close(fh);

		/*------Write sector data to file-------*/

		if ((reg_buf[reg_count].ax_1&0xff00)==0x0200)
		{	fh=_creat(sector_file,FA_ARCH);

			_SI=_DS;
			_CX=reg_buf[reg_count].bytes;
			_BX=fh;
			_DX=regs.x.bx;
			_DS=sregs.es;
			_AH=0x40;
			geninterrupt(0x21);
			_DS=_SI;

			_close(fh);
			(*((char *)sector_file))++;
		}

		/*------Adjust reg_count----------------*/

		if (reg_count<99) reg_count++;
	}



	disable();
	_SS=OLD_SS;
	_SP=OLD_SP;
	enable();

	AX=regs.x.ax;
	BX=regs.x.bx;
	CX=regs.x.cx;
	DX=regs.x.dx;
	SI=regs.x.si;
	DI=regs.x.di;
	FLAGS=regs.x.flags;
	ES=sregs.es;
	DS=sregs.ds;

	Busy=0;

	return;




i13_done:
	_SP=_SP-6;
	_BP=_BP-6;
	BP=DS;
	DI=ES;
	SI=DX;
	DS=CX;
	ES=BX;
	DX=AX;
	CX=IP;
	BX=CS;
	AX=FLAGS;
	_BP=_BP+6;
	CX=(unsigned int)OldInt13;
	BX=(unsigned long)OldInt13 / 65536;
	AX=FLAGS;
	_BP=_BP-6;
}

void	load_reg(void)
{	int	fh;

	if ((fh=_open("REGISTER.DAT",O_RDONLY))==-1)	return;
	_read(fh,&reg_count,2);
	reg_count/=sizeof(reg_buf[0]);
	_read(fh,reg_buf,sizeof(reg_buf[0])*100);
	_close(fh);
	dummy_read=1;
}

/*----------------- NewInt21 -----------------------------------------------*/

void	interrupt	NewInt21( unsigned BP,unsigned DI,unsigned SI,
				  unsigned DS,unsigned ES,unsigned DX,
				  unsigned CX,unsigned BX,unsigned AX,
				  unsigned IP,unsigned CS,unsigned FLAGS )
{	static	union	REGS	regs;
	static	struct	SREGS	sregs;
	static	int	Save_DX;
	static	char	far	*ptr;
	static	int	i;
	char	ah;


	if (Busy)	goto	i21_done;
	_AX=AX;
	ah=_AH;
	if ((ah!=0x3D)&&(ah!=0x4E))	goto	i21_done;

	Busy=1;

	regs.x.ax=AX;			/* Get register values from	*/
	regs.x.bx=BX;			/* stack and preserve in regs	*/
	regs.x.cx=CX;
	regs.x.dx=DX;
	regs.x.si=SI;
	regs.x.di=DI;
	regs.x.flags=FLAGS;
	sregs.es=ES;
	sregs.ds=DS;

	OLD_SS=_SS;
	OLD_SP=_SP;

	disable();			/* Switch stack			*/
	_SS=TSR_SS;
	_SP=TSR_SP;
	enable();

/*--------------------------------------*/
/*	Record file name (start)	*/
/*--------------------------------------*/

	ptr=MK_FP(sregs.ds,regs.x.dx);	/* Record file name		*/
	while((*ptr)&&(i<0x1000)) name_buf[i++]=*ptr++;
	if (i<0x1000)	i++;

	Save_DX=regs.x.dx;		/* Change file name		*/
	ptr=MK_FP(sregs.ds,regs.x.dx);
	if (((*ptr=='A')||(*ptr=='a'))&&(*(ptr+1)==':')) regs.x.dx+=2;

	int86x(0x21,&regs,&regs,&sregs);/* Excute DOS function call	*/
	regs.x.dx=Save_DX;

/*--------------------------------------*/
/*	Record file name (end)		*/
/*--------------------------------------*/

	disable();			/* Restore stack pointer	*/
	_SS=OLD_SS;
	_SP=OLD_SP;
	enable();

	AX=regs.x.ax;			/* Set new values to stack	*/
	BX=regs.x.bx;
	CX=regs.x.cx;
	DX=regs.x.dx;
	SI=regs.x.si;
	DI=regs.x.di;
	FLAGS=regs.x.flags;
	ES=sregs.es;
	DS=sregs.ds;

	Busy=0;

	return;




i21_done:
	_SP=_SP-6;			/* Adjust stack pointer		*/
	_BP=_BP-6;			/* Adjust base pointer		*/
	BP=DS;				/* Note: This DS value (right	*/
	DI=ES;				/*       hand side) is the old	*/
	SI=DX;				/*       BP value. Don't confuse*/
	DS=CX;
	ES=BX;
	DX=AX;
	CX=IP;
	BX=CS;
	AX=FLAGS;
	_BP=_BP+6;
	CX=(unsigned int)OldInt21;
	BX=(unsigned long)OldInt21 / 65536;
	AX=FLAGS;
	_BP=_BP-6;
}

/*----------------- NewInt28 -----------------------------------------------*/

void	interrupt	NewInt28(void)
{
	(*OldInt28)();			/* Execute old ISR		*/

	disable();			/* Disable interrupt !!		*/
	if (Busy) return;		/* Test Busy semaphore		*/
	Busy=1;				/* Set  Busy semaphore		*/
	enable();			/* Enable  interrupt !!		*/

	if ( (KeyState & KeySelect) != KeySelect )
	{	Busy=0;			/* If hot key is not pressed	*/
		return;			/* then return			*/
	}

	Activate();			/* Do the TSR routine		*/

	Busy=0;				/* Reset Busy semaphore		*/
	return;				/* Return to interrupted program*/
}

/*----------------- NewInt60 -----------------------------------------------*/

void	interrupt	NewInt60(void)
{
	setvect(0x09,OldInt09);		/* Restore old interrupt vector	*/
	setvect(0x13,OldInt13);
	setvect(0x21,OldInt21);
	setvect(0x28,OldInt28);
	setvect(0x60,OldInt60);
}

/*----------------- Initialize ---------------------------------------------*/

main()
{
	load_reg();

	TSR_SS=_SS;			/* Save Turbo C stack segment	*/
	TSR_SP=_BP;			/* Save Turbo C stack pointer!!	*/
	TSR_PSP=_psp;			/* Save Turbo C PSP segment	*/

	_AH=0x2F;			/* Use DOS function call to get	*/
	geninterrupt(0x21);		/* the DTA address		*/
	TSR_DTA_SEG=_ES;		/* Save DTA address in		*/
	TSR_DTA_OFF=_BX;		/* TSR_DTA_SEG & TSR_DTA_OFF	*/

	_AH=0x34;			/* Use DOS function call to get	*/
	geninterrupt(0x21);		/* the 'indos' flag and save it	*/
	InDos=MK_FP(_ES,_BX);		/* in InDos			*/

	OldInt09=getvect(0x09);		/* Save old interrupt vector	*/
	OldInt13=getvect(0x13);
	OldInt21=getvect(0x21);
	OldInt28=getvect(0x28);
	OldInt60=getvect(0x60);
	setvect(0x09,NewInt09);		/* Set  new interrupt vector	*/
	setvect(0x13,NewInt13);
	setvect(0x21,NewInt21);
	setvect(0x28,NewInt28);
	setvect(0x60,NewInt60);

	keep(0,FP_SEG(_heapbase)-_psp);	/* Terminate and stay resident	*/

	Printf("Something error in TSR.\n\r");
	exit(1);			/* Return error code		*/
}
