home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
PCACHSRC.ZIP
/
DOSTSR16.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-07-29
|
9KB
|
341 lines
;DOSTSR16.ASM
;This is a skeleton DOS TSR, that hooks INT-16h.
;All it does is detect a hot key (<alt-z>) and then activates.
;Upon activation it accepts further keyboard input and displays
;characters on the screen. Another <alt-z> will deactivate the TSR.
;Shows how to safely synchronise a TSR with DOS.
;Note that the only reason I put ".286" directive in is because I
;have used the PUSHA and POPA instructions.
;...................................................
.286
int16 SEGMENT BYTE PUBLIC 'CODE'
ASSUME cs:int16,ds:int16
ORG 100h
install: jmp start
oldoffivt2F DW 0 ;save old int-2F vector here.
oldsegivt2F DW 0 ; /
winloaded DB 0 ;set when Windows is loaded, & viceversa.
winmode DB 0 ;bit-0=1 if Standard, =0 if Enhanced.
oldoffivt16 DW 0 ;save old keyboard vector here.
oldsegivt16 DW 0 ; /
oldoffivt28 DW 0 ;old int-28h
oldsegivt28 DW 0 ; /
tsrpspseg DW 0 ;seg addr of psp, this tsr.
dosbusyoff DW 0 ;far addr of dos busy flag
dosbusyseg DW 0 ; /
isrbusy DB 0 ;set if this isr already in use.
isrwanted DB 0 ;set=isr tried to start but indos stopped it
oldpspseg DW 0 ;seg addr of psp prior to interrupt.
oldsp DW 0 ;stack prior to interrupt.
oldss Dw 0 ; /
oldctrlc DB 0 ;ctrl-c on/off
oldoffivt1B DW 0 ;old vectors
oldsegivt1B DW 0 ; /
oldoffivt23 DW 0 ; /
oldsegivt23 DW 0 ; /
oldoffivt24 DW 0 ; /
oldsegivt24 DW 0 ; /
localstack DB 511 DUP(0)
localendstack DW 0 ;top of stack
;....................................................................
runtime16:
;this is now the "signaller". it is entered at every keypress...
;but only when in a DOS VM or in standard real-mode...
;
;this is particular to int-16h (test if reading a char)....
cmp ah,0
je firsthurdle
cmp ah,10h
je firsthurdle
chain: jmp DWORD PTR cs:oldoffivt16 ;chain to old int-16
;
firsthurdle:
;give some thought to reentrancy... avoid potential problems with a flag...
cmp cs:isrbusy,0
jne chain ;this isr already in use!
secondhurdle:
;now test for the hot-key...
pushf
call DWORD PTR cs:oldoffivt16 ;call old int-16.
cmp ax,2C00h ;<alt-z>
je thirdhurdle
iret
thirdhurdle:
mov cs:isrwanted,1 ;to tell int-28 that we want to popup.
;before doing anything, we need to synchronise with dos...
;however the test for the "indos" flag does not work when COMMAND.COM
;is running... int-16 called with indos set....
push ax
push bx
push es
les bx,DWORD PTR cs:dosbusyoff
mov al,es:[bx] ;get dos-busy flag
or al,al
pop es
pop bx
pop ax
jnz chain ;get out, as dos is busy.
;
vvv: mov cs:isrbusy,1 ;lay claim to this isr.
mov cs:isrwanted,0 ;clear this, since we're in.
zzz: sti ;now allow interrupts.
;(note that if this was a hardware interrupt, would need EOI here also).
nop
;now get the regs setup for the isr... let's use a local stack...
cli
mov cs:oldss,ss
mov cs:oldsp,sp
mov ss,cs:tsrpspseg ;can do this since es=cs=ds at install.
mov sp,OFFSET cs:localendstack
sti
push es ;save working registers
push ds ; /
pusha ; /
push cs ;set ds == cs
pop ds ; /
;get the seg addr of the old psp (of program prior to interrupt)...
mov ah,62h
int 21h ;-->bx
mov oldpspseg,bx
;set dos to use psp of this tsr...
mov bx,tsrpspseg ;(saved during install)
mov ah,50h
int 21h
;one other thing that you should do is save the "break" setting
;and turn it off, so key entries such as ctrl-c can't upset our isr.
;firstly, get the vectors...
mov ax,351Bh
int 21h
mov oldoffivt1B,bx
mov oldsegivt1B,es
mov ax,3523h
int 21h
mov oldoffivt23,bx
mov oldsegivt23,es
mov ax,3524h
int 21h
mov oldoffivt24,bx
mov oldsegivt24,es
mov ax,3300h ;is ctrl-c checking turned on?
int 21h ;dl=1 enabled
mov oldctrlc,dl
;now hook them...
mov ax,251Bh
mov dx,OFFSET runtime1B
int 21h
mov ax,2523h
mov dx,OFFSET runtime23
int 21h
mov ax,2524h
mov dx,OFFSET runtime24
int 21h
mov ax,3301h ;ctrl-c testing
xor dl,dl ;turned off.
int 21h
;should also save extended error information (funcs 5D, 59)
; and the DTA (disk transfer area).
;Note that all of the above is reversed upon isr exit.
;
;a confirmation that we got this far!...
call longbeep
;..............................................................
;this is it... this is where we do whatever the tsr is supposed to do...
;let's display a char on screen and wait for another key...
ppp: mov ah,0 ;get char from key buffer.
int 16h ;(goes to old vector, as isrbusy is set).
cmp ax,2C00h
je backtohost
mov ah,9 ;display a char
mov bl,70h ;attribute/colour
mov bh,0 ;video page
mov cx,1 ;just one char
int 10h
jmp ppp
backtohost:
;.......
exit4:
mov ah,50h ;restore host psp
mov bx,oldpspseg
int 21h
;restore old break vectors & ctrl-c testing...
push ds
mov ax,251Bh
lds dx,DWORD PTR cs:oldoffivt1B
int 21h
mov ax,2523h
lds dx,DWORD PTR cs:oldoffivt23
int 21h
mov ax,2524h
lds dx,DWORD PTR cs:oldoffivt24
int 21h
pop ds
mov ax,3301h ;restore ctrl-c checking state.
mov dl,oldctrlc
int 21h
;......
popa ;restore registers.
pop ds ; /
pop es ; /
cli
mov ss,cs:oldss ;restore host stack
mov sp,cs:oldsp ; /
mov cs:isrbusy,0 ;isr no longer in use
mov cs:isrwanted,0 ;isr doesnt want to popup.
exit: iret
;....................................................................
runtime2F:
;also entered if try to reload this tsr... install sends AX=CC00
;if this signature, return with AX=CC01 to say already loaded...
cmp ah,0CCh ;note can use this mechanism to send
jne nextsig ; messages to the tsr from a dosapp:
cmp al,0 ;is it an install test?(value in AL=0)
je installtest
iret
installtest: mov al,1 ;flag can't load.
jmp SHORT chain2F
nextsig:
;entered when Windows loads, with AX=1605h, and when Windows unloads,
;with AX=1606h....
;detect when Windows loads, and set a flag ...
sti ;documentation says this req'd.
cmp ax,1605h ;test if Win is loading
jne notload
cmp cx,0 ;this must always be 0, else error.
jne loaderror
mov cs:winloaded,1
mov cs:winmode,dl
jmp SHORT chain2F
notload: cmp ax,1606h ;test if Win is unloading.
jne notunload
mov cs:winloaded,0
jmp SHORT chain2F
notunload:
loaderror:
chain2F:
jmp DWORD PTR cs:oldoffivt2F
;..................................................................
runtime28:
;this isr is required because of the peculiar way COMMAND.COM works!
pushf
call DWORD PTR CS:oldoffivt28 ;call old int-28
push ds
push es
pusha
push cs
pop ds
;is dos busy...
les bx,DWORD PTR dosbusyoff
mov al,es:[bx] ;get indos flag
or al,al
jz mmm ;if set, then we can popup.
;find out if isr wants to popup...
cmp isrwanted,0
jz mmm
pushf
call FAR PTR vvv ;calls runtime16 as an interrupt.
mmm: popa
pop es
pop ds
iret
;............................................................
runtime24: xor al,al
runtime1B:
runtime23: iret
;................................................................
longbeep:
pusha
mov al,0B6h ;turn on loudspeaker
out 43h,al
mov bx,07C5h
mov al,bl
out 42h,al
mov al,bh
out 42h,al
in al,61h
or al,3
out 61h,al
mov cx,0ffffh
xxx: nop
pusha ;just to kill time
popa
loop xxx
in al,61h ;turn off loudspeaker
and al,0FCh
out 61h,al
popa
ret
;................................................................
endprog: ;everything past here dumped when made resident.
start:
;save ptr to psp...
mov tsrpspseg,es ;if com, they all pt to it!
;is this tsr already installed?... i have given it a signature of CCh...
mov ax,0CC00h ;AL=0 is install-test code for my 2F handler.
int 2Fh ;multiplex interrupt (that we will hook)
or al,al ;AL=non-0 means abort.
jnz abortload
;get the addr of the dos-busy flag...
mov ah,34h
int 21h ;-->es:bx
mov dosbusyoff,bx
mov dosbusyseg,es
;
;hook int-2Fh vector in ivt. Windows calls this with AX=1605h when it loads,
;with regs telling useful info, such as if loading in Standard or
;Enhanced mode....
mov ax,352Fh ;get int-2F vector in ivt.
int 21h ; /
mov oldoffivt2F,bx ;save it
mov oldsegivt2F,es ; /
mov ax,252Fh ;hook int-2F
lea dx,runtime2F ;set ivt vector.
int 21h ; /
;
;hook keypresses ...
mov ax,3516h ;get int-16h vector in ivt.
int 21h ; /
mov oldoffivt16,bx ;save it
mov oldsegivt16,es ; /
mov ax,2516h ;hook int-16
lea dx,runtime16 ;set ivt vector.
int 21h ; /
;
;hook int-28h. COMMAND.COM calls this when idling & reading the keyboard...
;unfortunately when entering int-16 from COMMAND.COM, indos always set,
;but at int 28h call it is safe...
mov ax,3528h
int 21h
mov oldoffivt28,bx
mov oldsegivt28,es
mov ax,2528h
lea dx,runtime28
int 21h
;
;free the environment block ... ###(this may upset int-2F/1687h)
; mov es,ds:[2Ch] ;pointer to seg. addr. of env. block
; mov ah,49h ;deallocate memory
; int 21h ; /
;
lea dx,endprog+17 ;point past all code in this module.
shr dx,4 ;compute # paragraphs to keep.
mov ax,3100h ;terminate and stay resident.
int 21h ; /
abortload:
call longbeep
mov ax,4C00h ;don't make resident.
int 21h
;...............................................................
int16 ENDS
END install