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
-
- 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 near
- assume ds:nothing
- pushf ;save flags
- cmp ah,31H
- jne ex21
- call checkvec ;call routine to check vector table
- ex21: popf
- jmp dos_int ;transfer control to old int21 vector
- newint21 endp
-
- ;***********************************************************************
- ;interrupt handler for int27
- newint27 proc near
- assume ds:nothing
- call checkvec
- ex27: jmp tsr_int ;transfer control 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 oldss,ss
- mov oldsp,sp
-
- ;switch to our stack
- cli
- mov ss,newss
- mov sp,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
- 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,oldss
- mov sp,oldsp
- 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
-