; This is the source code for the replacement INT 21 handler EXTEND.PAS. ; This code is designed to be compiled by the TASM assembler and linked into ; the Pascal code. ; ; This code was based upon earlier work by Randy Forgaard, Bela Lubkin and ; Kim Kokkonen. The previous implementation was based on using the same ; technique only not using an interrupt handler. See EXTEND.DOC for more ; information. ; ; To compile with TASM: ; TASM EXTEND ; ; Scott Bussinger ; Professional Practice Systems ; 110 South 131st ; Tacoma, WA 98444 ; (206)531-8944 ; Compuserve [72247,2671] ; COMMENT ~ ** Revision History ** 1 EXTEND.ASM 9-Mar-89,`SCOTT' First version using TLIB -- Based on 3.2 2 EXTEND.ASM 19-Nov-90,`SCOTT' Modified documentation to be less confusing ** Revision History ** ~ PUBLIC ExtendInit,ExtendHandler DSEG SEGMENT WORD PUBLIC EXTRN OldInt21:DWORD ; Address of old INT 21 handler EXTRN PrefixSeg:WORD ; Segment address of Pascal program's PSP DSEG ENDS CSEG SEGMENT WORD PUBLIC ASSUME CS:CSEG, DS:DSEG ; CS relative Data Storage HandleTable DD ? ; Pointer to standard handle table in PSP IntVector DD ? ; Provide CS relative storage for old INT 21 vector SaveFunction DB ? ; Save DOS function number SaveHandle DB ? ; Save original handle SaveLastDCB DB ? ; Save original handle slot ; Initialize a few CS relative variables ExtendInit PROC NEAR LES AX,[OldInt21] ; Get the original INT 21 vector into CS relative storage MOV WORD PTR CS:[IntVector],AX MOV WORD PTR CS:[IntVector+2],ES MOV WORD PTR CS:[HandleTable],0018H ; Create a pointer to handle table in PSP MOV AX,[PrefixSeg] MOV WORD PTR CS:[HandleTable+2],AX RET ExtendInit ENDP ; Main replacement for INT 21 handler ExtendHandler PROC FAR PUSH BP ; Save BP MOV BP,SP ; Make sure this call is from our program MOV BP,[BP+4] ; BP = caller's CS CMP BP,WORD PTR CS:[HandleTable+2] ; Is the caller's CS < our PSP address JB IgnoreExtend CMP BP,DSEG ; Is the caller's CS < our data segment JAE IgnoreExtend POP BP ; Restore BP CMP AH,4BH ; Skip the rest of this if an EXEC function JNE NotEXEC IgnoreExtend: POP BP ; Restore BP JMP CS:[IntVector] ; Go to original handler NotEXEC: CMP AH,46H ; Function $46 is only partially supported JNE ValidFunction CMP CL,4 ; Permit FORCEDUP if it's a standard handle JBE ValidFunction NotSupported: MOV AX,6 ; Tell the user it's an invalid handle STC ; Signal an error JMP ReturnToTurbo ValidFunction: PUSH DS ; Set up pointer to handle table PUSH CX PUSH DI LDS DI,CS:[HandleTable] MOV CL,[DI+19] ; Remember contents of last handle slot MOV CS:[SaveLastDCB],CL MOV CS:[SaveFunction],AH ; Save function code for later CMP AH,3EH ; Check for DOS functions that pass a handle JB CallOldInt21 CMP AH,40H ; Convert functions $3E..$40 (Close,Read,Write) JBE ConvertDCB CMP AH,42H ; Convert function $42 (Seek) JE ConvertDCB CMP AH,44H ; Convert function $44..$46 (IOCTL,DUP,FORCEDUP) JB CallOldInt21 CMP AH,46H JBE ConvertDCB CMP AH,57H ; Convert function $57 (File time/date) JE ConvertDCB CMP AH,5CH ; Convert function $5C (Lock/Unlock) JE ConvertDCB CMP AH,68H ; Convert function $68 (Commit File) JNE CallOldInt21 ConvertDCB: MOV CS:[SaveHandle],BL ; Save the original handle CMP BL,4 ; Check for output to standard handle JBE CallOldInt21 ; Let calls with standard handle pass through SUB BL,5 ; Account for an offset of 5 in DCB number MOV [DI+19],BL ; Stuff DCB into last handle slot MOV BL,19 ; Use number of last handle slot CallOldInt21: POP DI ; Restore the registers POP CX POP DS PUSHF CALL CS:[IntVector] ; Fake an INT21 to original handler STI ; Allow interrupts PUSH DS ; Setup pointer to handle table PUSH DI PUSH BX LDS DI,CS:[HandleTable] ; Check if INT handler returned an error JC Done ; Possibly needs to goto CheckForHandle?? MOV BL,CS:[SaveFunction] ; Check for return handles CMP BL,3CH ; Convert function $3C (Create) JE ConvertHandle CMP BL,3DH ; Convert function $3D (Open) JE ConvertHandle CMP BL,45H ; Convert function $45 (Dup) JE ConvertHandle CMP BL,5AH ; Convert function $5A (Create unique) JE ConvertHandle CMP BL,5BH ; Convert function $5B (Create new) JE ConvertHandle CMP BL,68H ; Convert function $68 (Commit file) JNE CheckForHandle ConvertHandle: MOV BX,AX ; Use handle as offset into handle table MOV AL,0FFH ; Show the handle as unused XCHG AL,[DI+BX] ; Return DCB as handle number ADD AL,5 ; Use offset of 5 to avoid standard handles CheckForHandle: MOV BL,CS:[SaveFunction] ; Check for handles left in registers CMP BL,3FH ; Convert function $3F (Read) JE RestoreHandle CMP BL,40H ; Convert function $40 (Write) JE RestoreHandle CMP BL,42H ; Convert function $42 (Seek) JE RestoreHandle CMP BL,44H ; Convert function $44..$46 (IOCTL,DUP,FORCEDUP) JB Success CMP BL,46H JBE RestoreHandle CMP BL,57H ; Convert function $57 (File time/date) JE RestoreHandle CMP BL,5CH ; Convert function $5C (Lock/Unlock) JNE Success RestoreHandle: POP BX MOV BL,CS:[SaveHandle] ; Restore original handle in case calling PUSH BX ; program assumes BX unchanged Success: CLC ; Everything is fine so clear error flag Done: MOV BL,CS:[SaveLastDCB] ; Restore contents of last handle slot MOV [DI+19],BL POP BX POP DI POP DS ReturnToTurbo: RET 2 ; Return to the calling program and cleanup stack ExtendHandler ENDP CSEG ENDS END