;[]-------------------------------------------------------------------------[]
;|	Program name: 5_3_6.ASM                                              |
;|	Image   file: 5_3_6.COM                                              |
;|	Note        : Hole Lock protection program.                          |
;|                    ( The TSR routine will change INT 10H to boot routine )|
;[]-------------------------------------------------------------------------[]


cseg	segment
	assume	cs:cseg,ds:cseg
	org	100H
start:
	jmp	initialize

;------- Data area ---------------------

no_use		db	?
mark		db	'HoleLock'
old_int01	dd	?
old_int03	dd	?
old_int10	dd	?
old_int13	dd	?
filename	db	'TEST.EXE',5 dup (0)

old_int21	dd	?
old_int60	dd	?
old_int61	dd	?
err_msg		db	'No effect!',0DH,0AH,'$'
ter_msg		db	'TSR ok!',0DH,0AH,'$'
PSP		dw	0

;------- Include area ------------------

DEBUG	EQU	0
include	register.inc
include	interrup.inc
include	debug.inc

;------- INT 21H -----------------------

new_int21	proc	far

	cmp	ah,4BH
	jne	i21_0

	sti
	call	set_int10
	cli
i21_0:
	jmp	cs:old_int21

new_int21	endp


	LOCALS
set_int10	proc	near

	pushall

	cld
	mov	ax,ds
	mov	es,ax
	mov	di,dx
	mov	al,0
	mov	cx,0FFFFH
	repne	scasb
	sub	di,2
	mov	si,di

	mov	ax,cs
	mov	es,ax
	mov	di,offset filename
	mov	al,0
	mov	cx,13
	repne	scasb
	sub	di,2

	std
	mov	cx,13
	repe	cmpsb
	add	di,2
	cmp	di,offset filename
	ja	@@1

	mov	ax,cs
	mov	ds,ax

	get_int	01H,old_int01
	set_int	01H,<offset new_int60>
	get_int	03H,old_int03
	set_int	03H,<offset new_int60>

	mov	ax,0FFFFH
	mov	ds,ax
	mov	dx,0
	mov	ax,2510H
	int	21H

@@1:
	popall
	ret

set_int10	endp

;------- INT 60H -----------------------

new_int60	proc	far

	assume	cs:cseg,ds:nothing	; Override segment

	sti
	pushr	<ax,dx,ds>

	set_int	01H,<word ptr old_int01>,<word ptr old_int01[2]>
	set_int	03H,<word ptr old_int03>,<word ptr old_int03[2]>
	set_int	21H,<word ptr old_int21>,<word ptr old_int21[2]>
	set_int	60H,<word ptr old_int60>,<word ptr old_int60[2]>
	set_int	61H,<word ptr old_int61>,<word ptr old_int61[2]>

	popr	<ds,dx,ax>
	iret

new_int60	endp

;------- Check MCB in memory -----------

check_mcb	proc	near

	assume	cs:cseg,ds:cseg

	mov	di,0
	mov	cx,0
	mov	bx,3FFH

;=======================================
; Find the first MCB
;=======================================

@@1:	inc	bx
	mov	es,bx
	cmp	byte ptr es:[di],'M'
	jz	@@2
	cmp	byte ptr es:[di],'Z'
	jnz	@@1

@@2:	mov	ax,es
	mov	dx,es
@@3:	inc	dx
	cmp	dx,psp
	jz	@@4
	add	dx,es:[di+3]
	jc	@@1
	cmp	dx,0A000H
	ja	@@1
	mov	es,dx
	jmp	@@3

;=======================================
; Count the quantity of the processes
;=======================================

@@4:	mov	es,ax
	cmp	word ptr es:[di+1],0
	jz	@@5
	cmp	word ptr es:[di+1],8
	jz	@@5
	mov	bx,ax
	inc	bx
	cmp	es:[di+1],bx
	jnz	@@5
	inc	cx

@@5:	add	ax,es:[di+3]
	inc	ax
	cmp	ax,0A000H
	jnz	@@4

;=======================================
; Check the count
;=======================================

	mov	dx,offset ter_msg
	cmp	cx,2
	je	@@6
	pop	dx			; discard return address
	mov	dx,offset err_msg
@@6:	mov	ah,09H
	int	21H
	ret

check_mcb	endp

;------- Main program ------------------

initialize:

	assume	cs:cseg,ds:cseg

	mov	cs:PSP,ds
	call	check_mcb

	get_int	10H,old_int10
	get_int	13H,old_int13
	get_int	21H,old_int21
	set_int	21H,<offset new_int21>
	get_int	60H,old_int60
	set_int	60H,<offset new_int60>
	get_int	61H,old_int61
	set_int	61H,<offset new_int61>

	mov	dx,offset check_mcb	; Terminate and stay resident
	int	27H

cseg	ends
	end	start
