home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************************
- ; INSTALL inserts a bookmark in memory that allows TSRs installed above it
- ; to be removed from memory. Its syntax is:
- ;
- ; INSTALL [bookmark]
- ;
- ; where "bookmark" is the name of the bookmark. The bookmark name can be
- ; passed to REMOVE when a bookmark is removed. Only the first 32 characters
- ; of the name are used.
- ;****************************************************************************
-
- code segment
- assume cs:code
- org 100h
- begin: jmp init
-
- nextblock dw 0FFFFh ;Pointer to next block
- bookmark db "(No Name)",24 dup (0Dh);Default bookmark name
- signature db 0,1,2,"INSTALL",2,1,0 ;Program signature
- vectors dw 512 dup (?) ;Interrupt vectors
- prog_id db ? ;Multiplex ID number
- int2Fh dd ? ;Interrupt 2FH vector
-
- ;****************************************************************************
- ; MPLEX_INT handles interrupt 2FH. If, on entry, AH is set to INSTALL's
- ; multiplex ID number, MPLEX_INT uses the value in AL as a function code.
- ; The functions supported are:
- ;
- ; 00H Returns FFH in AL to indicate the program is installed
- ; and returns the address of its signature in ES:DI.
- ;****************************************************************************
-
- mplex_int proc far
- pushf ;Save FLAGS register
- cmp ah,cs:[prog_id] ;Branch if AH holds the
- je mplex2 ;multiplex ID
- popf ;Restore FLAGS
- jmp cs:[int2Fh] ;Pass the interrupt on
- ;
- ; Function 00H verifies that the program is installed.
- ;
- mplex2: popf ;Restore FLAGS
- or al,al ;Branch if function code
- jnz mplex3 ;is other than 00H
- mov al,0FFh ;Set AL to FFH
- push cs ;Point ES:DI to the program
- pop es ;signature
- mov di,offset signature
- mplex3: iret ;Return from interrupt
- mplex_int endp
-
- ;****************************************************************************
- ; Data that will be discarded when the program becomes memory-resident.
- ;****************************************************************************
-
- helpmsg db "Places a bookmark in memory that marks TSRs for "
- db "unloading.",13,10,13,10
- db "INSTALL [bookmark]",13,10,13,10
- db " bookmark Name of the bookmark being installed."
- db 13,10,13,10
- db "Bookmarks can be removed with INSTALL's companion "
- db "program, REMOVE. When a",13,10
- db "bookmark is removed, all the TSRs installed after "
- db "it are removed, too.",13,10,"$"
-
- errmsg1 db "Requires DOS 3.0 or higher",13,10,"$"
- errmsg2 db "INSTALL cannot be loaded high",13,10,"$"
- errmsg3 db "Program could not be installed",13,10,"$"
-
- msg1 db "INSTALL 1.3 Copyright (c) 1993 Jeff Prosise",13,10
- db "From: PC Magazine DOS 6 Memory Management "
- db "with Utilities",13,10,13,10
- db "Bookmark created. Use REMOVE to remove it."
- db 13,10,"$"
-
- ;****************************************************************************
- ; INIT makes the program resident in memory.
- ;****************************************************************************
-
- assume cs:code,ds:code
-
- init proc near
- cld ;Clear direction flag
- mov si,81h ;Point SI to command line
- call scanhelp ;Scan for "/?" switch
- jnc checkver ;Branch if not found
- mov ah,09h ;Display help text and exit
- mov dx,offset helpmsg ;with ERRORLEVEL=0
- int 21h
- mov ax,4C00h
- int 21h
- ;
- ; Check the DOS version and make sure the program isn't loaded high.
- ;
- checkver: mov dx,offset errmsg1 ;Exit if DOS version
- mov ah,30h ;is less than 3.0
- int 21h
- cmp al,3
- jae checkaddr
-
- error: mov ah,09h ;Display error message and
- int 21h ;exit with ERRORLEVEL=1
- mov ax,4C01h
- int 21h
-
- checkaddr: mov dx,offset errmsg2 ;Error if program is loaded
- mov ax,cs ;at segment address A000H or
- cmp ax,0A000h ;higher
- jae error
- ;
- ; Parse the command line.
- ;
- call findchar ;Advance to first character
- jc copy ;Branch if no parameters
- mov di,offset bookmark ;Point DI to buffer
- mov cx,32 ;Initialize counter
- parse1: lodsb ;Get a character
- cmp al,"a" ;Capitalize it if it's
- jb parse2 ;between "a" and "z"
- cmp al,"z"
- ja parse2
- and al,0DFh
- parse2: stosb ;Store it
- cmp al,0Dh ;Branch if was a carriage
- je copy ;return
- loop parse1 ;Loop back for more
- ;
- ; Copy the interrupt vector table from low memory.
- ;
- copy: push ds ;Save DS
- sub si,si ;Point DS:SI to 0000:0000
- mov ds,si
- assume ds:nothing
- mov di,offset vectors ;Point DI to storage area
- mov cx,512 ;Initialize counter
- cli ;Disable interrupts
- rep movsw ;Copy the vector table
- sti ;Enable interrupts
- pop ds ;Restore DS
- assume ds:code
- ;
- ; Install the program.
- ;
- call check_install ;Branch if a copy of INSTALL
- jnc install_full ;is not already installed
-
- mov di,offset nextblock ;Point DI to NEXTBLOCK
- install1: cmp word ptr es:[di],0FFFFh ;Branch if this is not the
- jne install2 ;last block in the chain
- mov word ptr es:[di],cs ;Record the address of this
- jmp short install_part ;block if it is
- install2: mov es,es:[di] ;Point ES to next block in
- jmp install1 ;the chain and loop back
-
- install_full: call mplex_id ;Find a multiplex ID number
- mov dx,offset errmsg3 ;Error if none available
- jc error
- mov prog_id,ah ;Save the ID number
-
- mov ax,352Fh ;Hook interrupt 2FH
- int 21h
- mov word ptr int2Fh,bx
- mov word ptr int2Fh[2],es
- mov ax,252Fh
- mov dx,offset mplex_int
- int 21h
-
- install_part: mov ah,49h ;Get the segment address of
- mov es,ds:[2Ch] ;the environment block
- int 21h ;and free the segment
-
- mov ah,09h ;Display message verifying
- mov dx,offset msg1 ;the installation
- int 21h
-
- mov ax,3100h ;Terminate with function 31H
- mov dx,(offset helpmsg - offset code + 15) shr 4
- int 21h
- init endp
-
- ;****************************************************************************
- ; FINDCHAR advances SI to the next non-white-space character. On return,
- ; carry set indicates EOL was encountered.
- ;****************************************************************************
-
- findchar proc near
- lodsb ;Get the next character
- cmp al,09h ;Loop if tab
- je findchar
- cmp al,20h ;Loop if space
- je findchar
- cmp al,2Ch ;Loop if comma
- je findchar
- dec si ;Point SI to the character
- cmp al,0Dh ;Exit with carry set if end
- je eol ;of line is reached
-
- clc ;Clear carry and exit
- ret
-
- eol: stc ;Set carry and exit
- ret
- findchar endp
-
- ;****************************************************************************
- ; SCANHELP scans the command line for a /? switch. If found, carry returns
- ; set and SI contains its offset. If not found, carry returns clear.
- ;****************************************************************************
-
- scanhelp proc near
- push si ;Save SI
- scanloop: lodsb ;Get a character
- cmp al,0Dh ;Exit if end of line
- je scan_exit
- cmp al,"?" ;Loop if not "?"
- jne scanloop
- cmp byte ptr [si-2],"/" ;Loop if not "/"
- jne scanloop
-
- add sp,2 ;Clear the stack
- sub si,2 ;Adjust SI
- stc ;Set carry and exit
- ret
-
- scan_exit: pop si ;Restore SI
- clc ;Clear carry and exit
- ret
- scanhelp endp
-
- ;****************************************************************************
- ; CHECK_INSTALL returns carry set if the program is already installed,
- ; carry clear if it's not. If carry returns set, AH holds the program's
- ; multiplex ID number.
- ;****************************************************************************
-
- check_install proc near
- mov ax,0C000h ;Initialize AH and AL
- mov cx,40h ;Initialize count
-
- chinst1: push ax ;Save AX and CX
- push cx
- sub di,di ;Set ES and DI to 0
- mov es,di
- int 2Fh ;Interrupt 2Fh
- cmp al,0FFh ;Nothing here if AL isn't
- jne chinst2 ;equal to FFH
-
- mov si,offset signature ;See if program signature
- mov cx,13 ;appears at the address
- repe cmpsb ;returned in ES:DI
- jne chinst2 ;Branch if it does not
-
- pop cx ;Clear the stack and exit
- pop ax ;with carry set
- stc
- ret
-
- chinst2: pop cx ;Retrieve AX and CX
- pop ax
- inc ah ;Next multiplex ID
- loop chinst1 ;Loop until done
-
- clc ;Exit with carry clear
- ret
- check_install endp
-
- ;****************************************************************************
- ; MPLEX_ID searches for an unused multiplex ID number. If one is found,
- ; it is returned in AH with carry clear. Carry set means no multiplex
- ; ID numbers are currently available.
- ;****************************************************************************
-
- mplex_id proc near
- mov ax,0C000h ;Initialize AH and AL
- mov cx,40h ;Initialize count
-
- mxid1: push ax ;Save AX and CX
- push cx
- int 2Fh ;Interrupt 2Fh
- or al,al ;Branch if AL=0
- jz mxid2
- pop cx ;Retrieve AX and CX
- pop ax
- inc ah ;Increment ID number
- loop mxid1 ;Loop until done
-
- stc ;Exit with carry set
- ret
-
- mxid2: pop cx ;Clear the stack and exit
- pop ax ;with carry clear
- clc
- ret
- mplex_id endp
-
- code ends
- end begin
-