/*--------------------------------------------------------------------------*/
/*	Program name: 5_2_8.C                                               */
/*	Compile mode: Small                                                 */
/*	Image   file: 5_2_8.EXE                                             */
/*	Note        : Hole Lock protection program.                         */
/*		      You can rename this program to HOLELOCK.EXE.          */
/*		      All rights reserved !!                                */
/*--------------------------------------------------------------------------*/


#include	<stdio.h>
#include	<conio.h>
#include	<dos.h>
#include	<fcntl.h>
#include	<io.h>

signed		int	fh,fh1,fh2;
signed		char	prot_code_file[]="HOLELOCK.DAT";
unsigned	int	Start_Track,End_Track;
unsigned	char	buffer[512],buffer1[512];
unsigned	int	hole_CX,hole_DX;


/*--------------------------------- UTILITY --------------------------------*/

disk_reset()
{	_AX=0;
	geninterrupt(0x13);
}

/*--------------------------------- CHECK ----------------------------------*/

sec_io(int c,int h,int r,int mode,int *ax,char far *buf)
{	int	es;

	es=_ES;
	_ES=FP_SEG(buf);
	_BX=FP_OFF(buf);
	_AX=mode;
	_CH=c;
	_CL=r;
	_DH=h;
	_DL=0;
	geninterrupt(0x13);
	*ax=_AX;
	_ES=es;
	return(_FLAGS&1);
}

verify_hole(int c,int h,int r)
{	int	i,ax;

	if (sec_io(c,h,r,0x0301,&ax,(char far *)buffer)==1)	return(1);
	if (sec_io(c,h,r,0x0201,&ax,(char far *)buffer1)==0)	return(1);
	for(i=0;i<512;i++)	if (buffer[i]!=buffer1[i])	break;
	if (i==512)	return(1);
	if (sec_io(c,h,r,0x0301,&ax,(char far *)buffer1)==1)	return(1);
	if (sec_io(c,h,r,0x0201,&ax,(char far *)buffer)==0)	return(1);
	for(i=0;i<512;i++)	if (buffer[i]!=buffer1[i])	break;
	if (i==512)	return(1);
	hole_CX=c*256+r;
	hole_DX=h*256;
	return(0);
}

check()
{	int	i,j,k,es,ax;

	printf("Checking...\n\r");
	disk_reset();
	for(i=Start_Track;i<=End_Track;i++)
	    for(j=1;j<=9;j++)
		for(k=0;k<=1;k++)
		{	printf("\rTrack:%02d  Head:%d  Sector:%d  ",i,k,j);
			if (sec_io(i,k,j,0x0201,&ax,(char far *)buffer))
			{	printf("AX=%04X\n",ax);
				if (ax==0x1001) verify_hole(i,k,j);
			}
			if (kbhit())
			{	if (getch()==27)
				{	printf("Program break!\n\r");
					return(1);
				}
			}
		}
	if (hole_CX==0)
	{   printf("\rNo hole can be selected for HOLELOCK protection!\n\r");
	    return(1);
	}
	else
	{   printf("\rHole: CX=%04X  DX=%04X        \n\r",hole_CX,hole_DX);
	    return(0);
	}
}

/*---------------------------------- MERGE ---------------------------------*/

merge()
{	unsigned	head[256],*prot_code;
	long		len,prot_code_len;

	printf("Merging...");

	/*-------------------------------------*/
	/* Read protection code to prot_code[] */
	/*-------------------------------------*/

	prot_code_len=lseek(fh,0,SEEK_END);
	lseek(fh,0,SEEK_SET);
	if ((prot_code=(unsigned int *)malloc(prot_code_len))==NULL)
	{	printf("memory allocation error!\n\r");
		return(1);
	}
	_read(fh,prot_code,prot_code_len);
	_close(fh);

	/*-------------------------------------*/
	/* Read the head component of protected*/
	/*   file to head[].                   */
	/*-------------------------------------*/

	_read(fh1,head,512);

	/*-------------------------------------*/
	/* Calculate the protected file length */
	/*   and make the head component of the*/
	/*   output file.                      */
	/*-------------------------------------*/

	if (head[1]==0)	len=head[2]*(long)512+head[5]*(long)16;
	else		len=(head[2]-1)*(long)512+head[1]+head[5]*(long)16;
	if (len%16!=0)	len=len+16-len%16;
	head[2]=(len+prot_code_len)/512;
	head[1]=(len+prot_code_len)%512;
	if (head[1]!=0)	head[2]++;
	head[5]=0;
	prot_code[2]=head[10];
	prot_code[3]=head[11];
	prot_code[4]=hole_CX;
	prot_code[5]=hole_DX;
	head[10]=0x100;
	head[11]=len/16-head[4]-0x10;

	/*-------------------------------------*/
	/* Copy and Merge                      */
	/*-------------------------------------*/

	_write(fh2,head,512);
	while((len-=512)>512)
	{	_read(fh1,head,512);
		_write(fh2,head,512);
	}
	_read(fh1,head,len);
	_write(fh2,head,len);
	_write(fh2,prot_code,prot_code_len);

	_close(fh1);
	_close(fh2);
	free(prot_code);
	printf("done!\n\r");
	return(0);
}

/*---------------------------------- MAIN ----------------------------------*/

parameter_check()
{	extern	int	_argc;
	extern	char	**_argv;

	if (_argc>5)
	{	printf("Too many parameters.\n\r");
		return(1);
	}
	if (_argc==1)
	{	printf("Usage: HOLELOCK [path]source.exe [path]target.exe "
		       "[Strat_Track [End_Track]]\n\r");
		return(1);
	}
	if (_argc<3)
	{	printf("Too few parameters.\n\r");
		return(1);
	}
	printf("Press any key to continue...\n\r");
	getch();
	if ((fh=_open(prot_code_file,O_RDONLY))==-1)
	{	printf("Can not open %s.\n\r",prot_code_file);
		return(1);
	}
	if ((fh1=_open(_argv[1],O_RDONLY))==-1)
	{	printf("Can not open %s.\n\r",_argv[1]);
		return(1);
	}
	if ((fh2=_creat(_argv[2],FA_ARCH))==-1)
	{	printf("Can not creat %s.\n\r",_argv[2]);
		return(1);
	}
	if (_argc>=4)	sscanf(_argv[3],"%d",&Start_Track);
	else		Start_Track=0;
	if (_argc==5)	sscanf(_argv[4],"%d",&End_Track);
	else		End_Track=39;
	return(0);
}

holelock()
{	char	ch;

	if (parameter_check())	return(1);
	if (check())		return(1);
	if (merge())		return(1);
	printf("\n\n\rAll done!\n\r");
}

main()
{	holelock();
}
