home *** CD-ROM | disk | FTP | other *** search
- ;WATCH.ASM Version 3.1 30-May-1989 03:10
- ;resident routine watches programs going resident
- ;and keeps a list of changes to interrupt vectors
- ;in an internal data structure
- ; written for MASM (version 4 or later) or TASM
- ; by Kim Kokkonen, TurboPower Software
- ; telephone: 408-438-8606, Compuserve 72457,2131
- ;
- ; VERSION 2.2 3/4/87
- ; First release, version to be consistent with MAPMEM.PAS
- ; VERSION 2.3 5/1/87
- ; Sets up a separate stack for the interrupt handlers
- ; to solve problem first noticed with EMMCACHE and WATCH
- ; Changes approach - store all vector information in RAM buffers
- ; No disk access at all by WATCH
- ; Better check for multiple installation
- ; Changed to use MASM
- ; VERSION 2.4 5/17/87
- ; for consistency with RELEASE
- ; VERSION 2.5 5/28/87
- ; save flags in int21 handler
- ; VERSION 3.1 5/30/89 for use with UnMark and ReMark 3.1
- ; by Tom Gilbert's Heart & Mind includes TurboPower 2.8
- ; NO [F]Mark INT vectors
- ; Change method to avoid reinstallation
- ; Nul VCHG area => vpos to simplify debugging
- ;v3.2 Toad Hall Tweak
-
- CSEG segment public para
- ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING, ss:NOTHING
-
- org 080H
- cmdline label byte ;pointer to command line
-
- org 100H
- ComEntry: jmp Init
-
- ;resident data section follows
-
- ;put the following in the MAP file
- public bmesg,ORIGV,PREVV,vpos,VCHG
- ; 0E20h, 620h,0A20h,104h,220h
-
- ;resident data structures not part of COM file
- VCHG equ 220H ;location of data area (>= offset bmesg)
- VRECSIZE equ 8 ;bytes per vector change record
- VSIZE equ 80H*VRECSIZE ;size of vector change area in bytes
- ;space for 128 changes of vector here
- ;vector table buffers
- ORIGV equ VCHG+VSIZE ;location of original vector table
- VECLEN equ 400H ;size of vector table in bytes
- PREVV equ ORIGV+VECLEN ;location of current vector table
- NEWSTACKPOS equ PREVV+VECLEN ;location of newstack
- SSIZE equ 0080H ;number of bytes in temporary stack
-
- NEWLOC equ NEWSTACKPOS+SSIZE ;where installation code relocated
-
- even
- vpos dw 0 ;next position to write in data area
-
- ;temporary stack used by interrupt handler
- newss dw 0 ;segment of temporary stack
- newsp dw 0 ;initial stack pointer
-
- ;information saved about the calling program
- oldss dw ? ;stack segment
- oldsp dw ? ;stack pointer
- curpsp dw ? ;program segment
-
- ;id code for a PSP data block
- PSPID equ 0FFFFH ;id used to indicate a PSP block
-
- ;previous interrupt handlers
- dos_int label dword
- old21 dw 2 dup (?) ;old int21 vector
- tsr_int label dword
- old27 dw 2 dup (?) ;old int27 vector
-
- ;***********************************************************************
- ;interrupt handler for int21
- NewInt21 proc FAR ;v1.1
- ASSUME DS:NOTHING
- pushf ;save flags
- cmp ah,31H
- jne ex21
- call CheckVec ;call routine to check vector table
- ex21: popf
- jmp CS:[dos_int] ;transfer control v1.1
- ; to old int21 vector
- NewInt21 endp
-
- ;***********************************************************************
- ;interrupt handler for int27
- NewInt27 proc FAR ;v1.1
- ASSUME DS:NOTHING
- call CheckVec
- ex27: jmp CS:[tsr_int] ;transfer control v1.1
- ; to old int27 vector
- NewInt27 endp
-
- ;***********************************************************************
-
- ;procedure CheckVec
- ; compares vectors to previous installation
- ; writes vector change information
- ; stores a new vector buffer
-
- CheckVec proc near
- ASSUME DS:NOTHING
-
- ;save current stack
- mov CS:oldss,SS ;v1.1
- mov CS:oldsp,sp
-
- ;switch to our stack
- cli
- mov ss,CS:newss ;v1.1
- mov sp,CS:newsp
- sti
- ;store registers
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push DS
- push ES
- ;get DS set up as CS
- mov ax,CS
- mov DS,ax
- ASSUME DS:CSEG
-
- mov ah,51H ;get current PSP
- pushf ;by simulated INT
- call [dos_int] ;bx returns PSP v1.1
- call VecHdr ;store PSP segment of program going resident
- call CmpVec ;scan vector table for changes from buffer
- mov di,PREVV ;save the new version of the vector table
- call SaveVec
- ;restore registers
- pop ES
- pop DS
- ASSUME DS:NOTHING
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ;restore stack
- cli
- mov ss,CS:oldss ;v1.1
- mov sp,CS:oldsp ;v1.1
- sti
- ret
- CheckVec endp
-
- ;***********************************************************************
- ;procedure VecHdr
- ; writes a header to the vector data area for this new TSR
- ; on entry:
- ; bx has PSP of the new TSR
- ;
- VecHdr proc near
- ASSUME DS:CSEG
- cmp vpos,VSIZE-VRECSIZE ;assure room for next record
- ja vecex ;ignore if no room
- push di
- mov di,vpos ;index into VCHG array
- mov word ptr [di+VCHG],PSPID ;store id word
- mov word ptr [di+VCHG+2],bx ;store PSP value two words in
- ;record left unitialized
- add vpos,VRECSIZE ;move to next data element
- pop di
-
- vecex: ret
- VecHdr endp
-
- ;***********************************************************************
- ;procedure WrChg
- ; writes information about changed vectors to the data area
- ; on entry
- ; ax has changed vector number
- ; ds points to segment 0
- ; on exit:
- ; flags changed
- ;
- WrChg proc near
- ASSUME DS:NOTHING, ES:NOTHING
-
- cmp vpos,VSIZE-VRECSIZE ;assure room for next record
- ja wrcex
-
- push ax
- push si
- push di
-
- mov di,vpos ;index into VCHG array
- mov CS:[di+VCHG],ax ;store interrupt vector number
-
- mov si,ax
- shl si,1
- shl si,1 ;get address of vector
- mov ax,[si] ;get offset of vector
- mov CS:[di+VCHG+2],ax ;store vector offset
- mov ax,[si+2] ;get segment
- mov CS:[di+VCHG+4],ax ;store segment
- ;one word in record left unused
- add vpos,VRECSIZE ;move to next data element
-
- pop di
- pop si
- pop ax
-
- wrcex: ret
- WrChg endp
-
- ;***********************************************************************
- ;procedure CmpVec
- ; compares vectors in buffer to those in use
- ; writes numbers of those different to data area
- ; on entry:
- ; bx has program's PSP
- ; on exit:
- ; ax,si,di destroyed
- ; flags changed
- ;
- CmpVec proc near
- push DS
- push ES
- ASSUME ES:NOTHING
- mov ES,bx ;If NO " T"
- cmp word ptr ES:[65h],'T '
- jne dovecs ;then NOT [F]Mark
- cmp word ptr ES:[67h],'RS'
- je cvexit ;else " TSR" is [F]Mark
-
- dovecs: ASSUME DS:NOTHING
- xor si,si ;source offset 0
- mov DS,si ;source address segment 0
- mov ax,CS
- mov ES,ax
- xor ax,ax ;vector counter
- mov di,PREVV ;destination offset
- cld ;upward direction
-
- nexvec: cmpsw ;compare offsets
- je cmpseg ;compare segments if offsets equal
- call WrChg ;write changed vector
- cmpsw ;compare next word, ignore result
- jmp short vecinc
-
- cmpseg: cmpsw ;compare segments
- je vecinc
- call WrChg ;write changed vector
-
- vecinc: inc ax ;next vector number
- cmp ax,00FFH
- jbe nexvec ;continue until 256 vectors checked
-
- cvexit: pop ES
- pop DS
- ret
- CmpVec endp
-
- ;***********************************************************************
- ;procedure SaveVec
- ; saves image of interrupt vectors
- ; on entry:
- ; di has destination offset
- ; on exit:
- ; ax,cx,si,di destroyed
- ; flags changed
- ;
- SaveVec proc near
- ASSUME DS:NOTHING, ES:NOTHING
- push DS
- push ES
- xor si,si ;offset 0
- mov DS,si ;source address segment 0
- mov ax,CS
- mov ES,ax ;destination always in this code segment
- mov cx,200H ;512 integers to store
- cld ;copy up
- rep movsw ;copy vectors to our table
- pop ES
- pop DS
- ret
- SaveVec endp ;of proc SaveVec
-
- ;***********************************************************************
- ;resident portion above
- ;temporary portion below
- ;***********************************************************************
-
- ;temporary strings
- even
- bmesg db 13,10,'Cannot install WATCH more than once....',13,10,36
- mesg db 13,10,'WATCH 3.1 successfully installed',13,10,36
- pname db 'TSR WATCHER'
- PLEN equ $-pname ;length of string
-
- ;***********************************************************************
- ;install new handlers for DOS go-resident services
- Init proc near
- ASSUME DS:CSEG
- ;search for a previous installation after DOS Master Environment
- mov ah,52h ;Use Undocumented Interrupt
- int 21h ; to locate DOS CONFIG.SYS
- mov ax,ES:[bx-2] ;Use its
- mov ES,ax ;MCB and
- inc ax ;Block to
- add ax,ES:[3] ; add in
- mov ES,ax ;lengths to
- inc ax ;location of
- add ax,ES:[3] ;environment
- mov ES,ax ;MCB to begin
- mov bx,CS ;comparisons
- watchs: inc ax ;If next segment
- mov ES,ax ;to be compared
- cmp ax,bx ;is NOT before here
- jnc success ;then NO other Watch
-
- mov si,offset pname ;else compare pname
- mov di,81h ;with command line
- mov cx,PLEN ;"TSR WATCHER"
- rep cmpsb ;If NO match
- jne watchs ;then loop
-
- ;error exit
- mov dx,offset bmesg ;else error message
- mov ah,09H ;NOT more than once
- int 21H ;DOS print string
- mov ax,4C01H ;exit with error
- int 21H
-
- success: ;print a success message
- mov dx,offset mesg ;start of message to write
- mov ah,09H
- int 21H ;DOS print string
-
- ;relocate ourselves out of the way of the vector tables
- mov ax,CS
- mov ES,ax
- mov di,NEWLOC+10H
- push di ;will act as a return address
- mov si,offset newstk
- mov cx,lastcode-newstk
- rep movsb ;move code
- ret ;"return" to the relocated code
-
- ;initialize location of WATCH stack
- newstk: mov newsp,NEWSTACKPOS+SSIZE
- mov newss,CS ;stack seg is code seg
- push ES
-
- ;get int 21H vector
- mov ax,3521H ;GetVector DOS function call
- int 21H
- mov old21,bx ;store first word of old21
- mov old21[2],ES ;store second word
-
- ;get int 27H vector
- mov ax,3527H ;GetVector DOS function call
- int 21H
- mov old27,bx ;store first word of old27 (offset)
- mov old27[2],ES ;store second word (segment)
- pop ES
- push ES
- mov ES,ES:[2Ch]
- mov ah,49h ; Release Environment and
- int 21h ; put an id label at
- mov ax,CS ; offset 80H so other programs
- mov ES,ax ; can recognize WATCH
- mov cx,PLEN ;length of name string
- mov si,offset pname ;offset of name string
- mov di,offset cmdline ;offset of DOS command line
- cld ;transfer in forward direction
- mov al,cl
- stosb ;store length byte first
- rep movsb ;transfer characters
- xor ax,ax ;nul-out
- mov di,VCHG ;vector change
- mov cx,200h ;table area
- rep stosw
-
- ;store image of original vector table in ORIGV following VCHG table
- mov ax,offset SaveVec
- call ax ;absolute call works as code is moved
-
- ;store it again in the current vector table PREVV which follows ORIGV
- mov ax,offset SaveVec
- call ax ;absolute call works as code is moved
-
- ;install the new vectors
- mov ax,2521H
- mov dx,offset NewInt21
- int 21H
- mov ax,2527H
- mov dx,offset NewInt27
- int 21H
-
- ;terminate and stay resident
- mov dx,(NEWLOC+15) shr 4
- mov ax,3100H ;return success code
- int 21H
-
- lastcode:
- Init endp
-
- CSEG ends
- end ComEntry