PAGE 90,132 ; TITLE ASSGMAIN.SAL - ASSIGN MAIN PROGRAM ;****************** START OF SPECIFICATIONS ***************************** ; MODULE NAME: ASSGMAIN.SAL ; ; DESCRIPTIVE NAME: Reassigns drive specifications. ; ;FUNCTION: This program reassigns the specified drives to a new drive ; identifier. ; ; ENTRY POINT: ENTRY_POINT ; ; INPUT: ; ; ASSIGN [DRIVE] [DELIMITER] [DRIVE] [SW] ; where DRIVE = optional colon ; where DELIMITER = +;=TAB LF SPACE ; where SW = /STATUS or /STA ; ; where: ; /STATUS - reports back to the user ; the currently changed ; drive assignments and the ; new assignment drive ; ; Note: ; If a drive value has not been ; ASSIGN will report back nothing. ; ; UTILITY FUNCTION: ; Instructs DOS to route disk I/O ; for one drive into disk I/O to another ; drive. eg. ; a=c sets a: to c: ; ; EXIT-NORMAL: Assigned drives or reassigned drives ; ; EXIT-ERROR: Any one of the possible parse errors ; ; INTERNAL REFERENCES: ; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.SAL) ; SYSLOADMSG ; SYSDISPMSG ; ; ; EXTERNAL REFERENCES: ; ROUTINES: none ; ; NOTES: ; This module should be processed with the SALUT preprocessor ; with the re-alignment not requested, as: ; ; SALUT ASSPARM,NUL; ; ; To assemble these modules, the sequential ; ordering of segments may be used. ; ; For LINK instructions, refer to the PROLOG of the main module, ; ASSIGN.SAL ; ; REVISION HISTORY: AN000 - Version 4.00: PARSER, System Message Handler, ; Status report ; ; COPYRIGHT: "Microsoft DOS ASSIGN Utility" ; "Version 4.00 (C)Copyright 1988 Microsoft" ; "Licensed Material - Program Property of Microsoft" ; ; ; AN000 -> New Code ; ; AN001 -> PTM P3954 Release the environmental vector and close ; all handles. ; ; AN002 -> PTM P3918 Parse error messages must conform to spec. ; All parse error messages should display ; the offending parameters. ; ; ;****************** END OF SPECIFICATIONS ***************************** ;********************************************* ;* * ;* UTILITY NAME: ASSIGN.COM * ;* * ;* SOURCE FILE NAME: ASSIGN.SAL * ;* * ;* STATUS: ASSIGN utility * ;* PC-DOS Version 3.40 * ;* * ;* SYNTAX (Command line) * ;* * ;* ASSIGN [DRIVE] [DELIMITER] [DRIVE] [SW] * ;* where DRIVE = optional colon * ;* where DELIMITER = +;=TAB LF SPACE * ;* where SW = /STATUS or /STA * ;* * ;* where: * ;* /STATUS - reports back to the user * ;* the currently changed * ;* drive assignments and the * ;* new assignment drive * ;* Note: * ;* If a drive value has not been * ;* ASSIGN will report back nothing. * ;* * ;* UTILITY FUNCTION: * ;* Instructs DOS to route disk I/O * ;* for one drive into disk I/O to another * ;* drive. eg. * ;* a=c sets a: to c: * ;********************************************* page DEBUG = 0 .xlist INCLUDE SYSMSG.INC ;AN000; INCLUDE SYSVAR.INC INCLUDE CURDIR.INC INCLUDE MULT.INC INCLUDE PDB.INC MSG_UTILNAME .list ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = BREAK BREAK MACRO subtitle .XLIST SUBTTL subtitle .LIST PAGE ENDM .xcref break ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = CallOperRange macro low,high,routine ;;NS-macro to call subroutines ?call = low ;;NS-in the given call range ;;NS-starting call value = low # rept (high-low)+1 ;;NS-calculate the entry point CallOper ?call,routine ;;NS-into the table then execute ?call = ?call + 1 ;;NS-increment call value to next endm endm ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = CallOper macro call,routine ;;NS-macro that calls a single ;;NS-subroutine that is used in ;;NS-the above macro loop CallOperange ORG (SysTab-ASSIGN_BASE)+(call*2) ;;NS-Calculate entry point into DW OFFSET CODE:routine ;;NS-code where SysTab is the ENDM ;;NS-entry point to the tables ;;NS-ASSIGN_BASE is at 0:0000 ;;NS-the (call*2) is calculated ;;NS-to take into account two bytes ;;NS-and final OFFSET statement points ;;NS-code to be executed at the given ;;NS-label ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; $SALUT (0,36,40,48) MyINT21 macro ;;NS-macro used to save pushf ;;NS-the flags to maintain call system ;;NS-DOS environment endm ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = SaveReg MACRO reglist ;; push those registers IRP reg, ?stackdepth = ?stackdepth + 1 PUSH reg ENDM ENDM .xcref SaveReg ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = RestoreReg MACRO reglist ;; pop those registers IRP reg, ?stackdepth = ?stackdepth - 1 POP reg ENDM ENDM .xcref RestoreReg ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = page BREAK ; $SALUT (0,23,28,41) ; DOS FUNCTIONS USED ; (DEC) (HEX) NO_ERROR equ 0 ;return code zero from the parser ;********** CNS ***************** ;Std_Con_String_Output EQU 9 ; 9 PSP_Env equ 2ch ;Environmental vector segment in PSP ;an001; dms; Get_PSP equ 62h ; DOS function call to get PSP address ;an001; dms; Handle_Close equ 3eh ;close handle ;an001; dms; Set_Default_Drive EQU 14 ; E Get_Default_Drive EQU 25 ; 19 Set_Interrupt_Vector EQU 37 ; 25 Get_Version EQU 48 ; 30 Keep_Process EQU 49 ; 31 Get_Interrupt_Vector EQU 53 ; 35 Get_Drive_Freespace EQU 54 ; 36 Exit EQU 76 ; 4C Dealloc EQU 73 ; 49 Get_In_Vars EQU 82 ; 52 Get_Set_Media_ID equ 69h ; 69h IOCTL_READ_BLOCK EQU 4404H ;READ FROM BLOCK DEVICE IOCTL_WRITE_BLOCK EQU 4405H ;WRITE TO A BLOCK DEVICE IOCTL_BLOCK_CHANGE EQU 4408H ;BLOCK DEVICE CHANGEABLE IOCTL_BLOCK_REMOTE EQU 4409H ;BLOCK DEVICE REMOTE ; VECTORS REFERENCED PGM_TERM EQU 20H DOS_CALL EQU 21H CTL_BREAK EQU 23H CRIT_ERR EQU 24H ABS_DISK_READ EQU 25H ABS_DISK_WRITE EQU 26H stay equ 27h ;NS stay interrupt value int_IBM EQU 2AH ;critical section maintenance MULTIPLEXOR EQU 2FH ;MULTIPLEXOR INTERRUPT VECTOR NUMBER ; CONSTANTS USED ACROSS THE MULTIPLEXOR INTERFACE MPLEX_ID EQU 06H ;ID OF ASSIGN IN MPLEX CHAIN MPLEX_R_U_THERE EQU 0 ;MPLEX FUNCTION: ARE YOU THERE? MPLEX_GET_SEG EQU 1 ;MPLEX FUNCTION: GET SEG OF INSTALLED ASSIGN MPLEX_INSTALLED EQU 0FFH ;"I AM HERE" RETURN VALUE ; OTHER EQUATES cr equ 0dh ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED f_Interrupt EQU 0000001000000000B ;NS - mask used for interrupt ;NS value BREAK ; $SALUT (4,15,21,41) code segment para public ;NS code all in one segment assume cs:code ; one segment page ASSIGN_BASE: ;NS- starting point of loaded file org 100h ENTRY_POINT: jmp INITIALIZATION ;JUMP TO INITIALIZATION ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = BREAK drives db 1,2,3,4,5,6,7,8,9 ;drive values used in comparison db 10,11,12,13,14,15,16,17,18,19 ;against default or found drive db 20,21,22,23,24,25,26 default_drive db ? drive_save db ? ; saved drive byte drive_address dw ? ; location (from DS) of drive byte drive_save2 db ? ; second saved drive byte ;****************************************************************************** ;****************************************************************************** system dd ? int25_vec dd ? ;NS - Hooks for the Int 2f handler preparation int26_vec dd ? ;NS - Hooks for the Int 2f handler preparation int2F_vec dd ? ;NS - Area to be hooked in and remain resident user_ret dd ? ; ??????????????????????????????????????? saveIntF dw ? ; ??????????????????????????????????????? I21_Func db ? ; Save area for INT21 function requested -->RW ; $SALUT (4,9,23,41) EVEN SysTab label word ;NS-Beginning of the call,subroutine table CallOper 00h,DoReset CallOperRange 01h,0Ch,DoNothing ; done ???????????????????????? CallOper 0Dh,DoReset ; done ???????????????????????? CallOper 0Eh,DoSetDefault CallOperRange 0Fh,17h,DoFCB ; done ???????????????????????? CallOper 18h,DoReset ; done ???????????????????????? CallOper 19h,DoGetDefault ; ???????????????????????? CallOperRange 1Ah,1Bh,DoReset ; done ???????????????????????? CallOper 1Ch,DoDL ; done ???????????????????????? CallOperRange 1Dh,20h,DoReset ; done ???????????????????????? CallOperRange 21h,24h,DoFCB ; done ???????????????????????? CallOperRange 25h,26h,DoReset ; done ???????????????????????? CallOperRange 27h,28h,DoFCB ; done ???????????????????????? CallOperRange 29h,31h,DoReset ; done ???????????????????????? CallOper 32h,DoDL ; done ???????????????????????? CallOperRange 33h,35h,DoReset ; done ???????????????????????? CallOper 36h,DoDL ; done ???????????????????????? CallOperRange 37h,38h,DoReset ; done ???????????????????????? CallOperRange 39h,3Dh,DoAscii ; done ???????????????????????? CallOperRange 3Eh,40h,DoReset ; done ???????????????????????? CallOper 41h,DoAscii ; done ???????????????????????? CallOper 42h,DoReset ; done ???????????????????????? CallOper 43h,DoAscii ; done ???????????????????????? CallOper 44h,DoIOCTL ; done ???????????????????????? CallOperRange 45h,46h,DoReset ; done ???????????????????????? CallOper 47h,DoDL ; done ???????????????????????? CallOperRange 48h,4Ah,DoReset ; done ???????????????????????? CallOper 4Bh,DoExec ; done ???????????????????????? CallOperRange 4Ch,4Dh,DoReset ; done ???????????????????????? CallOper 4Eh,DoAscii ; done ???????????????????????? CallOperRange 4Fh,55h,DoReset ; done ???????????????????????? CallOper 56h,DoRename ; done ???????????????????????? CallOperRange 57h,59h,DoReset ; done ???????????????????????? CallOperRange 5Ah,5Bh,DoAscii ; done ???????????????????????? CallOperRange 5Ch,5Fh,DoReset ; done ???????????????????????? CallOper 60h,DoTranslate ; done ???????????????????????? CallOperRange 61h,63h,DoReset ; done ???????????????????????? CallOperRange 64h,69h,DoSetGetMedia ;done ???????????????????????? CallOperRange 6ah,6bh,DoNothing ;done ???????????????????????? CallOper 6ch,DoAscii_DS_SI ;done ????????????????????????? ; ???????????????????????? page ; $SALUT (4,5,11,36) MAXCLL EQU 6CH ; High bound of table org (systab-ASSIGN_BASE) + (2 * (MAXCLL + 1)) ;NS - Beginning of code starts at ;NS - Beginning of table + 128 bytes BREAK ASSIGN_HANDLER: mov SaveIntf,f_interrupt ;NS- Move in the mask into a saved area SaveReg ;NS- ?????????????????????????????????? cmp ah,MAXCLL ; Do a high bound check on the call ; so we don't index past the end of ja DoNothing ; the table on a bogus call mov al,ah ;NS- Call must be in the 0 - 63h range cbw ;NS- zero out the high byte now ;NS- AX has 0 & call number shl ax,1 ;NS- Double the value in AX mov bx,ax ;NS- Move the value into BX to jmp systab[bx] ;NS- access the call number & subroutine ;NS- bx bytes into the tbl ;*********************************************************************************** EnterAssign: ;NS- make sure system intact by doing call LeaveAllAssign ;NS- error recovery check push ax ;NS- before making code mov ax,8000h + critAssign ;NS- non- reentrant if unable INT INT_IBM ;(2AH) NS- to screen out successfully POP AX ;NS- LeaveAllAssign will be executed RET ;return NS- and the critical section will be reset ;************************************************************************************ LeaveAssign: ;NS- restore re-entrancy to push ax ;NS- the code after & only mov ax,8100h + critAssign ;NS- after this call has been INT INT_IBM ;(2AH) NS- made or the error recovery POP AX ;NS- call has been made RET ;return NS- ;************************************************************************************ LeaveAllAssign: ;NS- Error recovery call push ax ;NS- to restore the Assigns mov ax,8908h ;NS- critical section int INT_IBM ;(2AH) NS- if ASSIGN has encountered pop ax ;NS- a problem on entrance or departure RET ;return NS- ;************************************************************************************ ; ; Reset the exclusion flag ;NS- Reset to Assign ; ;NS- critical section state DoReset: ;NS- call LeaveAllAssign ;NS- ;NS- ;**************************************************************************************** ; ; The system call needed no special processing. Go do it directly. ; DoNothing: ;NS-System registers and flags still RestoreReg ;NS-intact it has not been clobbered jmp system ;NS-by ASSIGN code page ;************************************************************************************ ; ; Munge the drive byte in an FCB pointed to by DS:DX. ; "MUNGE" ? (Webster will turn over in his gravy...) ; DoFCB: mov bx,dx ; indexable pointer mov al,[bx] ; get drive cmp al,0ffh ; extended fcb? jnz DoMapDrive ; no add bx,7 ; yes, advance past it mov al,[bx] ; get read drive byte DoMapDrive: or al,al ; default drive? ; $IF Z ;YES JNZ $$IF1 mov al,default_drive ; get default drive ; ; DS:BX points to the drive byte being munged. AL is the old value. Save ; it away. ; ; $ENDIF ;AC000; $$IF1: ;SaveFCB: call EnterAssign ; NS-Enter Assign's critical section mov drive_save,al ; NS-save the drive assignment call mapdrv1 ; NS-now let's map it to the mov [bx],al ; NS-numeric drive associated in ; NS-in drive range 1 to 26 ;****************************************************************************** ; The FCB has been converted. Now let's POP off the user's info and do the ; system call. Note that we are no longer reentrant! ; mov drive_address,bx ; NS- location of drive value RestoreReg ; get back original registers pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI ; NS- Clear out old interrupts ; NS- before an IRET is issued ; NS- update the current call system ; flags saved => this is a system call pushf ; NS- re-adjust the stack call RestInt ; NS- and setup the environment SaveReg ; NS- with drive and the drive address mov bx,drive_address ; NS- before leaving the Assign critical mov al,drive_save ; NS- section mov [bx],al RestoreReg push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign iret ; back to user page ;************************************************************************************ ; ; Munge the user's ASCIZ string at DS:DX. ; DoAscii: mov bx,dx ; point to area cmp byte ptr [bx+1],':' ; drive letter present? jnz DoNothing ; nope, ignore this ; ; There is a drive leter present. Grab it and convert it ; mov al,[bx] ; get drive letter call EnterAssign ; NS- Re-enter ASSIGN crit section mov drive_save,al ; remember previous contents call maplet ; convert to real drive letter mov [bx],al ; place in new drive letter mov drive_address,bx RestoreReg ; get back original registers pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI ; clean up stack call system ; flags saved => this is a system call pushf ; save all drive info call RestInt ; NS- clean up environment before SaveReg ; NS- returning to the user's environment mov bx,drive_address ; NS- to ask on the next ASSIGN entrance mov al,drive_save mov [bx],al RestoreReg push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign ; NS- exit ASSIGN crit. section iret ; back to user ;************************************************************************************ ; ; Munge the user's ASCIZ string at DS:SI. ; DoAscii_DS_SI: mov bx,si ; point to area cmp byte ptr [bx+1],':' ; drive letter present? ; $if ne ; drive letter not present JE $$IF3 jmp DoNothing ; nope, ignore this ; $endif ; $$IF3: ; ; There is a drive leter present. Grab it and convert it ; mov al,[bx] ; get drive letter call EnterAssign ; NS- Re-enter ASSIGN crit section mov drive_save,al ; remember previous contents call maplet ; convert to real drive letter mov [bx],al ; place in new drive letter mov drive_address,bx RestoreReg ; get back original registers pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI ; clean up stack call system ; flags saved => this is a system call pushf ; save all drive info call RestInt ; NS- clean up environment before SaveReg ; NS- returning to the user's environment mov bx,drive_address ; NS- to ask on the next ASSIGN entrance mov al,drive_save mov [bx],al RestoreReg push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign ; NS- exit ASSIGN crit. section iret ; back to user page ;************************************************************************************ ; ; DoDL - the drive to map is in DL. ; DoDL: or dl,dl ; NS- check for drive mapping ; $IF Z ;AC000;;USE DEFAULT DRIVE JNZ $$IF5 DNJ1: jmp DoNothing ; NS- default drive was requested ; NS- thus no mapping needed ; $ENDIF ;AC000; $$IF5: mov al,dl ; NS- not default case so no need doctor call EnterAssign ; NS- so enter ASSIGN crit. section again mov drive_save,al ; preserve old drive call mapdrv1 mov dl,al ; drive is mapped RestoreReg ; get back registers mov I21_Func,ah ; Save requested function call -->RW pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI call system ; flags saved => this is a system call pushf ; call RestInt cmp I21_Func,GET_DRIVE_FREESPACE ;(36h) If call returns info in DX, -->RW ; NS- DL in both cases Func 36 ; NS- Func 1Ch are both used for ; NS- drive input we don't want to ; NS- the old drives so they should not ; restored as the old value - use ASSIGN's je Dont_Restore_DL ;AC000;;THEN DO CHANGE IT cmp I21_Func,1ch ; If call returns info in DX, -->RW ;(NOTE 1CH IS NOT DEFINED IN SYSCALL.INC. EK) je Dont_Restore_DL ;AC000;;THEN DO CHANGE IT mov dl,drive_save ; restore his dl ;DONT_RESTORE_DL: Dont_Restore_DL: push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign iret ; back to user ;************************************************************************************ ; Map the IOCTL drives in BX ; NS- this section handles ; NS- INT21 calls to get drive info DoIOCTL: RestoreReg SaveReg cmp ax,IOCTL_READ_BLOCK ;(4404h) IOCTL read string from block dev jz DoMapBX ;AC000; ; jz DoMapBX cmp ax,IOCTL_WRITE_BLOCK ;(4405h) IOCTL write string from block dev jz DoMapBX ;AC000; ; jz DoMapBX cmp ax,IOCTL_BLOCK_CHANGE ;(4408h) IOCTL is removable jz DoMapBX ;AC000; ; jz DoMapBX cmp ax,IOCTL_BLOCK_REMOTE ;(4409h) IOCTL block dev redir (network) jnz DNJ2 ;AC000;;NORMAL CALL ;DoMapBX: DoMapBX: or bx,bx ; NS- drive letter associated in BL jz DNJ2 mov al,bl ; not the default case call EnterAssign mov drive_save,al ; remember drive call mapdrv1 ; NS- time to map drive to new assoc. mov bl,al ; drive is mapped RestoreReg ; get back registers (throw away BX) pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI call system ; flags saved => this is a system call pushf call RestInt mov bl,drive_save ; restore his dl push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign iret ; back to user DNJ2: jmp DoNothing DoSetGetMedia: RestoreReg ;an000; dms;restore regs SaveReg ;an000; dms;save regs cmp ah,Get_Set_Media_ID ;an000; dms;trap on get/set media id ; $if z ;an000; dms;found JNZ $$IF7 or bl,bl ;an000; dms;drive letter entered ; $if nz ;an000; dms;yes JZ $$IF8 mov al,bl ; not the default case call EnterAssign mov drive_save,al ; remember drive call mapdrv1 ; NS- time to map drive to new assoc. mov bl,al ; drive is mapped RestoreReg ; get back registers (throw away BX) pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI call system ; flags saved => this is a system call pushf call RestInt mov bl,drive_save ; restore his dl push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign ; $else ;an000; dms;not valid function 69h JMP SHORT $$EN8 $$IF8: jmp DoNothing ;an000; dms;pass to interrupt ; $endif ;an000; dms; $$EN8: ; $else ;an000; dms; JMP SHORT $$EN7 $$IF7: jmp DoNothing ;an000; dms;pass to interrupt ; $endif ;an000; dms; $$EN7: iret ; back to user page ;************************************************************************************ ; ; Map the drive letter and forget about it. EXEC never returns. ; DoExec: RestoreReg SaveReg or al,al ; $IF Z ;AC000;;IS LOAD GO, NOT USE NORMAL STUFF JNZ $$IF13 mov bx,dx ; point to area DoOnce: cmp byte ptr [bx+1],':' ; drive letter present? ; $IF Z ;AC000;;YES JNZ $$IF14 ; ; There is a drive leter present. Grab it and convert it ; mov al,[bx] ; get drive letter call maplet ; convert to real drive letter mov [bx],al ; place in new drive letter ; $ENDIF ;AC000; $$IF14: DNJ3: jmp DoNothing ; restore and go on! ; $ENDIF $$IF13: ;DAJ: jmp DoAscii ;************************************************************************************ ; ; Map the drive letter at DS:SI. We need to un-map it at the end. ; DoTranslate: mov bx,SI ; point to area cmp byte ptr [bx+1],':' ; drive letter present? jnz DNJ3 ; nope, ignore this ; ; There is a drive leter present. Grab it and convert it ; mov al,[bx] ; get drive letter call EnterAssign mov drive_save,al ; remember previous contents call maplet ; convert to real drive letter mov [bx],al ; place in new drive letter mov drive_address,bx RestoreReg ; get back original registers pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI call system ; flags saved => this is a system call pushf call RestInt SaveReg mov bx,drive_address mov al,drive_save mov [bx],al RestoreReg push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign iret ; back to user page ;************************************************************************************ ; ; Munge the user's ASCIZ string at DS:DX and es:di ; DoRename: mov bx,dx ; point to area mov ax,[bx] call EnterAssign mov drive_save,al mov drive_address,bx cmp ah,':' ; drive letter present? ; $IF Z ;AC000; JNZ $$IF17 call maplet ; convert to real drive letter mov [bx],al ; place in new drive letter ; $ENDIF ;AC000; $$IF17: ;DoES: mov ax,es:[di] ;NS- Get the 2nd drive from the command linepSOP mov drive_save2,al ;NS- Save possible drive cmp ah,':' ;NS- exclude if no colon present ; $IF Z ;AC000; JNZ $$IF19 call maplet ;NS- go convert letter to actual drive # mov es:[di],al ;NS- new drive value ; $ENDIF ;AC000; $$IF19: ;DoIt: RestoreReg ; get back original registers pop word ptr user_ret ; restore his IP pop word ptr user_ret+2 ; restore his CS call GotoCLI call system ; flags saved => this is a system call pushf call RestInt SaveReg mov al,drive_save2 ; NS- get the second drive update mov es:[di],al ; NS- on the command line mov bx,drive_address ; mov al,drive_save ; mov [bx],al ; RestoreReg ; push word ptr user_ret+2 ; push back user's cs push word ptr user_ret ; push back user's ip Call LeaveAssign iret ; back to user ;************************************************************************************ ; ; DoGetDefault - return our idea of the current drive... ; DoGetDefault: call Assign_Check ; $IF Z ;AC000; JNZ $$IF21 ;DNJ4: jmp DoNothing ; $ENDIF ;AC000; $$IF21: RestoreReg mov al,default_drive dec al iret page ;************************************************************************************ ; ; DoSetDefault - try to set to the mapped current drive. If we can do it, ; then OK, else oops! ; DoSetDefault: RestoreReg mov al,dl ; get new drive inc al ; convert it to 1-based call EnterAssign mov drive_save,al ; remember what we're doing call mapdrv1 ; convert drive dec al ; convert back to 0-based mov dl,al ; stick back in correct register mov drive_save2,al ; remember more of what we're doing MyInt21 ; try the set push ax ; save return info from set mov ah,Get_Default_Drive ;(29h) MyInt21 mov dl,drive_save dec dl ; Restore users original value cmp al,drive_save2 ; Did the set work? ; $IF Z ;AC000;;YES! JNZ $$IF23 mov al,drive_save mov default_drive,al ; Set ours too, it's valid! ; $ENDIF ;AC000; $$IF23: ;BadDrive: pop ax ; Set return info call LeaveAssign iret ;************************************************************************************ ; ; Maintain the CLI state upon the next IRET. Flags for the IRET are on the ; stack just under the return address. This means saving the current state ; of the int flag and then turning off the saved version. ; GotoCLI: push ax push bp mov bp,sp ; bp ax ret f mov ax,[bp + 2 + 2 + 2] and SaveIntf,ax ; save those interrupts and word ptr [bp + 2 + 2 + 2],not f_interrupt pop bp pop ax ret ; ;************************************************************************************ ; Restore he saved interrupt flag for the user. His flags are on the stack ; just above the RET. ; RestInt: push ax push bp mov bp,sp mov ax,SaveIntf ; bp ax ret f or [bp + 2 + 2 + 2],ax pop bp pop ax ret ;************************************************************************************ mapdrv0: ;a = 0 , b = 1 inc al ; $IF NZ ;AC000; JZ $$IF25 call mapdrv1 ; $ENDIF ;AC000; $$IF25: ;Wrap0: dec al ret ;************************************************************************************ mapdrv1: cmp al,26 ; $IF NA ;AC000; JA $$IF27 cmp al,0 ; check for default ; $IF Z ;AC000; JNZ $$IF28 mov al,default_drive mov drive_save,al ; $ENDIF ;AC000; $$IF28: push bx ;a = 1, b = 2 push cx mov ch,ah cbw mov bx,offset drives-1 add bx,ax mov al,cs:[bx] mov ah,ch pop cx pop bx ; $ENDIF ;AC000; $$IF27: ret ;************************************************************************************ maplet: cmp al,'A' jb LetDone cmp al,'Z' jbe DoMapLet cmp al,'a' jb LetDone cmp al,'z' ja LetDone DoMapLet: or al,20h sub al,"a"-1 call mapdrv1 add al,40h LetDone: ret page ;************************************************************************************ int25: call mapdrv0 jmp int25_vec int26: call mapdrv0 jmp int26_vec int2F: CMP AH,mplex_id ;(06h) is this our multiplex? ; $IF NE ;AC000;;NO JE $$IF31 jmp int2F_vec ; No, Chain to next guy ; $ENDIF ;AC000; $$IF31: ;MINE: CMP AL,mplex_get_seg ;(01h) ;0 AND 1 ARE THE ONLY ALLOWED FUNCTIONS ; $IF NA ;AC000;;IF NOT SOME OTHER NUMBER, JA $$IF33 ; $IF E ;AC000;;IF FUNCTION REQUEST IS 01 JNE $$IF34 ;RETURN THE SEGID IN ES PUSH CS POP ES ; Call 1 gets our segment in ES ; $ENDIF ;AC000; $$IF34: ;QUER: MOV AL,MPLEX_INSTALLED ;(0FFh) I AM here ; $ENDIF $$IF33: ;RESERVED_RET: IRET ;************************************************************************************ assign_check: push si push ax push cx xor ax,ax mov si,ax mov cx,26 ; $SEARCH ;AC000; $$DO37: ;scn: mov al,drives[si] INC SI cmp ax,si ; $EXITIF NZ,NUL ;AC000; JNZ $$SR37 ; $ENDLOOP LOOP ;AC000; LOOP $$DO37 xor ax,ax ; reset z flag ; $ENDSRCH ;AC000; $$SR37: ;scndone: pop cx pop ax pop si ret prog_size = ($-ASSIGN_BASE+15)/16 page ;************************************************************************************ ; TRANSIENT CODE ;************************************************************************************ ;********************************************* ;* * ;* Subroutine name: Initialization * ;* * ;* Purpose: Process the command line. * ;* If there are no errors update * ;* the drive table according to * ;* the drive assignments, terminate * ;* and stay resident. If status switch * ;* set and the drive values have been * ;* altered display drive is set to * ;* 2nd drive. * ;* * ;* Input: Command line (described in header) * ;* * ;* Output: Table will be updated and resident* ;* code will be hooked in. * ;* * ;* Normal Exit: Valid drives, sufficient * ;* memory. * ;* Error Conditions: * ;* Incorrect DOS Version * ;* Invalid Parameter * ;* Invalid switch * ;*Externals: * ;* PROCESS_PATH * ;* REPORT_STATUS * ;* EXIT_PROG * ;* * ;********************************************* ; ***************************************** ; * INITIALIZATION * ; ***************************************** ; * * ; * CALL SYSLOADMSG * ; * Do DOS Versinon Check * ; * CALL SYSDISPMSG * ; * IF <> X.X then * ; * Display message * ; * Message number 1 * ; * (001 - Incorrect DOS Version) * ; * exit * ; * .ENDIF * ; * Continue * ; * * ; * Establish address of the * ; * PDB environment * ; * (Process Data Block ) * ; * .IF NO SPACE free de-allocate (49)* ; * memory at the environment * ; * address * ; * .ENDIF * ; ***************************************** ;******************************************************************************* BREAK EXTRN SYSPARSE:NEAR ;AN000; ODDX equ 01H ;AN000; EVENX equ 00H ;AN000; PAD_CHAR equ ' ' ;AN000; SEMICOLON equ ';' ;AN000; SPACE equ ' ' ;AN000; EQUAL equ '=' ;AN000; PLUS equ '+' ;AN000; good_parse_finish equ 0ffffh ;an000; ;****************************************************************************** STATUS_ONLY db 0 ;AN000; STRING_CTR db 0 ;AN000; STATUS_FLAG db 0 ;AN000; ERR_CODE db 0 ;AN000; POS_FLAG db 'n' ;AN000; PARMS_AVAIL db 'n' ;AN000; PAR_RETC dw 0 ;AN000; used for the return code DRV_X db 0 ;AN000; from the parser save_dr_tbl_ptr dw ? ;an000;drive table pointer curr_es_seg dw ? Parm_Ptr1 dw ? ;an002;ptr to parse parm Parm_Ptr2 dw ? ;an002;ptr to parse parm inv dd ? STring dd ? ;AN000;string holder INCLUDE ASSGPARM.INC ;AN000; INCLUDE ASSGMSG.INC ;AN000; assume cs:code, ds:code, ss:code, es:code INITIALIZATION: push ax ;an000; save ax mov ax,ds ;an000; get the current ds mov SEG_1,ax ;an000; set sublist table mov SEG_2,ax ;an000; set sublist table pop ax ;an000; restore ax call SYSLOADMSG ;AN000; ;does DOS version check ; $IF C ;AN000; JNC $$IF41 ;remainder of info given call SYSDISPMSG ;AN000; ;by the msg retriever ;message and exit call EXIT_PROG ;AC000; ;(4CH) Terminate function ; $ENDIF $$IF41: page ;************************************* CNS ************************************ ; ***************************************** ; * INITIALIZATION * ; ***************************************** ; * * ; * Make internal DOS function call (52h)* ; * to process the data block * ; * information after mem is available * ; ****************************************** ;************************************* CNS ************************************ ;OKDOS: mov ax,ds:[pdb_environ] ;get your Process Data Block Address or ax,ax ;check to see if space available ; $IF NZ ;AC000; JZ $$IF43 ; jz nofree push es ; save code segment value mov es,ax ; de-allocate memory mov ah,dealloc ;(49H) int DOS_CALL pop es ;restore code segment value ; $ENDIF ;ACx00; $$IF43: ;nofree: push es ;an000; save es mov ah,Get_In_Vars ;(52H) int DOS_CALL mov Word ptr inv,bx mov Word ptr inv+2,es pop es ;an000; restore es ;****************************************************************************** ; ; ***************************************** ; * Establish addressability * ; * to command line parms (DS:SI) * ; * Establish addressability to PARM * ; * control block (ES:DI) * ; * * ; ***************************************** ;******************************************************************************* ;parser es & ds now points at the command line cld ;clear the directional flag ;decrement mode - maintanis pointer without ;advancement mov di,offset ASS_PARMS ;AC000; ;set index to the location of your PARAMETER ;PARSER control block mov si,81h ;AC000; ;set index to the beginning of the commandline ;at 81h to the first 128 bytes page ;****************************************************************************** ;* PROCESS PATH ;****************************************************************************** ;********************************************* ;* * ;* Subroutine : Process_path * ;* Function : Process command line. * ;* Repeat searching for drive * ;* spec. If valid update * ;* drive table. * ;* * ;* Normal exit: End of line * ;* Parse error * ;* * ;* Abort exit: Invalid drive * ;* * ;********************************************* ; ***************************************** ; * * ; * WHILE PAR_RETC eq NO_ERROR (0) * ; * CALL SYSPARSE * ; * Case: * ; * .IF (POSITIONAL) * ; * Result is positional & Ctr even * ; * INC CTR * ; * CHECK_STRING * ; * .IF the string is valid * ; * valid drive * ; * calculate table drv posit. * ; * based on the ascii value * ; * .ELSE * ; * * ; * PARSE ERROR * ; * .ENDIF * ; * Result is positional & CTR odd * ; * save the ascii_value * ; * Check the String * ; * .IF the string is valid * ; * valid drive * ; * update the drive table * ; * .ELSE * ; * * ; * PARSE ERROR * ; * .ENDIF * ; * .ENDIF * ; * INC CTR * ; ***************************************** ;****************************************************************************** xor cx,cx ;an000; set cx to 0 for parse xor dx,dx ;an000; set dx to 0 for parse mov Parm_Ptr1,si ;an002; dms;ptr to 1st. parm mov Parm_Ptr2,si ;an002; dms;ptr to 1st. parm call SYSPARSE ;AN000; dms;priming parse mov par_retc,ax ;AN000; dms;set flag ; $DO $$DO45: CMP ax,no_error ;AN000;Is compare the return ; $LEAVE NE ;AN000;code 0 no error keep JNE $$EN45 ;AN000;parsing call CHK_PARSER ;AN000; mov Parm_Ptr2,si ;an002; dms;ptr to 1st. parm call SYSPARSE ;AN000;go parse the command line mov par_retc,ax ;AN000; dms;set flag ;AN000;restore the parm return code ; $ENDDO ;AN000; JMP SHORT $$DO45 $$EN45: cmp ax,good_parse_finish ;an000; dms;see if a parse error ; $if ne ;an000; dms;if a parse error JE $$IF48 push ax ;an002; dms save ax mov ax,Parm_Ptr2 ;an002; dms;get original parm ptr mov Parm_Ptr1,ax ;an002; dms;place in variable pop ax ;an002; dms;restore ax call PARSE_ERR ;an000; dms;display error & exit ; $endif ;an000; dms; $$IF48: cmp PARMS_AVAIL,'y' ;AN000; ; $IF E ;AN000; If there are parms available JNE $$IF50 cmp ax,0 ;AN000; see if the return code was no error ; $IF G ;AN000; if greater than 0 JNG $$IF51 mov ax,parse10 call PARSE_ERR ;AN000; you got a parser error ;AN000; so report & exit ; $ENDIF ;AN000; you also get an error $$IF51: xor ax,ax ;AN000; mov al,String_ctr ;AN000; mov bx,0002h div bl ;AN000; cmp ah,EVENX ; $IF NE ;AN000; if the drives did not pair off JE $$IF53 mov ax,parse10 call PARSE_ERR ; $ENDIF ;AN000; $$IF53: cmp POS_FLAG,'n' ;AN000;has a drive been specified ; $IF E,AND ;AN000;and has a switch also been JNE $$IF55 cmp STATUS_FLAG,1 ;AN000;specified if so hook in code ; $IF E ;AN000;and then report status JNE $$IF55 mov STATUS_ONLY,1 ;AN000;set flag specifing user input full ; $ENDIF ;AN000;command line $$IF55: ;AN000; hook in the code ; $ENDIF ;AN000; $$IF50: page cmp STATUS_ONLY,0 ;AN000; ; $IF E ;AN000; JNE $$IF58 call Get_Vectors ;get current vectors ;an001; dms; call Set_Vectors ;set new vectors ;an001; dms; ; $ELSE ;AN000;END of HOOK-IN JMP SHORT $$EN58 $$IF58: call REPORT_STATUS ;AN000; call EXIT_PROG ;AN000; ; $ENDIF $$EN58: page ;*********************************** CNS *************************************** RELOAD_CURDIR PROC NEAR ;***************************************************************************** ; ; We have an interesting problem here. What if the user is assigning away ; his current drive? Here's the solution: ; ; o We get the current drive here. ; o We reload the mapping table. ; o We set the current drive. ; MOV AH,Get_Default_Drive ;(19H) INT DOS_CALL PUSH AX ; save away the table MOV AX,(MPLEX_ID SHL 8)+MPLEX_GET_SEG ;(0601H) Get the SEG of the installed ASSIGN INT MULTIPLEXOR ;(2FH) in ES mov si,offset drives ;move in the new drive table mov di,si mov cx,26 ; move a-z CLI rep movsb ; STI POP DX ; restore the old current drive MOV AH,Set_Default_Drive ;(0EH) INT DOS_CALL call EXIT_PROG ;go_home: INT PGM_TERM ;(20H) Exit SHOULD not return, but be safe ret RELOAD_CURDIR ENDP ;*********************************** CNS *************************************** ;Input: Parser control block ;Output: Result Parser control block ;Register usage: AX,BX,CX,DX,ES,DS,SI,DI ; ; ;*********************************** CNS *************************************** CHK_PARSER PROC NEAR xor cx,cx ;an000; clear out cx xor ax,ax ;AN000; clear out ax mov al,String_ctr ;AN000; grab current assign ctr mov bx,0002h ;an000; set bx to 2 div bl ;AN000; divide so we get rem. cmp RES_TYPE,2 ;an000; check for 1st drive ; $IF E,AND ;AN000; drive letter? JNE $$IF61 cmp ah,EVENX ;AN000; and no remainder? ; $IF E ;AN000; JNE $$IF61 inc STRING_CTR ;AN000; increment counter mov PARMS_AVAIL,'y' ;AN000; signal parms entered push ax ;AN000; save ax mov al,res_itag ;AN000; grab parm entered mov drv_x,al ;AN000; save it for later use call drvchk ;AC000; check for valid drive cbw ;AC000; convert drive byte found to a word mov bx,offset drives-1 ;AC000; get the drive table add bx,ax ;AC000; get the drive address mov save_dr_tbl_ptr,bx ;an000; save the drive table pointer pop ax ;an000; restore ax ; $ENDIF ;AN000; $$IF61: cmp RES_TYPE,2 ;AN000; check for 2nd drive ; $IF E,AND ;AN000; drive entered? JNE $$IF63 cmp ah,EVENX ;AN000; and not first? ; $IF NE ;AN000; JE $$IF63 inc STRING_CTR ;AN000; increment counter mov PARMS_AVAIL,'y' ;AN000; signal parms entered push ax ;AN000; save ax mov al,res_itag ;AN000; grab parm entered mov drv_x,al ;AN000; save it for later use call drvchk ;AC000; if so see if it was valid mov bx,save_dr_tbl_ptr ;an000; set bx to drive table mov [bx],al ;AC000; if valid update the table mov POS_FLAG,'y' ;AN000; yes you have valid positionals pop ax ;an000; restore ax mov Parm_Ptr1,si ;an002; dms;ptr to 1st. parm ; $ENDIF ;AN000; $$IF63: cmp RES_SYN,0 ;AN000; See if a switch was specified ; $IF NE ;AN000; If so, JE $$IF65 mov STATUS_flag,1 ;AN000; set the status flag on mov PARMS_AVAIL,'y' ;AN000; and report that a valid parameter mov byte ptr SW_Syn1,20h ;an000; remove switch from list mov byte ptr SW_Syn2,20h ;an000; remove switch from list mov Parm_Ptr1,si ;an002; dms;ptr to 1st. parm ; $ENDIF ;AN000; was on the command line $$IF65: ret ;AN000; CHK_PARSER ENDP page ;*********************************** CNS *************************************** ; ; check drive validity ; drvchk: sub al,"A" ; NS- error checking ; $IF NB ;AN000; ;if alphabetic, JB $$IF67 push es push bx push ax les bx,inv cmp al,es:[bx].sysi_ncds ;AN000; ;NS- check in case current directory ; $IF NAE ;AN000; ;NS- has been altered JAE $$IF68 les bx,es:[bx].sysi_cds push bx mov bl,size curdir_list mul bl pop bx add bx,ax test es:[bx].curdir_flags,curdir_inuse ; $IF NZ ;AC000; JZ $$IF69 pop ax pop bx pop es inc al ret ; $ENDIF ;AC000; curdir in use? $$IF69: ; $ENDIF ;AC000; curdir been altered? $$IF68: ; $ENDIF ;AC000; alphabetic? $$IF67: mov ax,parse10 ;AN000; Invalid parameter call PARSE_ERR ;an000; display the error & end ;******************************* CNS ******************************************* ;Purpose: Print the mapping status of the drive table. ;Input : Drive table ;Registers affected: BX,CX,DX,AX ; ;Output : Display of all drive values stored not equal to their sequential ; storage address ; ;******************************* CNS ******************************************* REPORT_STATUS PROC NEAR push es ;an000; save es push es ;an000; swap es with pop ax ;an000; ax mov curr_es_seg,ax ;an000; save es in curr_es_seg mov ax,0601h ;an000; our int 2fh int 2fh ;an000; returns segment of drive vector assume es:nothing ;an000; tell the linker mov cl,01 ;AN000; ;initialize the counter ;AN000; advance to next drive mov bx,offset drives ;AN000; load drive table ; $DO $$DO73: cmp cl,26 ;AN000; see if we scanned all drives ; $LEAVE A ;AN000; exit loop if we have JA $$EN73 cmp cl,es:[bx] ;AN000; ;compare the table value ;to the table contents ; $IF NE ;AN000; JE $$IF75 push bx ;an000; save bx - we stomp it push cx ;an000; save cx - we stomp it mov al,es:[bx] ;AN000; get the table contents to convert push es ;an000; save es for print mov bx,curr_es_seg ;an000; get the current segment mov es,bx ;an000; get the segment into es assume es:code ;an000; tell linker it is code add cl,40H ;AN000; convert to ascii representation add al,40h ;an000; convert to ascii mov OLD_DRV,cl ;AN000; place in parms for printing mov NEW_DRV,al ;AN000; by message retriever mov ax,0002h ;an000; message #2 mov bx,stdout ;an000; print to standard out mov cx,0002h ;an000; two replaceable parms mov si,offset sublist1 ;an000; offset of sublist mov di,0000h ;an000; no buffer for user input mov dl,no_input ;AN000; no user input to mes. ret. mov dh,utility_msg_class ;an000; utility messages only call SYSDISPMSG ;AN000; ;go to message retriever pop es ;an000; restore es assume es:nothing ;an000; tell the linker pop cx ;an000; restore cx pop bx ;an000; restore bx ; $ENDIF ;AN000; $$IF75: inc bx ;an000; next drive in vector inc cl ;AN000; next letter to address ; $ENDDO ;AN000; JMP SHORT $$DO73 $$EN73: pop es ;an000; restore es assume es:code ;an000; tell the linker ret ;AN000; REPORT_STATUS ENDP page ;******************************* CNS ******************************************* ; Purpose: Exit program ; Input : Error code AL ; Output : Error code AL ; ;******************************* CNS ******************************************* EXIT_PROG PROC NEAR mov ah,EXIT ;AC000;(4ch) RETURN TO DOS WITH ERRORLEVEL int DOS_CALL ;AC000; ret ;AC000; EXIT_PROG ENDP ;******************************* CNS ******************************************* ;========================================================================= ; PARSE_ERR : This routine prints out the applicable parse ; error that is returned in AX by SYSPARSE. ; ; Inputs : AX - Parse error number to be printed ; Outputs : Applicable parse error ;========================================================================= PARSE_ERR proc near ;an000; dms;report an error push ax ;an000;save ax mov byte ptr ds:[si],0 ;an002;null terminate string mov dx,Parm_Ptr1 ;an002;move ptr to sublist mov Parse_Sub_Off,dx ;an002; mov Parse_Sub_Seg,ds ;an002; mov bx,STDERR ;an000;print to standard out mov cx,1 ;an002;1 replaceable parm mov si,offset Parse_Sublist ;an002;sublist for replaceable parm mov dl,NO_INPUT ;AN000;no input to message retriever mov dh,PARSE_ERR_CLASS ;AN000;display parse errors call SYSDISPMSG ;AN000;display error pop ax ;AN000;restore errcode call EXIT_PROG ;AN000;exit ASSIGN due to error PARSE_ERR endp ;an000; dms; Release_Environment proc near ;an001; dms; push ax ;save regs ;an001; dms; push bx ; ;an001; dms; push es ; ;an001; dms; mov ah,Get_PSP ; get the PSP segment ;an001; dms; int 21h ; invoke INT 21h ;an001; dms; mov es,bx ; BX contains PSP segment - put in ES ;an001; dms; mov bx,word ptr es:[PSP_Env]; get segment of environmental vector ;an001; dms; mov es,bx ; place segment in ES for Free Memory ;an001; dms; mov ah,Dealloc ; Free Allocated Memory ;an001; dms; int 21h ; invoke INT 21h ;an001; dms; pop es ; restore regs ;an001; dms; pop bx ; ;an001; dms; pop ax ; ;an001; dms; ret ; return to caller ;an001; dms; Release_Environment endp Close_Handles proc near ;close handles 0-4 ;an001; dms; push bx ;save regs ;an001; dms; mov bx,4 ;close all standard files ;an001; dms; Close_Handle_Loop: mov ah,Handle_Close ;close file handle ;an001; dms; int 21h ; ;an001; dms; dec bx ;next handle ;an001; dms; jns Close_Handle_Loop ;continue ;an001; dms; pop bx ;restore regs ;an001; dms; ret ; ;an001; dms; Close_Handles endp ; ;an001; dms; Get_Vectors proc near ;get original vectors ;an001; dms; mov ax,(GET_INTERRUPT_VECTOR SHL 8)+ABS_DISK_READ ;(3525h) get the int 25 vector int DOS_CALL mov word ptr [int25_vec],bx mov word ptr [int25_vec+2],es mov ax,(GET_INTERRUPT_VECTOR SHL 8)+ABS_DISK_WRITE ;(3526H) get the int 26 vector int DOS_CALL mov word ptr [int26_vec],bx mov word ptr [int26_vec+2],es mov ax,(GET_INTERRUPT_VECTOR SHL 8)+MULTIPLEXOR ;(352FH) get the int 2F vector int DOS_CALL mov word ptr [int2F_vec],bx mov word ptr [int2F_vec+2],es mov ax,(Get_Interrupt_Vector SHL 8)+DOS_CALL ;(3521H) int DOS_CALL mov word ptr cs:[system],bx mov word ptr cs:[system+2],es MOV AX,(MPLEX_ID SHL 8)+MPLEX_R_U_THERE ;(0600H) See if we are in system already INT MULTIPLEXOR ;(2FH) OR AL,AL ; $IF NZ ;AC000; NOT INSTALLED JZ $$IF78 call RELOAD_CURDIR ;AC000; ; $ENDIF $$IF78: ret ; ;an001; dms; Get_Vectors endp ; ;an001; dms; Set_Vectors proc near ;set to new vectors ;an001; dms; mov ah,Get_Default_Drive ;(19H) int DOS_CALL inc al mov [default_drive],al ;NS- add one to the value to get the call mapdrv1 ;NS- actual drive value before mapping dec al ;NS- dec one to setup for select function mov dl,al ;select its replacement mov ah,Set_Default_Drive ;(0EH) int DOS_CALL ;NS- Set up hooks mov dx,offset int25 ;set int 25 vector mov ax,(SET_INTERRUPT_VECTOR SHL 8) + ABS_DISK_READ ;(2525H) int DOS_CALL ;NS- setup new seg mov dx,offset int26 ;set int 26 vector mov ax,(SET_INTERRUPT_VECTOR SHL 8) + ABS_DISK_WRITE ;(2526H) int DOS_CALL ;NS- Hook in resident portion mov dx,offset int2F ;set int 2F vector mov ax,(SET_INTERRUPT_VECTOR SHL 8) + MULTIPLEXOR ;(252FH) int DOS_CALL mov dx,offset ASSIGN_HANDLER ;set the system int vector mov ax,(SET_INTERRUPT_VECTOR SHL 8) + DOS_CALL ;(2521H) int DOS_CALL call Close_Handles ;close handles 0-4 ;an001; dms; call Release_Environment ;release the environmental vector ;an001; dms; mov dx,prog_size ;end but stay resident mov ah,KEEP_PROCESS ;(31h) NS- ASSIGN loaded in mem int DOS_CALL ret ; ;an001; dms; Set_Vectors endp ; ;an001; dms; .xlist MSG_SERVICES msg_services msg_services msg_services msg_services msg_services .list include msgdcl.inc code ends end ENTRY_POINT