;----------------------------------------------------------------------- ; Alternate Multiplex Interrup Specification Library ; AMIS.ASM Public Domain 1992 Ralf Brown ; You may do with this software whatever you want, but ; common courtesy dictates that you not remove my name ; from it. ; ; Version 0.80 ; LastEdit: 4/19/92 ;----------------------------------------------------------------------- INCLUDE AMIS.MAC ;----------------------------------------------------------------------- _TEXT SEGMENT PUBLIC BYTE 'CODE' ASSUME CS:_TEXT ;----------------------------------------------------------------------- resident_seg dw 0 ; location of TSR code after relocation alloc_strat dw 0 link_state db 0 ; are UMBs part of memory chain? ;----------------------------------------------------------------------- ; Call the XMS driver ; ; entry: all registers as needed for XMS call ; exit: registers as returned by XMS driver ; ZF set if successful, ZF clear if failure ; XMS proc near db 09Ah ; FAR CALL xms_entry dd 0 ; XMS driver's entry point cmp ax,1 ret XMS endp ;----------------------------------------------------------------------- ; Determine entry point of XMS driver and initialize procedure XMS to call ; that entry point ; ; exit: CF set if no XMS driver or other failure ; CF clear if initialization successful ; get_XMS_entry proc near push es mov ax,352Fh int 21h ; find out whether INT 2F is valid mov ax,es or ax,bx ; don't try XMS if INT 2F is NULL jz no_XMS_driver ; (could be case under DOS 2.x) mov ax,4300h ; see if XMS is installed int 2Fh cmp al,80h ; did XMS respond? jnz no_XMS_driver mov ax,4310h ; if XMS present, get its entry point int 2Fh mov word ptr xms_entry,bx mov word ptr xms_entry+2,es ; and store entry point for call pop es clc ret no_XMS_driver: pop es stc ret get_XMS_entry endp ;----------------------------------------------------------------------- ; entry: nothing ; exit: CF set if not available, clear if available ; AX,BX,CX,DX destroyed ; if available, DOS5 UMBs have been linked into the memory chain ; check_if_DOS5_UMBs proc near mov ax,5800h int 21h ; get current allocation strategy mov alloc_strat,ax ; and remember it for later restore mov ax,5802h ; get current state of UMB linkage int 21h mov link_state,al mov ax,3000h ; get DOS version int 21h cmp al,5 ; DOS 5.0 or higher? jb no_DOS5_UMBs cmp al,10 ; but make sure not OS/2 penalty box jae no_DOS5_UMBs mov ax,2B01h mov cx,4445h mov dx,5351h int 21h ; check if DESQview running cmp al,0FFh ; if yes, no UMB's to be allocated jne no_DOS5_UMBs mov ax,5803h mov bx,1 ; try to link in UMBs int 21h mov ax,5802h ; get new link state int 21h cmp al,1 jne no_DOS5_UMBs clc ; yes, we have UMBs ret no_DOS5_UMBs: stc ret check_if_DOS5_UMBs endp ;----------------------------------------------------------------------- ; entry: DS:SI -> hooked interrupt list ; exit: AX, BX, CX, DX destroyed ; CF set if unable to unhook all vectors ; CF clear if successful ; public unhook_interrupts unhook_interrupts proc DIST push es push ds push di push si cld chk_unhook_loop: lodsb mov dx,[si] ; get offset of interrupt handler inc si ; and skip that field in the hook inc si ; list cmp al,2Dh je all_unhookable mov ah,35h int 21h ; get interrupt vector mov ax,es mov cx,ds cmp ax,cx ; check segment agains of vectors jne chk_isp_loop cmp dx,bx ; check offset of vector against ours je chk_unhook_loop ; this int is unhookable if same chk_isp_loop: cmp word ptr es:[bx],10EBh ; handler starts with JMP SHORT $+12 ? jne not_unhookable cmp word ptr es:[bx+6],424Bh ; valid signature? jne not_unhookable cmp byte ptr es:[bx+9],0EBh ; hardware reset must also be JMP SHORT jne not_unhookable cmp cx,word ptr es:[bx+4] ; check segment of next ptr against ours jne chk_next_isp cmp dx,word ptr es:[bx+2] ; check offset of next ptr against ours je chk_unhook_loop ; this int is unhookable if same chk_next_isp: les bx,es:[bx+2] ; advance to next ISP header jmp chk_isp_loop ; and test it not_unhookable: stc unhook_ints_done: pop di pop si pop ds pop es ret all_unhookable: pop si ; get back start of hook list push si ; and preserve SI for return unhook_loop: lodsb mov dx,[si] inc si inc si push ds push ax mov ah,35h int 21h ; get interrupt vector mov ax,es mov cx,ds cmp ax,cx ; check segments of vectors jne isp_loop cmp dx,bx ; check offsets of vectors jne isp_loop lds dx,[bx+2] ; get our old_int?? pointer pop ax push ax mov ah,25h ; set interrupt vector int 21h jmp short unhooked_interrupt isp_next: les bx,es:[bx+2] ; advance to next ISP header isp_loop: ; ; no need to check for a valid ISP header, as we already know all chains reach ; our header before non-ISP code ; cmp cx,es:[bx+4] ; check segment of 'previous' ptr jne isp_next cmp dx,es:[bx+2] ; check offset of 'previous' ptr jne isp_next xchg bx,dx lds bx,[bx+2] xchg bx,dx ; ES:BX -> previous ISP ; DS:DX -> next ISP mov es:[bx+2],dx ; prev->next = curr->next mov es:[bx+4],ds ; thus, we are now unhooked unhooked_interrupt: pop ax pop ds cmp al,2Dh jne unhook_loop clc ; indicate success jmp unhook_ints_done unhook_interrupts endp ;----------------------------------------------------------------------- ; entry: AX = segment of TSR code within the calling executable ; exit: CF clear if successful ; CF set on error ; public _AMIS_uninstall _AMIS_uninstall proc DIST push bp mov bp,sp ifidni , @mpx_number = byte ptr [bp+6] ELSE @mpx_number = byte ptr [bp+4] ENDIF ; ; first, see whether the TSR can uninstall itself ; mov ah,@mpx_number mov al,2 mov dx,cs ; load return address for success mov bx,offset _TEXT:uninstall_successful int 2Dh cmp al,0FFh ; successful? je uninstall_successful cmp al,02h ; unsupp, unsucc, or unable to remove? jbe uninstall_done cmp al,05h ; unknown return code? jae uninstall_failed ; ; TSR said it is safe to uninstall, but not able to do so itself, ; so now we unhook its interrupts and free its memory ; mov resident_seg,bx ; remember which memory block to free mov ah,@mpx_number mov al,4 mov bl,0 ; start with INT 00h int 2Dh cmp al,1 ; function unsupported or can't determine? jbe uninstall_failed cmp al,4 jne uninstall_failed ; sorry, can't handle returns 02h/03h yet go_uninstall: push ds push si mov ds,dx ; DS:SI -> hook list mov si,bx call unhook_interrupts pop si pop ds jc uninstall_failed cmp resident_seg,0B000h ; regular DOS memblk if below video jae uninstall_highmem mov es,resident_seg mov ah,49h ; free memory block int 21h uninstall_successful: mov al,0FFh ; indicate success jmp short uninstall_done uninstall_failed: mov al,1 ; status = unsuccessful uninstall_done: mov ah,0 ; return AX=uninstall status code pop bp ret uninstall_highmem: call check_if_DOS5_UMBs ; check if UMBs, and link them in jc uninstall_XMS mov es,resident_seg ; free the memory block mov ah,49h int 21h restore_link_state: mov ax,5801h mov bx,alloc_strat ; restore allocation strategy int 21h mov ax,5803h ; and restore UMB link status mov bh,0 mov bl,link_state int 21h jmp uninstall_successful uninstall_XMS: call get_XMS_entry jc uninstall_failed ; no XMS driver!?!?! mov ah,11h ; release UMB mov dx,resident_seg call XMS jne uninstall_failed ; we deallocation successful? jmp uninstall_successful _AMIS_uninstall endp ;----------------------------------------------------------------------- _TEXT ENDS END