home *** CD-ROM | disk | FTP | other *** search
- page 66,132
- ;=============================================================================
- ; TEMPLATE - A template for a Terminate and stay resident program
- ;
- ; Written by Douglas Boling
- ;
- ; Revision History
- ;
- ; 1.0 Initial Release
- ;
- ;=============================================================================
- ;----------------------------------------------------------------------------
- ; BIOS Data segment
- ;----------------------------------------------------------------------------
- bios_data segment at 40h
- org 17h
- shift_state db ? ;State of keyboard shift keys
- org 4Eh
- video_buffoff dw ? ;Offset of video buffer
- org 63h
- video_ioregs dw ? ;I/O addr of video controller
- org 84h
- video_rows db ? ;Number of rows on the screen
- bios_data ends
- ;----------------------------------------------------------------------------
- ; CODE segment
- ;----------------------------------------------------------------------------
- code segment para public 'code'
- assume cs:code
-
- POPTIME EQU 18 ;Ticks allowed until popup
- RESSTACKSIZE EQU 512 ;Size of resident stack
-
- org 80h
- command_tail db ?
- org 100h
- begin: jmp initialize
-
- program db "Template 1.0 (c) 1992 Douglas Boling",13,10
- db "Written by Douglas Boling$",26
- ;-----------------------------------------------------------------------------
- ; Memory locations required for system overhead.
- ;-----------------------------------------------------------------------------
- hotshift db 0ah ;Shift combination for TSR
- ; <Alt> <Left shift>
- ; bit key
- ; 0 R Shift
- ; 1 L Shift
- ; 2 Ctrl
- ; 3 Alt
- dos_version dw 0 ;DOS version number
- mouse_flag db 0 ;Mouse driver present
- resident_sp dw 0 ;Resident stack pointer
-
- ems_flag db 0 ;Use expanded memory
- ems_segment dw 0 ;EMS page frame segment
- ems_version db 0 ;Version of EMS manager
-
- ems_handle dw 0 ;EMS handle used
-
- xms_flag db 0 ;Extended memory available
- xms_service dd -1 ;Entry pt for XMS manager
- xms_version db 0 ;Version of XMS manager
-
- indos_ptr dd -1 ;Pointer to INDOS flag
- criterr_ptr dd -1 ;Pointer to DOS crit err flag
-
- int08h dd -1 ;Int 2f vector (Timer)
- int09h dd -1 ;Int 09 vector (Keyboard HW)
- int10h dd -1 ;Int 10 vector (Video BIOS)
- int13h dd -1 ;Int 13 vector (Disk BIOS)
- int16h dd -1 ;Int 16 vector (BIOS Keyboard)
- int28h dd -1 ;Int 28 vector (DOS Idle)
- int2Fh dd -1 ;Int 2F vector (DOS Multiplex)
-
- int08_active db 0 ;Interrupt active flag
- int09_active db 0 ;Interrupt active flag
- int10_active db 0 ;Interrupt active flag
- int13_active db 0 ;Interrupt active flag
- int16_active db 0 ;Interrupt active flag
- int28_active db 0 ;Interrupt active flag
- int2F_active db 0 ;Interrupt active flag
-
- SWNotifyJT dw offset SWNInit ;Jump table used by switcher
- dw offset SWNQSuspend ; notification routine.
- dw offset SWNSuspend
- dw offset SWNActivate
- dw offset SWNActive
- dw offset SWNCSession
- dw offset SWNDSession
- dw offset SWNExit
- ;----------------------------------------------------------------------------
- ;Switcher global data structures
- ;----------------------------------------------------------------------------
- StartupInfo = $
- sisVersion dw 3 ;Switcher structure ID
- sisNextDev dd 0 ;Ptr to prev startup structure
- sisVirtDevFile dd 0 ;Ptr to name of opt dev drvr
- sisReferenceData dd 0 ;Data for Win dev drivr
- sisInstData dd 0 ;Ptr to instance mem list
-
- InstItem1 dd 0 ;Ptr to instance data
- InstSize1 dw 0 ;Size of instance data
- InstItem2 dd 0 ;Ptr to instance stack
- InstSize2 dw 0 ;Size of instance stack
- dd 0 ;Ptr to next block = 0 to
- dw 0 ; terminate list
- ;============================================================================
- ;Instance data
- ;============================================================================
- TSRInstData = $
- ;----------------------------------------------------------------------------
- ;Switcher instance data structures
- ;----------------------------------------------------------------------------
- SWService dd 0 ;Ptr to switcher service rtn
-
- CallbackInfo = $
- scbiNext dd 0 ;Ptr to prev callback struc
- scbiEntryPoint dd 0 ;Ptr to local callback proc
- scbiReserved dd 0 ;Reserved
- scbiAPI dd 0 ;Ptr to info structures
-
- SwapInfo = $
- dw 0 ;Zero swapinfo structure
- dw 0 ; since no API support
- dw 0 ; implimented by the TSR
- dw 0
- dw 0
-
- ;----------------------------------------------------------------------------
- ;DOS State information
- ;----------------------------------------------------------------------------
- saved_dta dd 0 ;saved pointer to curr DTA
- saved_psp dw 0 ;saved segment of curr PSP
- ss_register dw 0 ;SS register
- sp_register dw 0 ;SP register
-
- shift_save db 0 ;Keyboard shift lock state
- A20_state dw 0 ;Saved state of A20 line
-
- mem_alloc dw 0 ;DOS memory allocation strat
- linkflag db 0 ;DOS UMB link flag
-
- curr_disk db 0 ;Default disk at popup
- curr_dir db 64 dup (0) ;Default directory at popup
-
- 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
-
- vector1bh dd 0 ;int 1Bh vector (Break)
- vector23h dd 0 ;int 23h vector (Ctrl-C)
- vector24h dd 0 ;int 24h vector (Crit err)
-
- ;----------------------------------------------------------------------------
- ;TSR State information
- ;----------------------------------------------------------------------------
- popflag db 0 ;Request flag/timer
- main_active db 0 ;TSR active flag
- no_switch dw 0 ;Flag indicating switch OK
- ret_addr dw 0 ;Saved return addr for calls
- win_enhanced db 0 ;Enhanced mode windows flag
- TSRInstDataEnd = $
-
- ;============================================================================
- ; VIDEOINT processes BIOS video services interrupt (Int 10h)
- ;============================================================================
- videoint proc far
- assume cs:code,ds:nothing,es:nothing
- inc cs:int10_active
- pushf
- call cs:[int10h] ;Call old int
- dec cs:int10_active
- iret ;Return
- videoint endp
-
- ;=============================================================================
- ; DISKINT receives control when an interrupt 13h is generated.
- ;=============================================================================
- diskint proc far
- assume cs:code,ds:nothing,es:nothing
- pushf ;save flags register
- inc cs:int13_active ;set disk access flag
- call cs:[int13h]
- pushf ;save flags again
- dec cs:int13_active ;reset disk access flag
- popf ;restore flags
- ret 2 ;exit with flags intact
- diskint endp
-
- ;============================================================================
- ; BIOSKEYINT processes the BIOS keyboard services
- ;============================================================================
- bioskeyint proc far
- assume cs:code,ds:nothing,es:nothing
- pushf ;save flags register
- inc cs:int16_active ;set keyboard active flag
- call cs:[int16h]
- pushf ;save flags again
- dec cs:int16_active ;reset keyborard avtive flag
- popf ;restore flags
- ret 2 ;exit with flags intact
- bioskeyint endp
-
- ;============================================================================
- ; TIMERINT processes timer interrupt (Int 08h)
- ;============================================================================
- timerint proc far
- assume cs:code,ds:nothing,es:nothing
- pushf
- call cs:[int08h] ;Call old int 8
-
- cmp cs:int08_active,0 ;See if we are in this
- jne timerint_exit ; routine already
-
- cmp cs:popflag,0 ;See if we need to try to
- jne timer_check ; pop up
- timerint_exit:
- iret ;Return
- timer_check:
- push ax
- inc cs:int08_active ;Set int active flag
-
- call check_system ;See if system OK to pop up
- or ax,ax
- jne timerint_dec
- call main ;Call the TSR
- mov cs:popflag,1
- timerint_dec:
- dec cs:popflag
- dec cs:int08_active ;Clear int active flag
- pop ax
- jmp short timerint_exit
- timerint endp
-
- ;============================================================================
- ; KEYINT processes keyboard interrupts (Int 09h)
- ;============================================================================
- keyint proc far
- assume cs:code,ds:nothing,es:nothing
- pushf
- call cs:[int09h] ;Call old int 9
-
- push ax
- push ds
- mov ax,40h
- mov ds,ax ;Set ES to bios data segment
- assume ds:bios_data
- mov al,ds:[shift_state]
- and al,0fh ;Mask lock bits
- cmp al,cs:[hotshift]
- pop ds
- pop ax
- je keyint_hotkey
- keyint_exit:
- iret ;Return
- keyint_hotkey:
- mov cs:popflag,POPTIME ;Set timer to pop up
- jmp short keyint_exit
- keyint endp
-
- ;============================================================================
- ; IDLEINT processes DOS Idle interrupt (Int 28h)
- ;============================================================================
- idleint proc far
- assume cs:code,ds:nothing,es:nothing
- pushf
- call cs:[int28h] ;Call old int
-
- cmp cs:int28_active,0 ;See if we are in this
- jne idleint_exit ; routine already
- cmp cs:popflag,0 ;See if we need to try to
- jne idle_check ; pop up
- idleint_exit:
- iret ;Return
- idle_check:
- push ax
- inc cs:int28_active ;Set int active flag
- call check_system ;See if OK to pop up. Ignore
- or al,al ; INDOS since in idle.
- jne idleint_exit1
- mov cs:popflag,0 ;Clear popup flag
- call main ;Call the TSR
- idleint_exit1:
- dec cs:int28_active ;Clear int active flag
- pop ax
- jmp short idleint_exit
- idleint endp
-
- ;============================================================================
- ; MUXINT processes the DOS Multiplex interrupt
- ;============================================================================
- muxint proc far
- assume cs:code,ds:nothing,es:nothing
-
- cmp ax,1605h ;See if Windows start
- je init_win
- cmp ax,4b05h ;See if switcher get instance
- je init_instance ; data.
- cmp ax,4b01h ;See if switcher build chain
- je chain_init
- muxint_jmp:
- jmp cs:[int2fh] ;Call old int
- close_win:
- test dx,01h ;See if enhanced mode Windows
- jne muxint_jmp
- dec cs:win_enhanced ;Clear enhanced mode flag
- jmp short muxint_jmp
- init_win:
- test dx,01h ;See if enhanced mode Windows
- jne init_instance
- inc cs:win_enhanced
- init_instance:
- pushf
- call cs:[int2fh] ;Call old int
- mov word ptr cs:[sisNextDev],bx
- mov word ptr cs:[sisNextDev+2],es
- push cs ;ES:BX point to switcher struc
- pop es
- mov bx,offset StartupInfo
- jmp short muxint_exit
- chain_init:
- pushf
- call cs:[int2fh] ;Call old int
- mov word ptr cs:[scbiNext],bx
- mov word ptr cs:[scbiNext+2],es
- push cs ;ES:BX point to switcher struc
- pop es
- mov bx,offset CallbackInfo
- muxint_exit:
- iret
- muxint endp
-
- ;---------------------------------------------------------------------------
- ; Check System Determines if the system is in a state compatible with TSRs
- ; Exit: CF - Clear if OK to pop up
- ;---------------------------------------------------------------------------
- check_system proc near
- assume cs:code,ds:nothing,es:nothing
- push bx
- push ds
- xor ax,ax
- or al,cs:int10_active ;Check BIOS video int
- or al,cs:int13_active ;Check BIOS disk int
- or al,cs:int16_active ;Check BIOS keyboard int
- lds bx,cs:criterr_ptr ;Check DOS critical error
- or al,byte ptr ds:[bx] ; flag
- lds bx,cs:indos_ptr ;Check INDOS flag
- mov ah,byte ptr ds:[bx]
- check_sys_exit:
- pop ds
- pop bx
- ret
- check_system endp
-
- ;=============================================================================
- ; CRITICALERR receives control when an interrupt 24h is generated.
- ;=============================================================================
- criticalerr proc far
- assume cs:code,ds:nothing,es:nothing
- xor al,al ;Default to ignore
- cmp cs:dos_version,30ah ;See if before DOS 3.1
- jl critical1
- add al,3
- critical1:
- iret
- criticalerr endp
-
- ;=============================================================================
- ; MAIN
- ;=============================================================================
- main proc near
- assume cs:code,ds:nothing,es:nothing
- cli
- inc cs:no_switch ;Don't allow switch
- inc cs:[main_active] ;set program status flag
- mov cs:ss_register,ss ;save SS and SP registers
- mov cs:sp_register,sp
- mov ax,cs ;switch to internal stack
- mov bx,resident_sp
- mov ss,ax
- mov sp,bx
- dec cs:no_switch
- sti ;enable interrupts
- call save_regs ;save all registers
- assume ds:code,es:nothing
- ;-----------------------------------------------------------------------------
- ;Point the interrupt 1Bh, 23h, and 24h vectors to internal handlers.
- ;-----------------------------------------------------------------------------
- mov ax,351bh ;get and save 1Bh vector
- int 21h
- mov word ptr vector1bh,bx
- mov word ptr vector1bh[2],es
- mov ax,251bh ;point interrupt to IRET
- mov dx,offset idleint_exit
- int 21h
-
- mov ax,3523h ;get and save 23h vector
- int 21h
- mov word ptr vector23h,bx
- mov word ptr vector23h[2],es
- mov ax,2523h ;Set to IRET
- mov dx,offset idleint_exit
- int 21h
-
- mov ax,3524h ;get and save 24h vector
- int 21h
- mov word ptr vector24h,bx
- mov word ptr vector24h[2],es
- mov ax,2524h ;point interrupt to internal
- mov dx,offset criticalerr ; critical error handler
- int 21h
- ;-----------------------------------------------------------------------------
- ;Save and switch to internal PSP
- ;-----------------------------------------------------------------------------
- mov ah,51h ;Get current PSP
- call dospspcall ;Beware DOS 2.0 - 3.0
- mov saved_psp,bx ;save it
- push cs
- pop bx
- mov ah,50h ;Set internal PSP
- call dospspcall
- ;-----------------------------------------------------------------------------
- ;Save and switch to internal DTA
- ;-----------------------------------------------------------------------------
- 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,offset command_tail ;use PSP for DTA
- mov ah,1ah ;Set DTA
- int 21h
- ;-----------------------------------------------------------------------------
- ;If DOS 3.x, save extended error information.
- ;-----------------------------------------------------------------------------
- cmp word ptr dos_version,030ah
- jb skip_err_save
- push ds ;save DS
- xor ax,ax ;Clear regs
- mov bx,ax
- mov cx,ax
- mov dx,ax
- mov di,ax
- mov si,ax
- 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
- skip_err_save:
- ;-----------------------------------------------------------------------------
- ;If using EMS memory, save EMS mapping context and map our page.
- ;-----------------------------------------------------------------------------
- cmp ems_flag,0
- je skip_ems_save
- mov ah,47h ;Save mapping context
- mov dx,ems_handle
- int 67h
- or ah,ah
- jne clean_up
- xor ax,ax
- mov bx,ax
- call map_emsmem ;Map page
- jne clean_up
- skip_ems_save:
- ;-----------------------------------------------------------------------------
- ;Save default directory and drive
- ;-----------------------------------------------------------------------------
- mov ah,19h ;Get current disk
- int 21h
- mov curr_disk,al
- mov ah,47h ;Get current directory
- xor dl,dl
- mov si,offset curr_dir
- int 21h
- ;-----------------------------------------------------------------------------
- ;Save state of A20 line.
- ;-----------------------------------------------------------------------------
- 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:
- ;-----------------------------------------------------------------------------
- ;Save UMB link and mem allocaton state. If DOS 5, link UMBs
- ;-----------------------------------------------------------------------------
- mov ax,5800h ;Get DOS mem alloc strategy
- int 21h
- mov mem_alloc,ax
- cmp dos_version,500h ;If DOS 5, save UMB link
- jb skip_umblink ; state. Then link UMBs
- mov ax,5802h
- int 21h
- mov linkflag,al ;Save UMB link state
- mov ax,5803h
- mov bx,1 ;Link UMBs
- int 21h
- skip_umblink:
- ;-----------------------------------------------------------------------------
- ;Save Mouse state
- ;-----------------------------------------------------------------------------
- cmp mouse_flag,0
- je skip_mouse_save
- mov ax,17h
- mov dx,offset ResCodeEnd ;Save mouse state
- push cs
- pop es
- int 33h
- skip_mouse_save:
- ;-----------------------------------------------------------------------------
- ;Save Keyboard shift state
- ;-----------------------------------------------------------------------------
- mov ah,2 ;Get keyboard shift state
- int 16h
- mov shift_save,al
-
- ;=============================================================================
- ;Do work here
- ;=============================================================================
- mov ax,0e07h ;Beep the speaker
- int 10h
- work_1:
- mov ah,01 ;See if key available
- int 16h
- jne work_2
- call TSR_idle ;Indicate TSR idle
- jmp short work_1
- work_2:
- xor ah,ah
- int 16h
- cmp al,27 ;See if <Esc> key
- jne work_1 ;No, continue to wait
-
- mov ax,0e07h ;Beep the speaker again
- int 10h
-
- ;-----------------------------------------------------------------------------
- ;Clean up DOS for return to forground task.
- ;-----------------------------------------------------------------------------
- clean_up:
- push cs
- pop ds
- assume ds:code,es:nothing
- ;-----------------------------------------------------------------------------
- ;Restore Keyboard shift state
- ;-----------------------------------------------------------------------------
- mov ax,bios_data ;Point ES to BIOS data seg
- mov es,ax
- assume es:bios_data
- mov al,shift_save
- and al,0f0h ;Look only at lock bits
- mov es:[shift_state],al
- push cs
- pop es
- assume es:code
- ;-----------------------------------------------------------------------------
- ;Restore Mouse state
- ;-----------------------------------------------------------------------------
- cmp mouse_flag,0
- je skip_mouse_restore
- mov ax,17h
- mov dx,offset ResCodeEnd ;Restore mouse state
- int 33h
- skip_mouse_restore:
- ;-----------------------------------------------------------------------------
- ;Restore UMB link state, link and allocation strat
- ;-----------------------------------------------------------------------------
- mov ax,5801h ;Set DOS mem alloc strategy
- mov bx,mem_alloc
- int 21h
-
- cmp dos_version,500h ;If DOS 5, restore UMB link
- jb skip_umblink_restore ; state.
- mov ax,5803h ;Set UMB link state
- xor bh,bh
- mov bl,linkflag
- int 21h
- skip_umblink_restore:
- ;-----------------------------------------------------------------------------
- ;Restore A20 line
- ;-----------------------------------------------------------------------------
- cmp xms_flag,0
- je skip_xms_restore
- 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
- mov A20_state,ax
- skip_xms_restore:
- ;-----------------------------------------------------------------------------
- ;If using EMS memory, restore EMS mapping context.
- ;-----------------------------------------------------------------------------
- cmp ems_flag,0
- je ems_restore_skip
- mov ah,48h ;Restore mapping context
- mov dx,ems_handle
- int 67h
- ems_restore_skip:
- ;-----------------------------------------------------------------------------
- ;Restore default directory and drive
- ;-----------------------------------------------------------------------------
- mov ah,0eh ;Set default disk
- mov dl,curr_disk
- int 21h
- mov ah,3bh ;Set current directory
- mov dx,offset curr_dir
- int 21h
- ;-----------------------------------------------------------------------------
- ;Restore extended error info.
- ;-----------------------------------------------------------------------------
- cmp word ptr dos_version,30ah ;DOS 3.1 and up
- jb skip_err_restore
- mov ax,5d0ah ;Restore ext error info
- mov dx,offset errinfoarray ;point to Saved info
- int 21h
- skip_err_restore:
- ;-----------------------------------------------------------------------------
- ;Restore PSP and DTA
- ;-----------------------------------------------------------------------------
- mov bx,saved_psp ;Get old PSP
- mov ah,50h ;Restore PSP
- call dospspcall
- push ds
- lds dx,[saved_dta]
- mov ah,1ah ;Restore DTA
- int 21h
- ;-----------------------------------------------------------------------------
- ;Reset the displaced interrupt 1Bh, 23h, and 24h vectors.
- ;-----------------------------------------------------------------------------
- mov ax,2524h ;reset int 24h vector
- lds dx,cs:[vector24h]
- int 21h
- mov ax,2523h ;reset int 24h vector
- lds dx,cs:[vector23h]
- int 21h
- mov ax,251bh ;reset int 1Bh vector
- lds dx,cs:[vector1bh]
- int 21h
- pop ds
- ;-----------------------------------------------------------------------------
- ;Restore register values, switch back to original stack, and return to caller.
- ;-----------------------------------------------------------------------------
- main_exit:
- call restore_regs ;Restore registers
- assume ds:nothing
- cli ;make sure interrupts are off
- inc cs:no_switch ;Don't allow task switch
- mov ss,cs:ss_register ;switch to original stack
- mov sp,cs:sp_register
- dec cs:[main_active] ;clear program status flag
- dec cs:no_switch ;Allow task switch
- sti ;interrupts on
- ret ;Return to interrupt routine
- main endp
-
- ;-----------------------------------------------------------------------------
- ; DOSPSPCALL modifies critical error flag on PSP calls to DOS is using 2.x
- ;-----------------------------------------------------------------------------
- dospspcall proc near
- assume cs:code
- cmp cs:[dos_version],30Ah ;See if DOS < 3.1
- jae dospspcall_ok ;no, just call DOS
- push ds
- push di
- lds di,cs:criterr_ptr ;retrieve crit err flag adr
- inc byte ptr [di] ;Set DOS in crit error state
- pop di
- pop ds
- int 21h ;Call DOS
- push ds
- push di
- lds di,cs:criterr_ptr ;retrieve crit err flag adr
- dec byte ptr [di] ;Set DOS in crit error state
- pop di
- pop ds
- ret
- dospspcall_ok:
- int 21h ;Call DOS
- ret
- dospspcall endp
-
- ;-----------------------------------------------------------------------------
- ; STOP SWITCH Signals the task switcher (if active) to not switch this
- ; session.
- ;-----------------------------------------------------------------------------
- stop_switch proc near
- assume cs:code
- inc cs:no_switch ;Set no switch flag for TS
- cmp win_enhanced,0
- jne stop_switch_1
- stop_switch_exit:
- ret
- stop_switch_1:
- mov ax,1681h ;Win begin critical section
- int 2fh
- jmp short stop_switch_exit
- stop_switch endp
-
- ;-----------------------------------------------------------------------------
- ; GO SWITCH Signals the task switcher (if active) it is OK to switch this
- ; session.
- ;-----------------------------------------------------------------------------
- go_switch proc near
- assume cs:code
- dec cs:no_switch ;Clear switch flag for TS
- cmp win_enhanced,0
- jne go_switch_1
- go_switch_exit:
- ret
- go_switch_1:
- mov ax,1682h ;Win end critical section
- int 2fh
- jmp short go_switch_exit
- go_switch endp
-
- ;-----------------------------------------------------------------------------
- ; TSR IDLE Signals the system that the TSR is idle.
- ;-----------------------------------------------------------------------------
- TSR_idle proc near
- assume cs:code
- int 28h ;Old DOS Idle
- cmp dos_version,300h ;No Multiplex interrupt for
- jb TSR_Idle_exit ; DOS 2.x
- mov ax,1680h ;Win-OS/2 release timeslice.
- int 2fh
- TSR_idle_exit:
- ret
- TSR_idle endp
-
- ;============================================================================
- ; SWNOTIFY Routine to parse switcher notification messages
- ;============================================================================
- SWNotify proc far
- assume cs:code,ds:nothing,es:nothing
- push si
- push ds
- push cs
- pop ds
- assume ds:code
- mov word ptr [SWService],di ;Save ptr to service rtn
- mov word ptr [SWService+2],es
- cmp ax,7
- ja SWN1 ;If unknown type, skip
- mov si,ax
- shl si,1
- call [SWNotifyJT+si] ;Call proper notification func
- mov ax,0
- SWN1:
- pop ds
- pop si
- ret
-
- ;---------------------------------------------------------------------------
- ; SWINIT - Switcher initialization notification
- ;---------------------------------------------------------------------------
- SWNInit proc near
- assume cs:code,ds:code
- mov ax,0 ;Allow switcher init
- ret
- SWNInit endp
- ;---------------------------------------------------------------------------
- ; SWQSUSPENDINIT - Switcher query suspend notification
- ;---------------------------------------------------------------------------
- SWNQSuspend proc near
- assume cs:code,ds:code
- mov ax,no_switch ;Switch only if not in
- ret ; critical section
- SWNQSuspend endp
- ;---------------------------------------------------------------------------
- ; SWSUSPEND - Switcher suspend notification
- ;---------------------------------------------------------------------------
- SWNSuspend proc near
- assume cs:code,ds:code
- mov ax,no_switch ;Switch only if not in
- ret ; critical section
- SWNSuspend endp
- ;---------------------------------------------------------------------------
- ; SWACTIVATE - Switcher going active notification
- ;---------------------------------------------------------------------------
- SWNActivate proc near
- assume cs:code,ds:code
- mov ax,0 ;Allow session activate
- ret
- SWNActivate endp
- ;---------------------------------------------------------------------------
- ; SWACTIVE - Switcher session active notification
- ;---------------------------------------------------------------------------
- SWNActive proc near
- assume cs:code,ds:code
- mov ax,0 ;Allow session activate
- ret
- SWNActive endp
- ;---------------------------------------------------------------------------
- ; SWCSESSION - Switcher create session notification
- ;---------------------------------------------------------------------------
- SWNCSession proc near
- assume cs:code,ds:code
- mov ax,0 ;Allow session create
- ret
- SWNCSession endp
- ;---------------------------------------------------------------------------
- ; SWDSESSION - Switcher destroy session notification
- ;---------------------------------------------------------------------------
- SWNDSession proc near
- assume cs:code,ds:code
- mov ax,0 ;Allow session destroy
- ret
- SWNDSession endp
-
- ;---------------------------------------------------------------------------
- ; SWEXIT - Switcher exit notification
- ;---------------------------------------------------------------------------
- SWNExit proc near
- assume cs:code,ds:code
- mov ax,0 ;Allow switcher exit
- ret
- SWNExit endp
- SWNotify endp
-
- ;-----------------------------------------------------------------------------
- ; GETEMSMEM Allocates pages of memory from the Expanded memory manager
- ; Entry: BX - number of 16K pages to request
- ; Exit: DX - handle to pages
- ; ZF - Set if call successful
- ;-----------------------------------------------------------------------------
- get_emsmem proc near
- mov ah,43h ;Allocate EMS pages
- int 67h
- or ah,ah
- ret
- get_emsmem endp
-
- ;-----------------------------------------------------------------------------
- ; FREEEMSMEM Frees pages of memory from the Expanded memory manager
- ; Entry: DX - handle to memory pages to free
- ; Exit: ZF - Set if call successful
- ;-----------------------------------------------------------------------------
- free_emsmem proc near
- mov ah,45h ;Free EMS page
- int 67h
- or ah,ah
- ret
- free_emsmem endp
-
- ;-----------------------------------------------------------------------------
- ; MAPEMSMEM Maps a page of Expanded memory to the EMS page frame
- ; Entry: AL - Physical page in page frame
- ; BX - logical page to map
- ; DX - handle to memory pages
- ; Exit: ZF - Set if call successful
- ;-----------------------------------------------------------------------------
- map_emsmem proc near
- mov ah,44h ;Map EMS page
- int 67h
- or ah,ah
- ret
- map_emsmem 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 to
- push ax ;save all registers
- push bx
- push cx
- push dx
- push bp
- push si
- push di
- push ds
- push es
- 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
-
- ;=============================================================================
- ; End of resident code. Resident stack and mouse save area sits just
- ; above resident code
- ;=============================================================================
- ResCodeEnd = $
- ;=============================================================================
- ; Non-Resident data
- ;=============================================================================
-
- errmsg1 db 13,10,"Usage: TEMPLATE [/U][/X][/E]$"
- errmsg2 db "Bad switch$"
- errmsg3 db "Expanded memory driver not found$"
- errmsg4 db "DOS 2.0 or greater required$"
- errmsg5 db "Not able to uninstall$"
- errmsg6 db "TEMPLATE not installed$"
-
- infomsg1 db "TEMPLATE installed$"
- infomsg2 db "TEMPLATE removed$"
-
- errmsg8 db "Program uninstalled$"
- errmsg9 db "Can't install$"
-
- installed_seg dw 0 ;Segment of installed code
- TSRResident db 0 ;TSR already installed flag
- def_disk db ? ;Default disk drive
- ems_header db "EMMXXXX0" ;EMS driver header
- mouse_savesize dw 0 ;Size of mouse save area
-
- cmd_switches db "eu" ;Letters of valid commands.
- cmd_switch_end = $
- cmd_jmptbl dw offset remove ;Jump table to rouines that
- dw offset use_expanded ; impliment the cmd line args
-
- ;=============================================================================
- ; INITIALIZE
- ;=============================================================================
- initialize proc near
- assume cs:code, ds:code
- cld ;String operations UP
- mov dx,offset program ;Print copyright
- call message
- ;-----------------------------------------------------------------------------
- ;Get DOS version, Determine if TSR already installed.
- ;-----------------------------------------------------------------------------
- mov ah,30h ;Get DOS version
- int 21h
- xchg al,ah ;Put version in proper order
- mov dos_version,ax ;Save DOS version
- cmp ax,200h ;See if at least DOS ver 2
- ja init_0
- mov dx,offset errmsg4
- jmp short error_exit
- init_0:
- call find_copy ;See if TSR already installed
- jc init_1
- inc TSRResident ;Set already installed flag
- mov installed_seg,es ;save installed code segment
- init_1:
- push cs
- pop es
- ;-----------------------------------------------------------------------------
- ;Parse the command line for switches.
- ;-----------------------------------------------------------------------------
- mov di,offset command_tail ;Point SI to command line text
- xor cx,cx
- or cl,[di] ;Get length of command line.
- jz init_3 ;If 0, skip parse
- inc di
- init_2:
- mov al,"/" ;Put switch in AL
- repne scasb ;Scan for cmd line switches
- jne init_3
- mov al,[di]
- or al,20h ;Make lower case
- push cx
- push di
- mov di,offset cmd_switches
- mov cx,offset cmd_switch_end - offset cmd_switches
- repne scasb
- mov bx,cx ;Copy index into list
- pop di
- pop cx
- mov dx,offset errmsg2 ;Command not found msg
- jne error_exit
- shl bx,1 ;Convert to word offset
- push cx
- push di
- call cs:[bx+cmd_jmptbl] ;Call command routine.
- pop di
- pop cx
- jc error_exit ;If error terminate parse.
- jcxz init_3 ;If at file end, exit parse.
- jmp short init_2
- init_3:
- ;-----------------------------------------------------------------------------
- ;If not installed, install.
- ;-----------------------------------------------------------------------------
- cmp TSRResident,0 ;Is TSR installed?
- je install
- mov ax,4c00h ;No, terminate with RC = 0.
- int 21h
-
- ;=============================================================================
- ;Display error message and exit with Return Code = 1.
- ;=============================================================================
- error_exit: call message
- mov es,installed_seg ;point ES to installed code
- dec es:[main_active] ;enable background task.
- mov ax,4c01h ;Exit RC = 1
- int 21h
-
- ;=============================================================================
- ;Install. Get address of INDOS and DOS Critical Error flags.
- ;=============================================================================
- install:
- mov ah,34h ;Get INDOS address from DOS
- int 21h
- mov word ptr [indos_ptr],bx
- mov word ptr [indos_ptr+2],es
- call find_cefptr ;Find critical error flag
- jnc ceffound
- mov dx,offset errmsg9 ;Critical error flag not found
- jmp short error_exit
- ceffound:
- mov word ptr criterr_ptr,bx ;store it
- mov word ptr criterr_ptr[2],es
- ;-----------------------------------------------------------------------------
- ;Initialize task switcher structures. See if task switcher active.
- ;-----------------------------------------------------------------------------
- cmp word ptr dos_version,300h ;DOS 3.0 and up
- jb nowin
-
- mov ax,offset TSRInstData ;Init instance memory struc
- mov word ptr [InstItem1],ax
- mov word ptr [InstItem1+2],cs
- mov ax,offset TSRInstDataEnd - offset TSRInstData
- mov [InstSize1],ax
-
- mov ax,offset ResCodeEnd ;Init instance stack struc
- mov word ptr [InstItem2],ax
- mov word ptr [InstItem2+2],cs
- mov ax,RESSTACKSIZE
- mov [InstSize2],ax
-
- mov ax,offset InstItem1 ;Init ptr to instance
- mov word ptr [sisInstData],ax ; memory structure.
- mov word ptr [sisInstData+2],cs
-
- mov ax,offset SWNotify ;Init ptr to
- mov word ptr [scbiEntryPoint],ax ; notification
- mov word ptr [scbiEntryPoint+2],cs ; routine.
-
- mov ax,4b02h ;See if switcher active
- int 2fh ;Use multiplex interrupt
- or ax,ax
- jne noswitcher
- mov word ptr [SWService],di ;Save ptr to service routine
- mov word ptr [SWService+2],es
-
- mov ax,4 ;Hook notification chain
- push cs ;ES:BX point to callback struc
- pop es
- mov di,offset CallbackInfo
- call SWService
- noswitcher:
- ;-----------------------------------------------------------------------------
- ;Check for Windows active
- ;-----------------------------------------------------------------------------
- mov ax,1600h ;See if Enhanced mode windows
- int 2fh
- or al,al
- je nowin
- inc win_enhanced ;Set enhanced mode flag
- nowin:
- ;-----------------------------------------------------------------------------
- ;Determine if extended memory manager active
- ;-----------------------------------------------------------------------------
- mov ax,4300h ;Look for HIMEM.SYS
- int 2fh
- or al,al
- jne noxms
- 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
- inc xms_flag
- noxms:
- ;-----------------------------------------------------------------------------
- ;Set up EMS memory if necessary.
- ;-----------------------------------------------------------------------------
- cmp ems_flag,0 ;See if expanded memory
- je no_emsmem ; requested
-
- call check4ems ;See if EMS driver installed
- jnc install_1
- mov dx,offset errmsg3 ;EMS driver error
- jmp error_exit
- install_1:
- mov ems_segment,bx ;Save seg of EMS page frame
- mov ems_version,dl ;Save EMS version
-
- mov bx,1 ;Allocate 1 page
- call get_emsmem
- mov ems_handle,dx ;Save EMS handle
-
- xor al,al ;Map to EMS page 0
- xor bx,bx
- call map_emsmem
- no_emsmem:
- ;-----------------------------------------------------------------------------
- ;See if mouse driver loaded
- ;-----------------------------------------------------------------------------
- xor ax,ax
- int 33h
- or ax,ax
- je no_mouse
- inc mouse_flag ;Set mouse found flag, get
- mov ax,15h ; size of mouse driver save
- int 33h ; context area.
- mov mouse_savesize,bx
- no_mouse:
- ;-----------------------------------------------------------------------------
- ;Set interrupts used by TSR
- ;-----------------------------------------------------------------------------
- mov al,08h ;Get/set the timer interrupt
- mov dx,offset timerint
- mov di,offset int08h
- call set_interrupt
- mov al,09h ;Get/set the keyboard int
- mov dx,offset keyint
- mov di,offset int09h
- call set_interrupt
- mov al,10h ;Get/set the video interrupt
- mov dx,offset videoint
- mov di,offset int10h
- call set_interrupt
- mov al,13h ;Get/set the disk interrupt
- mov dx,offset diskint
- mov di,offset int13h
- call set_interrupt
- mov al,16h ;Get/set the BIOS keyboard int
- mov dx,offset bioskeyint
- mov di,offset int16h
- call set_interrupt
- mov al,28h ;Get/set the DOS idle int
- mov dx,offset idleint
- mov di,offset int28h
- call set_interrupt
-
- cmp dos_version,300h ;DOS 3.0 and up
- jb skip_hook2f
- mov al,2fh ;Get/set the DOS multiplex int
- mov dx,offset muxint
- mov di,offset int2fh
- call set_interrupt
- skip_hook2f:
- ;-----------------------------------------------------------------------------
- ;Deallocate the program's environment block.
- ;-----------------------------------------------------------------------------
- mov ax,ds:[2ch] ;get environment segment
- mov es,ax
- mov ah,49h ;free it
- int 21h
- mov dx,offset infomsg1 ;Tell user that we are
- call message ; installed.
-
- mov ax,3100h ;terminate with ERRORLEVEL = 0
- mov dx,offset ResCodeEnd-offset code + RESSTACKSIZE
- add dx,mouse_savesize
- mov resident_sp,dx
- add dx,15
- mov cl,4
- shr dx,cl
- int 21h
- initialize endp
-
- ;-----------------------------------------------------------------------------
- ; USE EXPANDED Sets a flag to use expanded memory
- ;-----------------------------------------------------------------------------
- use_expanded proc near
- mov ems_flag,1
- ret
- use_expanded endp
-
- ;-----------------------------------------------------------------------------
- ; REMOVE deallocates the memory block addressed by ES and restores the
- ; interrupt vectors displaced on installation.
- ; Exit: CF clear - program uninstalled
- ; CF set - can't uninstall
- ;-----------------------------------------------------------------------------
- remove proc near
- assume cs:code,ds:code
-
- cmp TSRResident,0 ;See if TSR installed
- jne remove_1
- mov dx,offset errmsg6
- jmp remove_error1
- remove_1:
- mov es,installed_seg
- mov ax,5 ;Unhook notification chain
- mov di,offset CallbackInfo
- cmp word ptr es:[SWService+2],0
- je remove_2
- call es:[SWService]
- remove_2:
- mov al,8 ;check interrupt 8 vector
- call checkvector
- jne jmp_remove_error
- mov al,9 ;check interrupt 9 vector
- call checkvector
- jne jmp_remove_error
- mov al,10h ;check interrupt 10 vector
- call checkvector
- jne jmp_remove_error
- mov al,13h ;check interrupt 13h vector
- call checkvector
- jne jmp_remove_error
- mov al,16h ;check interrupt 16 vector
- call checkvector
- jne jmp_remove_error
- mov al,28h ;check interrupt 28h vector
- call checkvector
- je remove_3
- jmp_remove_error:
- jmp remove_error
- remove_3:
- cmp dos_version,300h ;DOS 3.0 and up
- jb skip_check2f
- mov al,2Fh ;check interrupt 2Fh vector
- call checkvector
- jne remove_error
- skip_check2f:
- cmp ems_flag,0 ;If using Expanded memory
- je skip_remove_ems ; free it
- mov dx,ems_handle ;Free Expanded memory
- call free_emsmem
- jne remove_error
- skip_remove_ems:
- push ds ;save DS
- assume ds:nothing
- mov ax,2508h ;restore interrupt 8 vector
- lds dx,es:[int08h]
- int 21h
- mov ax,2509h ;restore interrupt 9 vector
- lds dx,es:[int09h]
- int 21h
- mov ax,2510h ;restore interrupt 10 vector
- lds dx,es:[int10h]
- int 21h
- mov ax,2513h ;restore interrupt 13h vector
- lds dx,es:[int13h]
- int 21h
- mov ax,2516h ;restore interrupt 16 vector
- lds dx,es:[int16h]
- int 21h
- mov ax,2528h ;restore interrupt 28h vector
- lds dx,es:[int28h]
- int 21h
-
- cmp cs:dos_version,300h ;DOS 3.0 and up
- jb skip_restore2f
- mov ax,252Fh ;restore interrupt 2Fh vector
- lds dx,es:[int2Fh]
- int 21h
- skip_restore2f:
- pop ds ;Restore DS
- assume ds:code
- not word ptr es:[begin] ;Destroy fingerprint
- mov ah,49h ;Free memory given to
- int 21h ; original program block
- jc remove_error ;branch on error
-
- mov dx,offset infomsg2 ;Indicate program removed
- call message
- clc ;clear CF for exit
- remove_exit:
- ret ;exit with CF intact
- remove_error:
- mov dx,offset errmsg5
- remove_error1: stc
- jmp remove_exit ;Error during remove
- remove endp
-
- ;-----------------------------------------------------------------------------
- ; CHECKVECTOR is called by REMOVE to compare the segment pointed to by an
- ; interrupt vector against a segment value supplied by the caller.
- ; Entry: AL - interrupt number
- ; Exit: ZF clear - segments do not match
- ; ZF set - segments match
- ;-----------------------------------------------------------------------------
- checkvector proc near
- push es
- mov cx,es
- mov ah,35h ;get vector
- int 21h
- mov ax,es ;transfer segment to AX
- cmp ax,cx ;compare
- pop es
- ret
- checkvector endp
-
- ;-----------------------------------------------------------------------------
- ; SETINTERRUPT Get and sets an interrupt
- ; Entry: AL - Interrupt number
- ; DX - Pointer to new interrupt routine
- ; DI - Pointer to storage location for old interrupt vector
- ;-----------------------------------------------------------------------------
- assume cs:code,ds:code,es:nothing
- set_interrupt proc near
- push es
- push ax
- mov ah,35h ;DOS get interrupt
- int 21h
- pop ax
- mov word ptr [di],bx ;Save old vector
- mov word ptr [di+2],es
- mov ah,25h ;DOS set interrupt
- int 21h
- pop es
- ret
- set_interrupt endp
-
- ;-----------------------------------------------------------------------------
- ; FINDCOPY Determines if the TSR is already resident
- ; Exit: CF - Clear if copy found
- ; ES - Segment of installed code (if CF = 0)
- ;-----------------------------------------------------------------------------
- find_copy proc near
- not word ptr [begin] ;initialize fingerprint
- mov bx,0a000h ;Start scan in UMBs
- mov ax,cs ;keep CS value in AX
- find_copy1:
- inc bx ;increment search segment value
- mov es,bx
- cmp ax,bx ;not installed if current
- je find_copy2 ; segment is looped back to
- mov si,offset begin ;search this segment for ASCII
- mov di,si ; fingerprint
- mov cx,16
- repe cmpsb
- jne find_copy1 ;loop back if not found
- clc ;Set copy found flag
- find_copy_exit:
- ret
- find_copy2:
- stc
- jmp short find_copy_exit
- ret
- find_copy endp
- ;-----------------------------------------------------------------------------
- ; GETCEFPtr Returns a pointer to the DOS ErrorMode flag
- ; Exit: CF - Clear if ErrorMode Flag found
- ; ES:BX - Segment:offset of ErrorMode flag
- ;
- ; For versions of DOS before 3.1, search for following code in DOS seg
- ;
- ; 36: 80 3E ???? 00 cmp byte ptr ss:[ErrorMode],0
- ; 75 ?? jne near label
- ; CD 28 int 28h
- ;
- ; For DOS 3.1 and later, ErrorMode sits before InDOS flag
- ;
- ;-----------------------------------------------------------------------------
- find_cefptr proc near
- mov ah,34h ;Get ptr to INDOS
- int 21h ;After DOS 3.1, the CEF is
- dec bx ; documented to be the byte
- cmp dos_version,30ah ; before the INDOS flag
- jnc find_cef_exit
-
- mov ax,3e80h ;CMP opcode
- mov cx,-1 ;Max segment size
- mov di,bx ;Start at INDOS address
- find_cef_1:
- repne scasb ;Scan for CMP
- jcxz find_cef_notfound ;Error if CMP not found
- cmp es:[di],ah ;Check other half of CMP opcode
- jne find_cef_1
- cmp byte ptr es:[di+4],075h ;Check for JNE
- jne find_cef_1
- cmp word ptr es:[di+6],028cdh ; Check for Int 28h call
- jne find_cef_1 ;Resume loop if not found
- find_cef_found:
- inc di
- mov bx,es:[di] ;Get offset of ErrorMode flag
- clc
- find_cef_exit:
- ret
- find_cef_notfound:
- stc
- jmp short find_cef_exit
- find_cefptr endp
-
- ;-----------------------------------------------------------------------------
- ; CHECK4EMS Determines if an Expanded memory driver is loaded.
- ; Exit: BX - Segment of EMS page frame if CF clear
- ; DL - EMS driver version number
- ; CF - Clear if EMS driver found
- ;-----------------------------------------------------------------------------
- check4ems proc near
- push es
- push di
- mov ax,3567h ;Get EMS vector
- int 21h
- mov di,0ah ;Using the segment from the
- mov si,offset ems_header ; 67h vector, look at offset
- mov cx,8 ; 0ah. Compare the next 8
- cld ; bytes with the expected
- repe cmpsb ; EMS header. If they are
- pop di ; the same, EMS driver
- pop es ; found.
- je check4ems_found
- check4ems_error:
- stc ;Set not found flag
- jmp short check4ems_exit
- check4ems_found:
- mov ah,40h ;Check status
- int 67h
- or ah,ah
- jne check4ems_error
- mov ah,41h ;Get page frame segment
- int 67h
- or ah,ah
- jne check4ems_error
- mov ah,47h ;Get EMM version number
- int 67h
- or ah,ah
- jne check4ems_error
- mov dl,al ;Copy version number
- check4ems_exit:
- ret
-
- check4ems endp
-
- ;----------------------------------------------------------------------
- ; MESSAGE Prints a message to screen
- ; Entry: DX - Offset of '$' terminated message
- ;----------------------------------------------------------------------
- crlf$ db 13,10,"$"
-
- message proc near
- assume cs:code,ds:code
-
- mov ah,9 ;Print string
- int 21h
- mov dx,offset crlf$ ;Append carrage return
- mov ah,9
- int 21h
- ret
- message endp
-
-
-
- EndOfCode = $
- code ends
- end begin