; ; Assembly version of the well known utility ESCAPE. ; Most programs can be terminated with this utility. ; 30.12.1994, Have a nice year :-) ; ; Extensively modified by D.Lindauer, August 2000 ; ; EXECUTE AS A EXE FILE! ; .model small .stack .code assume ds:nothing,es:nothing MaxInt EQU 100h ; Save interrupts 0-100h BufSize EQU 4*MaxInt Sign DB 'DA' ; so we won't get confused with old versions jexit: dw exit,0 ; entry point to delete the TSR jrefresh: dw refresh,0 ; entry point to refresh the interrupt table xmsproc dd 0 ; pointer to the XMS hook procedure xmsmdata dd 1024 ; the next few bytes describe an xms transfer from xmshandle dw 0 ; xms back down to 0:0. If handle is zero table dd 0 ; is assumed in conventional memory dw 0 dd 0 ; ; Entry point to refresh the interrupt table ; refresh proc far test [xmshandle],0ffffh ; In XMS jnz xmsmove ; yes do it push ds ; Otherwise move from conv mem push es CLD push cs pop ds lea si,dataarea XOR DI,DI ; DI:=0 MOV ES,DI ; ES:=0 MOV CX,BufSize REP MOVSB ; Move pop es pop ds ret xmsmove: push ds ; XMS move set up params push si push cs pop ds lea si,xmsmdata ; now point at data and do the move mov ah,0bh call xmsproc pop si pop di ret refresh endp ; ; Entry point for int 8 ; If a flag is set when the timer ticks, abort the current process ; int8 proc far PUSHF jmpr DB 9Ah ; CALL FAR xxxx:xxxx jip8 DW 0000 jcs8 DW 0000 sti push ax in al,64h test al,1 jnz quit in al,60h cmp al,58h jnz quit cli ris: in al,60h or al,al jns ris PUSH CS POP DS call refresh ; refresh interrupt table STI VidMod: MOV AX,0000h ; Restore original video mode INT 10h save1: mov dx,0 ; restore original mouse state or dx,dx jz nomouse mousemod: mov cx,0000h mov es,dx save2: mov dx, 0 mov ax,14h int 33h nomouse: MOV AX,4C00h ; Terminate process INT 21h quit: POP AX IRET int8 endp ; ; Entry point for winding down TSR mode exit proc far push ds push es lds dx,dword ptr jip8 ; reset vectors mov ax,2508h int 21h mov ax,cs ; delete the code seg sub ax,7h mov es,ax mov ah,49h int 21h test [xmshandle],0ffffh ; see if in XMS jz nofreexms mov dx,xmshandle ; else free the XMS mem mov ah,0ah call xmsproc nofreexms: pop es pop ds ret exit endp dataarea db 1024 DUP (0) TsrEnd LABEL NEAR ;--------------------------------------------- ; ; Everything after this is non-resident. Between address zero and here ; we will keep the interrupt table if there is no XMS, otherwise we discard ; the memory. ; flag DB 00h pspseg dw 0 signon DB 0Ah,0Dh DB 'ESCAPE v3.0 by Selcuk Ayguney & D Lindauer, 1994,2000',0Ah,0ah,0Dh,'$' usage DB 'Usage : ESCAPE to install',0Ah,0Dh DB ' ESCAPE /R to restore interrupt table.',0Ah,0Dh DB ' ESCAPE /U to uninstall.',0Ah,0Dh DB 'Press F12 to ESCAPE from any program.',0Ah,0Dh,'$' uninst DB 'ESCAPE uninstalled.',0Ah,0Dh,'$' alinst DB 'ESCAPE already installed. Interrupt table refreshed.',0Ah,0Dh,'$' rest DB 'Interrupt table restored.',0Ah,0Dh,'$' xmsmemp db 'XMS being used for storage',0ah,0dh,'$' xmsmdat2 dd 1024 dw 0 dd 0 xmshandle2 dw 0 dd 0 ; ; subroutine to print a string. We will rarely have DS=CS ; print PROC NEAR push ds push cs pop ds MOV AH,09h INT 21h pop ds RET print ENDP ; ; Subroutine copies the interrupt table either to our data seg or to XMS ; Last thing we do before exiting ; CopyT PROC NEAR push ds push es test xmshandle2,0ffffh ; in XMS jnz xmscopyt push ds ; no, do a convention mem copy pop es CLD lea di,dataarea XOR SI,SI ; SI:=0 MOV DS,SI ; DS:=0 MOV CX,BufSize REP MOVSB ; Refresh jmp copytx xmscopyt: push ds ; in XMS, set up the data table pop es ; and transfer to XMS push cs pop ds lea si,xmsmdat2 mov ah,0bh call es:[xmsproc] copytx: pop es pop ds RET CopyT ENDP ; ; Subroutine copies the program down lower into the program area ; CopyE PROC NEAR push ds push cs pop ds CLD mov ax,[pspseg] ; Get env pointer add ax,7h mov es,ax sub di,di sub si,si mov cx,offset TsrEnd rep movsb clc pop ds ret CopyE ENDP ; ; Subroutine initializes XMS ; getxms proc near mov ax,4300h ; See if xms exists int 2fh cmp al,80h stc jnz xmsx mov ax,4310h ; get a pointer to its function int 2fh mov word ptr ds:[xmsproc],bx mov word ptr ds:[xmsproc+2],es mov ah,0 ; get the version and make sure it is 3 or higher call ds:[xmsproc] cmp ah,3 jc xmsx mov ah,9h ; allocate a 1K block mov dx,1 call ds:[xmsproc] cmp ax,1 stc jnz xmsx mov ds:[xmshandle],dx ; all done, everything was kosher mov [xmshandle2],dx clc xmsx: ret getxms endp ; ; Main program ; start proc near mov [pspseg],es ; save PSP for later LEA DX,signon ; signon message CALL print mov ax,3508h ; see if resident by checking int 8 int 21h cmp word ptr es:[sign],"AD" jnz L0 MOV [flag],01h ; yes resident, ES holds pointer to it L0: MOV SI,0081h ; scan command line MOV CX,0080h CLD space: LODSB CMP AL,20h JNZ param LOOP space param: MOV AX,WORD PTR [SI-1] CMP AX,'?/' ; Help wanted? JNZ IsItU LEA DX,usage CALL print MOV AX,4C01h INT 21h IsItU: CMP AX,'u/' ; Uninstall parameter? JZ Unin CMP AX,'U/' JZ Unin CMP AX,'r/' ; Refresh parameter? JZ restz CMP AX,'R/' JNZ Instl restz: CMP [flag],01h JZ L1 MOV AX,4C02h ; trying to refresh when not resident INT 21h l1: call dword ptr es:[jrefresh] ; Refresh command, call resident routine LEA DX,rest CALL print MOV AX,4C00h INT 21h Unin: CMP [flag],01h ; uninstall routine JZ L2 MOV AX,4C02h ; trying to uninstall when not installed INT 21h L2: call dword ptr es:[jexit] ; call TSR to uninstall LEA DX,uninst CALL print MOV AX,4C00h INT 21h Instl: CMP BYTE PTR CS:[flag],01h ; install routine JNZ L3 LEA DX,alinst ; trying to reinstall, just exit call print call dword ptr es:[jrefresh] ; Refresh command, call resident routine MOV AX,4C04h INT 21h l3: call COPYE ; copy environment mov word ptr es:[jexit+2],es ; initialize seg vals in the TSR mov word ptr es:[jrefresh+2],es MOV AH,0Fh ; Install, get graphics mode INT 10h MOV BYTE PTR es:[VidMod+1],AL push es ; install, get mouse mov ax,3533h int 21h mov ax,es or ax,bx pop es jz x1 push es mov ax,14h mov cx,0 int 33h mov ax,es pop es mov word ptr es:[mousemod + 1],cx mov word ptr es:[save2+1],dx mov word ptr es:[save1+1],ax mov ax,14h int 33h x1: push es ; at this point DS is the TSR pop ds call getxms ; initialize XMS lea dx,TsrEnd ; assume no XMS jc term ; term if so lea dx,xmsmemp ; else tell them call print lea dx,dataarea term : push dx ; save exit size MOV AX,3508h ; get old values of interrupts INT 21h ; and put them in the TSR MOV ds:jip8,BX MOV ds:jcs8,ES MOV AX,2508h ; set new values of interrupts LEA DX,int8 INT 21h CALL CopyT ; get the initial version of the int table mov es,[pspseg] ; drop the environment mov es,es:[2ch] mov ah,49h int 21h pop dx ; now get TSR size add dx,15+70h ; nonzero, calc paragraphs and load TSR mode mov cl,4 shr dx,cl mov ah,31h int 21h ; back to DOS start endp END start ; End of source