home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
pcmag
/
vol12n22.zip
/
QPATH.ZIP
/
QPATH.ASM
next >
Wrap
Assembly Source File
|
1993-11-24
|
33KB
|
1,175 lines
page 66,132
;====================================================================
; QPATH.COM Looks for a program on an extra path string before
; COMMAND.COM makes its standard search
;
; QPATH [/E] [/D] [/U] [/X cmd,cmd,cmd]
;
;
; where /U = Uninstall the program
; /E = Enable extra path search
; /D = Disable extra path search
; /X = Spefify commands to disable
;
;====================================================================
BUFFSIZE equ 130
DTASIZE equ 2Ch
QPATHSIZE equ offset qpathname_end - offset qpathname
PATHSIZE equ offset pathname_end - offset pathname
REG_AL equ byte ptr ss:[bp+10h]
DTAPTR equ offset end_of_resident
BUFFOFFSET equ DTAPTR + DTASIZE
ENDOFBUFF equ BUFFOFFSET + BUFFSIZE
MUXINSTCHK equ 0
MUXENABLE equ 1
MUXDISABLE equ 2
MUXQUERY equ 3
code segment
assume cs:code
org 2ch
env_segment dw ? ;Word containing the segment
; of the program's env. block.
org 80h
command_tail db ? ;Offset of the command tail.
org 100h
begin: jmp initialize
program db 13,10,"QPATH 1.0 "
copyright db "Copyright (c) 1993 Douglas Boling",10,13
author db "First Published in PC Magazine Dec 7, 1993"
db 10,10,13,"$",1Ah
endtag = $
int21h dd -1 ;Int 21 vector (DOS Dispatch)
int2fh dd -1 ;Int 2f vector (DOS Multiplex)
xms_service dd -1 ;Entry pt to XMS driver
dos_version dw 0 ;DOS Version number
xms_flag db 0 ;XMS driver present flag
chk_path db 1 ;Enable flag.
main_active db 0 ;Active flag
multiplex_id db 0dbh ;Program ID for multiplex int
api_tbl dw offset inst_chk ;Jump table for app mux
dw offset appenable ; interrupt functions.
dw offset appdisable
dw offset enablequery
api_tblend = $
qpathname db "QPATH=" ;QPATH env var name
qpathname_end = $
pathname db "PATH=" ;PATH env var name
pathname_end = $
db ';' ;Needed for name sub
pathptr dd ?
qpathptr dd ?
;
;DOS state variables
;
ret_addr dw 0 ;Value used by Save Regs routine
A20_state dw 0 ;State of A20 flag
saved_dta dd 0 ;saved pointer to curr DTA
saved_psp dw 0 ;saved segment of curr PSP
buff_ptr dd 0 ;Ptr to working buff
exbuff_ptr dw 0 ;Ptr to exclude buffer
command_ptr dd 0 ;Ptr to cmd.com command
intcmd_ptr dd 0 ;Ptr to formatted cmd
int1bh dd -1 ;Int 1b vector (Break)
int23h dd -1 ;Int 23 vector (Ctrl C)
int24h dd -1 ;Int 24 vector (Crit Error)
errinfoarray:
errAX dw 0 ;Saved extended error info
errBX dw 0
errCX dw 0
errDX dw 0
errSI dw 0
errDI dw 0
errDS dw 0
errES dw 0
dw 3 dup (0) ;Reserved error table bytes
exts db ".BAT.EXE.COM",0
extflag db 0 ;Extension specified
goflag db 0 ;Prog found flag
disablecmd db 0 ;Disable cmd flag
;====================================================================
; DOSINT processes calls to interrupt 21h
; Entry: AH - DOS function
;====================================================================
dosint proc far
assume cs:code,ds:nothing,es:nothing
cmp cs:goflag,0 ;See if we need to
jne dosint_1 ; fool cmd.com
goto_dosint:
jmp cs:[int21h] ;else pass the call on
dosint_1:
cmp ah,4bh ;EXEC
je dos_exec
cmp ah,48h ;Alloc Mem
je dos_exec
cmp ah,4eh ;Find First
je dos_ff
jmp short goto_dosint
dos_exec:
mov cs:goflag,0 ;Stop fooling program
push es
push di
push ds
push si
mov si,cs ;Copy QPATH back over
mov ds,si ; PATH=;
mov si,offset qpathname
les di,cs:qpathptr
movsw
movsw
movsw
lds si,cs:pathptr
mov di,ds ;Validate path ptr
or di,di
je dos_exec1
mov byte ptr [si],'P' ;Restore PATH= from ~ATH=
dos_exec1:
pop si
pop ds
pop di
pop es
jmp cs:[int21h] ;Pass the call on
dos_ff:
dec cs:goflag
cmp cs:goflag,-2
je dos_ff1
jmp cs:[int21h] ;Pass the call on
dos_ff1:
push bp
mov bp,sp
or word ptr ss:[bp+6],1 ;Set carry flag
pop bp
mov ax,12h ;No more files
iret
dosint endp
;====================================================================
; MUXINT processes calls to interrupt 2Fh
; Entry: AH - Device ID
; AL - Command
;====================================================================
muxint proc far
assume cs:code,ds:nothing,es:nothing
cmp ah,0AEh ;Command.com cmd hook
je cmd_chk
cmp ah,cs:[multiplex_id] ;Check for program ID
je muxint_myapi ;Its us, chk our cmds
goto_muxint:
jmp cs:[int2fh] ;else pass the call on
cmd_chk:
cmp dx,-1 ;See if really cmd hook
jne goto_muxint
or al,al ;See if chk or launch
jne cmd_launch
call main ;Check cmd
cmp cs:goflag,0
je goto_muxint
iret
cmd_launch:
cmp cs:[disablecmd],0 ;See if disable cmd set
mov cs:[disablecmd],0 ;Clear disable cmd flag
je goto_muxint
mov byte ptr ds:[si],0 ;Zero cmd length byte
iret
muxint_myapi:
cmp al,(offset api_tblend - offset api_tbl) shr 1
jae muxint_iret
push bx
mov bl,al
xor bh,bh
shl bx,1
mov ax,cs:[bx+offset api_tbl]
pop bx
call ax
muxint_iret:
iret
muxint endp
;--------------------------------------------------------------------
;QPATH multiplex functions
;--------------------------------------------------------------------
my2fapi proc near
inst_chk:
mov ax,-1 ;Indicate QPATH installed
push cs ;ES = installed code segment
pop es
ret
appenable:
mov cs:chk_path,1 ;Set enable flag
jmp short enablequery
appdisable:
mov cs:chk_path,0 ;Clear enable flag
enablequery:
xor dx,dx
mov dl,cs:chk_path ;Get enable flag state
xor ax,ax
ret
my2fapi endp
;====================================================================
; CRITICALERR receives control when an interrupt 24h is generated.
;====================================================================
criterrint proc far
assume cs:code,ds:nothing,es:nothing
mov al,3 ;Set to Fail
criterr_iret:
iret
criterrint endp
;--------------------------------------------------------------------
; MAIN - Saves regs, calls chk disable and chk path
;--------------------------------------------------------------------
main proc near
assume cs:code,ds:nothing,es:nothing
inc cs:main_active ;Check to see if active
jnz main_exit
cmp cs:chk_path,0 ;See if disabled
je main_exit
;Save regs and critical pointers
cld ;Set string dir flag
mov word ptr cs:[command_ptr],bx
mov word ptr cs:[command_ptr+2],ds
mov word ptr cs:[intcmd_ptr],si
mov word ptr cs:[intcmd_ptr+2],ds
call save_regs ;Save register state
assume ds:code
call chk_discmds ;Check for disabled cmd
jc main_restore ;CF set, cmd disabled
cmp goflag,0 ;See if already active
jne main_restore
call chkcmd ;See if path specified
jc main_restore
call chkmypath ;Check Quick path
main_restore:
call restore_regs ;Restore register state
main_exit:
dec cs:main_active
ret
main endp
;--------------------------------------------------------------------
; CHK_DISCMDS - Checks list of disabled commands.
;--------------------------------------------------------------------
chk_discmds proc near
assume cs:code,ds:code
les di,intcmd_ptr ;Get ptr to formatted cmd
mov si,exbuff_ptr ;Get ptr to excluded cmds
xor ax,ax
xor cx,cx
mov cl,es:[di] ;Get length of cmd
inc di
chk_discmds_1:
lodsb ;Get length of ex cmd
or al,al
je chk_discmds_exit
cmp ax,cx ;See if same length
jne chk_discmds_2
push si
push di
repe cmpsb
pop di
pop si
mov cx,ax
je chk_discmds_3
chk_discmds_2:
add si,ax ;Point to next cmd
jmp short chk_discmds_1
chk_discmds_3:
mov REG_AL,-1 ;Accept cmd
mov cs:disablecmd,1 ;Set flag to catch next call
stc ;Indicate cmd disabled
chk_discmds_exit:
ret
chk_discmds endp
;--------------------------------------------------------------------
; CHKMYPATH - searches list of directories for a file
;--------------------------------------------------------------------
chkmypath proc near
assume cs:code,ds:code
;Save necessary DOS state
cmp xms_flag,0
je skip_xms_save
mov ah,7 ;Get state of A20 line
call [xms_service]
mov A20_state,ax
skip_xms_save:
;Point the interrupt 1Bh, 23h, and 24h vectors to internal handlers.
mov al,1bh
mov di,offset int1bh
mov dx,offset criterr_iret
call getandsetint
mov al,23h
mov di,offset int23h
mov dx,offset criterr_iret
call getandsetint
mov al,24h
mov di,offset int24h
mov dx,offset criterrint
call getandsetint
;Save extended error information
push ds ;save DS
mov ah,59h ;Extended error info
int 21h ;Call DOS
mov cs:[errDS],ds ;save returned DS
pop ds ;Restore DS
push bx
mov bx,offset errinfoarray ;Save data in registers
mov [bx],ax ; in this specific order.
pop [bx+2]
mov [bx+4],cx
mov [bx+6],dx
mov [bx+8],si
mov [bx+10],di
mov [bx+14],es
;Save active PSP and DTA, then switch to my PSP and DTA
mov ah,51h ;Get current PSP
int 21h
mov saved_psp,bx ;save it
mov ah,2fh
int 21h ;Get current DTA
mov word ptr saved_dta,bx ;save it
mov word ptr saved_dta+2,es
mov dx,DTAPTR ;Set DTA
push cs
pop bx ;Set active PSP to us
call setpspdta
;Do the work
call srchpath ;Look for file
push ax ;Save found flag
or al,al
jne chkmypath_2
mov si,offset pathname ;If program found in
mov cx,PATHSIZE ; qpath, fake out
mov word ptr [pathptr+2],0 ; COMMAND.COM by subbing
call getevar ; the QPATH for the PATH
cmp byte ptr es:[di],0 ; in the environment.
je chkmypath_1
sub di,PATHSIZE
mov word ptr [pathptr],di ;Save ptr to PATH var
mov word ptr [pathptr+2],es ; in the environment.
mov byte ptr es:[di],'~' ;Change PATH= to ~ATH=
chkmypath_1:
call getqpath
sub di,QPATHSIZE
mov word ptr [qpathptr],di
mov word ptr [qpathptr+2],es
mov si,offset pathname
movsw ;Copy PATH=; over QPATH=
movsw
movsw
chkmypath_2:
;Restore DOS state, start with DTA and PSP
push ds
mov bx,saved_psp ;Get old PSP
lds dx,saved_dta ;Get old DTA
call setpspdta ;Set old PSP and DTA
pop ds
mov ax,5d0ah ;Restore ext error info
mov dx,offset errinfoarray ;point to Saved info
int 21h
push ds
mov ax,2524h ;Restore crit err int
lds dx,int24h
int 21h
mov ax,2523h ;Restore ctl C int
lds dx,int23h
int 21h
mov ax,251bh ;Restore break int
lds dx,int1bh
int 21h
pop ds
cmp xms_flag,0 ;See if XMS driver present
je skip_xmsrestore
mov ah,5 ;Assume local disable A20
cmp A20_state,0
je xms_restore_1
inc ah ;Change to local enable A20
xms_restore_1:
call [xms_service] ;Restore A20 line state
skip_xmsrestore:
pop ax
not al
mov goflag,al ;Save found flag
chkmypath_exit:
ret
chkmypath endp
;--------------------------------------------------------------------
; SRCHPATH - searches list of directories for a file
; Exit: AL = 0 if file found
;--------------------------------------------------------------------
pathdirptr equ dword ptr ss:[bp-4]
pathdiroff equ word ptr ss:[bp-4]
pathdirseg equ word ptr ss:[bp-2]
srchpath proc near
assume cs:code,ds:code
push bp
push ds
mov bp,sp
sub sp,4
call getqpath ;Get ptr to QPATH data
srchpath_1:
mov pathdiroff,di ;Save ptr to path dir
mov pathdirseg,es
les di,buff_ptr ;Get ptr to work buff
lds si,pathdirptr ;Get ptr to curr path dir
assume ds:nothing
mov al,-1
cmp byte ptr [si],0 ;See if end of path str
je srchpath_exit
mov ax,3b00h ;Copy up to ';'
call copystr ;Copy path directory
cmp byte ptr es:[di-1],'\' ;See if term \
je srchpath_2
mov al,'\'
stosb ;Append \
srchpath_2:
lds si,cs:[command_ptr] ;Get ptr to filename
lodsw ;Skip past size bytes
mov ax,0d01h
call copystr ;Append to path
push cs
pop ds
assume ds:code
call findprog ;See if prog name in dir
jnc srchpath_exit ;File found, exit
les di,pathdirptr ;Find next dir in
mov ah,';' ; the path.
call findchar
jmp short srchpath_1
srchpath_exit:
mov sp,bp
pop ds
pop bp
ret
srchpath endp
;--------------------------------------------------------------------
; FINDPROG - searches a directory for a COM EXE or BAT file.
; Entry: Program name loaded in working buffer.
; ES:DI pointing to end of filename.
; Exit: AL = 0 if file found
;--------------------------------------------------------------------
findprog proc near
assume cs:code,ds:code,es:code
push bp
mov bp,di
cmp extflag,0 ;See if extension needed
jne findprog_1
mov ax,'*.' ;Append .*
stosw
findprog_1:
xor ax,ax ;Terminate filename with 0
stosb
lds dx,buff_ptr ;DS:DX ptr to filename
mov cx,7 ;Look for all kinds of files
mov ah,4Eh ;Find first file
int 21h
jc findprog_exit
cmp extflag,0 ;See if ext specified
jne findprog_6
xor cx,cx ;Clear file found flag
findprog_2:
mov si,offset exts
mov di,DTAPTR+1Eh ;Point to found extension
mov ah,'.'
call findchar
dec di
findprog_21:
push di
mov bx,si ;File found, compare extension
cmpsw ; found to allowable prog
jne findprog_3 ; extensions: COM EXE BAT.
cmpsw
findprog_3:
pop di
je findprog_4 ;Found ext, cmp to last found.
mov si,bx
add si,4
cmp byte ptr [si],0
jne findprog_21
jmp short findprog_41 ;If no more exts, search again.
findprog_4:
cmp cx,bx ;See if higher priority than
ja findprog_41 ; prev found prog extension.
mov cx,bx
findprog_41:
mov ah,4fh ;Find Next file
int 21h
jnc findprog_2
findprog_5:
or cx,cx ;See if no prog files found.
stc
je findprog_exit
mov si,cx
mov di,bp ;Get ptr to end of filename
movsw ;Append found extension.
movsw
xor ax,ax ;Set found flag and
stosb ; zero terminate filename
findprog_6:
clc
findprog_exit:
pop bp
ret
findprog endp
;--------------------------------------------------------------------
; GETQPATH - Returns a pointer to the QPATH env var
; Exit: ES:DI Ptr to QPATH var data
;--------------------------------------------------------------------
getqpath proc near
assume cs:code,ds:code
mov si,offset qpathname
mov cx,QPATHSIZE
call getevar
ret
getqpath endp
;--------------------------------------------------------------------
; GETEVAR - Returns a pointer to an envrironment variable
; Entry: DS:SI Ptr to variable name
; CX Length of variable name
; Exit: ES:DI Ptr to variable data
;--------------------------------------------------------------------
getevar proc near
assume cs:code,ds:code
mov es,saved_psp ;Get Command.com seg
mov es,es:[env_segment] ;Get env seg
xor di,di
getevar_1:
push si
push cx
repe cmpsb
pop cx
pop si
je getevar_exit
xor al,al ;Find next env var
push cx
mov cx,200
repne scasb
pop cx
cmp byte ptr es:[di],0 ;At end of env?
jne getevar_1
getevar_exit:
ret
getevar endp
;--------------------------------------------------------------------
; CHKCMD - Checks a command to see if includes a path spec
; Exit: CF - Set if path specified
;--------------------------------------------------------------------
chkcmd proc near
assume ds:nothing,es:nothing
mov cs:extflag,0
push ds
push es
push cs
pop es
assume es:code
lds si,command_ptr
cmp byte ptr [si+3],':' ;See if drive speced
je chkcmd_error
inc si
xor ch,ch
mov cl,[si] ;Get length of command
inc si
chkcmd_1:
lodsb
cmp al,'\'
je chkcmd_error
cmp al,'.' ;See if extension speced
jne chkcmd_2
inc cs:extflag
jmp short chkcmd_3
chkcmd_2:
call isfilechar
jc chkcmd_4
chkcmd_3:
loop chkcmd_1
chkcmd_4:
clc
chkcmd_exit:
pop es
pop ds
ret
chkcmd_error:
stc
jmp short chkcmd_exit
chkcmd endp
;-----------------------------------------------------------------------------
; ISFILECHAR - Determines if a character is an allowable DOS filename char
; Entry: AL - ASCII char to check
; Exit: CF - Set if not an allowable filename char
;-----------------------------------------------------------------------------
filechar_chars db "!#$%^&()-_{}~" ;Valid filename chars
filechar_endc = $
isfilechar proc near
assume ds:nothing,es:code
push cx
cmp al,128 ;Check for graphics chars
jnc isfilechar_exit
mov cx,"09" ;Check for numbers
call inside
jnc isfilechar_exit
push ax
or al,20h
mov cx,"az" ;Check for letters
call inside
pop ax
jnc isfilechar_exit
push di ;Check for other chars
cld
mov di,offset filechar_chars
mov cx,offset filechar_endc - offset filechar_chars
repne scasb
pop di
je isfilechar_exit
stc
isfilechar_exit:
pop cx
ret
;Simple routine to bounds check a character
inside proc near
cmp al,ch ;See if char inside
jb inside_exit ; char range indicated
cmp cl,al ; by CL and CH
inside_exit:
ret
inside endp
isfilechar endp
;--------------------------------------------------------------------
; COPYSTR - Copies a string up to a character
; COPYNSTR - Copies a string (of N max bytes) up to a character
; Entry: DS:SI source string
; ES:DI dest
; AH Term char of string
; AL If 1, copy only valid filename chars
; Exit: DI,SI updated
;--------------------------------------------------------------------
copystr proc near
push bx
mov bx,ax
copystr_1:
lodsb
cmp al,ah ;See if end char
je copystr_exit
or al,al ;See if end of string
je copystr_exit
or bl,bl
je copystr_2
call isfilechar ;See if valid filename
jc copystr_exit ; char
copystr_2:
stosb
jmp short copystr_1
copystr_exit:
pop bx
ret
copystr endp
;--------------------------------------------------------------------
; FINDCHAR - Scans an ASCIIZ string for a char
; Entry: ES:DI source string
; AH search char
; Exit: DI Points to char if found
;--------------------------------------------------------------------
findchar proc near
mov al,es:[di]
or al,al
je findchar_1
inc di
cmp al,ah
jne findchar
findchar_1:
ret
findchar endp
;--------------------------------------------------------------------
; GETANDSETINT - Gets and saves an interrupt then sets to new value
; Entry: AL - Interrupt number
; DI - Ptr to dword save vector
; DX - Offset of new routine
;--------------------------------------------------------------------
getandsetint proc near
push ax
mov ah,35h ;Get interrupt vector
int 21h
mov word ptr [di],bx ;Save old vector
mov word ptr [di+2],es
pop ax
mov ah,25h ;Set new vector
int 21h
ret
getandsetint endp
;--------------------------------------------------------------------
; SETPSPDTA - Sets the Active PSP and current DTA
; Entry: BX - New PSP
; DX - New DTA
;--------------------------------------------------------------------
setpspdta proc near
mov ah,50h ;Set internal PSP
int 21h
mov dx,DTAPTR ;use PSP for DTA
mov ah,1ah ;Set DTA
int 21h
ret
setpspdta endp
;--------------------------------------------------------------------
; SAVEREGS saves all the registers used in the interrupt routines and
; sets DS.
;--------------------------------------------------------------------
save_regs proc near
pop cs:[ret_addr] ;Get address to return
push ax ;save all registers
push bx
push cx
push dx
push bp
push si
push di
push ds
push es
mov bp,sp ;Set bp to stack frame
push cs ;Set DS = CS
pop ds
assume ds:code
jmp word ptr [ret_addr] ;Return
save_regs endp
;--------------------------------------------------------------------
;RESTOREREGS restores register values.
;--------------------------------------------------------------------
restore_regs proc near
pop ret_addr ;Save return address
pop es ;restore registers
pop ds
assume ds:nothing
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
jmp word ptr cs:[ret_addr] ;Return
restore_regs endp
final_install:
rep movsb ;copy exclude string
mov main_active,-1 ;Enable installed code
int 21h ;TSR
even ;Align stack on word boundry
end_of_resident = $
;--------------------------------------------------------------------
; Non-resident data.
;--------------------------------------------------------------------
alrdy_installed db 0 ;Installed flag
other_seg dw 0 ;Segment of installed code
infomsg0 db 13,10,"For help type QPATH /?$"
infomsg1 db "QPATH uninstalled$"
infomsg2 db "QPATH $"
infomsg2a db "disabled",13,10,"$"
infomsg2b db "enabled",13,10,"$"
infomsg3 db "QPATH installed$"
errmsg0 db "Need DOS 3.3 or greater$"
errmsg1 db "QPATH not installed$"
errmsg2 db 13,10,"Syntax: QPATH [/D][/E][/U][/X cmd[, ...]]"
db 13,10,10
db 9,"/D = Disable",13,10
db 9,"/E = Enable",13,10
db 9,"/U = Uninstall",13,10
db 9,"/X = Exclude commands",13,10,"$"
errmsg3 db "Can",39,"t uninstall$"
errmsg4 db "Error using Int 2Fh$"
errmsg5 db "Can",39,"t disable commands once installed$"
endmsg db 13,10,"$"
cmd_switches db "udex" ;Letters of valid commands.
cmd_switch_end = $
cmd_tbl dw offset remove ;This jump table is used to
dw offset disable ; call the routines that
dw offset enable ; process the command line
dw offset exclude
;--------------------------------------------------------------------
; Initialization routine.
;--------------------------------------------------------------------
initialize proc near
assume cs:code,ds:code,es:code
cld
mov dx,offset program ;Display copyright message
call printmsg
mov ah,30h ;Get DOS version
int 21h
xchg al,ah ;Swap major, minor numbers
mov dx,offset errmsg0 ;Bad DOS version
cmp ax,31eh ;Run if DOS 3.3 or greater.
jb disp_error
mov dos_version,ax ;Save version number
call findinstalled ;See if another copy in mem
jc disp_error
mov other_seg,es ;Save seg of installed code
push cs
pop es
assume es:code
call parse_line ;Parse command line
jc disp_error
cmp alrdy_installed,0 ;If not already installed,
je install ; jump to install routine.
xor al,al ;Zero return code
exit:
mov ah,4Ch ;Terminate
int 21h
disp_error:
assume ds:nothing
call printmsgcr ;Print error message
mov al,1
jmp short exit
;
;Install routine. Find segment of COMMAND.COM, hook into int 2Fh and TSR.
;
install:
assume ds:code
mov ax,4300h ;Look for HIMEM.SYS
int 2fh
or al,al
je noxms
inc xms_flag
mov ax,4310h ;Get entry point for XMM
int 2fh
mov word ptr [xms_service],bx
mov word ptr [xms_service+2],es
push cs
pop es
noxms:
mov al,21h ;Get and set int 21 (DOS)
mov di,offset int21h
mov dx,offset dosint
call getandsetint
mov al,2fh ;Get and set int 21 (DOS)
mov di,offset int2fh
mov dx,offset muxint
call getandsetint
push ds ;ES = DS
pop es
mov dx,offset infomsg3 ;Tell user we are
call printmsgcr ; installing
mov dx,ENDOFBUFF ;Set ptr to exclude buffer.
mov word ptr [buff_ptr], BUFFOFFSET
mov word ptr [buff_ptr+2],cs
mov word ptr [exbuff_ptr],dx
mov cx,-1 ;Get size of exclude buff
mov si,offset end_of_code
mov di,si
xor al,al
repne scasb
not cx
add dx,cx ;Add to end of res offset
add dx,15 ;Compute installed size
push cx
mov cl,4
shr dx,cl
pop cx ;Get back disabled cmds len
mov ax,3100h
mov di,exbuff_ptr ;Get ptr for disabled cmds
jmp final_install
initialize endp
DTAPTR equ offset end_of_resident
BUFFOFFSET equ DTAPTR + DTASIZE
ENDOFBUFF equ BUFFOFFSET + BUFFSIZE
;--------------------------------------------------------------------
; FINDINSTALLED - Finds any installed copies of the program in memory.
; Exit: Sets the already installed flag
; ES points to installed segment or CS if no copy found.
; CF - Set if all Multiplex IDs used
;--------------------------------------------------------------------
findinstalled proc near
assume cs:code,ds:code
mov cx,36 ;Try 36 different IDs.
find_copy1:
xor ax,ax ;Zero ES
mov es,ax
push ds
push cx
mov ah,multiplex_id ;Load ID. Use Int 2Fh to
int 2fh ; reach installed code
pop cx
pop ds
or al,al
je find_copynf
mov si,es ;See if ES <> 0. If so,
or si,si ; compare headers.
jne find_copy3
find_copy2:
inc multiplex_id ;ID used by another program.
loop find_copy1 ; Change and try again.
mov dx,offset errmsg4 ;All IDs taken, print error
stc
jmp find_copyexit1
find_copy3:
push cx
call cmpheader ;See if correct program by
pop cx ; comparing file headers.
jne find_copy2
inc alrdy_installed ;Set installed flag
find_copyexit:
clc
find_copyexit1:
ret
find_copynf:
push cs
pop es ;If AL not changed, prog not
jmp short find_copyexit ; installed.
findinstalled endp
;--------------------------------------------------------------------
; CMPHEADER compares the first 16 bytes of this file with the segment
; pointed to by ES.
; Entry: DS - code segment
; ES - pointer to segment to compare
; Exit: ZF - 0 = segments match.
;--------------------------------------------------------------------
cmpheader proc near
mov si,offset begin+3 ;Compare 16 bytes of block
mov di,si ; for ASCII fingerprint.
mov cx,16
repe cmpsb
ret
cmpheader endp
;--------------------------------------------------------------------
; PRINTMSG prints the message pointed to by DX to the screen.
; Entry: DX - pointer to ASCII message terminated by $
;--------------------------------------------------------------------
printmsg proc near
assume ds:nothing,es:nothing
push ds
push cs
pop ds
assume ds:code
mov ah,9 ;Print message
int 21h
pop ds
ret
printmsg endp
;--------------------------------------------------------------------
; PRINTMSGCR calls PRINTMSG, then appends a carriage return to the
; message.
; Entry: DX - pointer to ASCII message terminated by $
;--------------------------------------------------------------------
printmsgcr proc near
assume ds:nothing,es:nothing
push dx
call printmsg
mov dx,offset endmsg
call printmsg
pop dx
ret
printmsgcr endp
;--------------------------------------------------------------------
; PARSELINE Parses the command line
;--------------------------------------------------------------------
parse_line proc near
assume cs:code,ds:code,es:code
mov si,offset command_tail ;Point to command line
lodsb
or al,al ;See if any chars on line
je parse_end
parse_loop:
call scan4char ;Get 1st character
jc parse_end ;If CR exit
cmp al,"/" ;Compare character to switch.
jne short parse_exit
lodsb ;Get command line switch
or al,20h ; switches.
mov di,offset cmd_switches
mov cx,offset cmd_switch_end - offset cmd_switches
repne scasb
mov dx,offset errmsg2 ;Syntax message
jne parse_exit
mov bx,offset cmd_switch_end - offset cmd_switches - 1
sub bx,cx ;Copy index into list
shl bx,1 ;Convert to word offset
call cs:[bx+offset cmd_tbl] ;Call command routine.
jnc parse_loop ;If no error, continue
parse_exit:
ret
parse_end:
clc
jmp short parse_exit
parse_line endp
;--------------------------------------------------------------------
; ENABLE enables installed code
;--------------------------------------------------------------------
enable proc near
assume ds:code,es:code
cmp alrdy_installed,0
je enable_2
mov ah,multiplex_id ;Enable
mov al,MUXENABLE
int 2fh
enable_2:
clc
ret
enable endp
;--------------------------------------------------------------------
; DISABLE disables installed code
;--------------------------------------------------------------------
disable proc near
assume ds:code,es:code
mov chk_path,0
cmp alrdy_installed,0
je disable_2
mov ah,multiplex_id ;Enable
mov al,MUXDISABLE
int 2fh
disable_2:
clc
ret
disable endp
;--------------------------------------------------------------------
; EXCLUDE disables COMMAND.COM commands
;--------------------------------------------------------------------
exclude proc near
assume ds:code,es:code
mov dx,offset errmsg5
cmp alrdy_installed,0 ;If installed, fail
stc ; switch
jne exclude_exit
mov di,offset end_of_code ;Set ex buff ptr
exclude_1:
call scan4char ;Find first command
jc exclude_2
dec si ;Back up to char
mov bx,di ;Save start ptr
inc di
mov cx,"az"
exclude_10:
lodsb ;Copy command. Convert
call inside ; to upper case during
jc exclude_11 ; copy.
and al,0dfh ;Make upper case
exclude_11:
call isfilechar
jc exclude_12
stosb
jmp short exclude_10
exclude_12:
mov dx,di
sub dx,bx
dec dx
mov es:[bx],dl ;Copy length of command
cmp al,','
je exclude_1
exclude_2:
mov byte ptr [di],0 ;Terminate string
dec si
clc
exclude_exit:
ret
exclude endp
;--------------------------------------------------------------------
; REMOVE uninstalls the installed program from memory.
;--------------------------------------------------------------------
remove proc near
assume ds:code,es:code
push ds
push es
mov dx,offset errmsg1 ;Not installed msg
cmp alrdy_installed,0 ;See if installed
je remove_exit
mov ax,3521h ;Get DOS vector
int 21h
mov ax,es ;Check to make sure DOS
cmp ax,cs:[other_seg] ; vector not modified.
jne remove_error
mov ax,352fh ;Get MUX vector
int 21h
mov ax,es ;Check to make sure MUX
cmp ax,cs:[other_seg] ; vector not modified.
jne remove_error
lds dx,es:[int21h] ;Get old interrupt 21 vector
mov ax,2521h ;Set interrupt
int 21h
lds dx,es:[int2Fh] ;Get old interrupt 2F vector
mov ax,252fh ;Set interrupt
int 21h
mov cx,es:[env_segment]
mov ah,49h ;Free program memory block
int 21h
mov es,cx ;Free environment block
mov ah,49h
int 21h
mov dx,offset infomsg1 ;Indicate uninstalled.
remove_exit:
stc
pop es
pop ds
ret
remove_error:
mov dx,offset errmsg3 ;Can't remove error msg
jmp short remove_exit
remove endp
;--------------------------------------------------------------------
; SCAN4CHAR scans a string to find the first character.
; Entry: SI - pointer to ASCII string
; Exit: AL - first nonspace character
; CF - set if carriage return found
;--------------------------------------------------------------------
scan4char proc near
assume ds:nothing,es:nothing
scan4loop:
lodsb
cmp al,13 ;Check for carriage return.
stc
je scan4_exit
cmp al,21h ;Check for space or other
jb scan4loop ; 'white' characters.
scan4_exit:
ret
scan4char endp
end_of_code = $
db 0 ;Default end of ex buffer
code ends
end begin