From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM | 1771 ++++++++++++++++++++++++++++++++++++++ v4.0/src/CMD/ASSIGN/ASSGMSG.INC | 74 ++ v4.0/src/CMD/ASSIGN/ASSGPARM.ASM | 141 +++ v4.0/src/CMD/ASSIGN/ASSGPARM.INC | 242 ++++++ v4.0/src/CMD/ASSIGN/ASSIGN.SKL | 9 + v4.0/src/CMD/ASSIGN/MAKEFILE | 43 + 6 files changed, 2280 insertions(+) create mode 100644 v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM create mode 100644 v4.0/src/CMD/ASSIGN/ASSGMSG.INC create mode 100644 v4.0/src/CMD/ASSIGN/ASSGPARM.ASM create mode 100644 v4.0/src/CMD/ASSIGN/ASSGPARM.INC create mode 100644 v4.0/src/CMD/ASSIGN/ASSIGN.SKL create mode 100644 v4.0/src/CMD/ASSIGN/MAKEFILE (limited to 'v4.0/src/CMD/ASSIGN') diff --git a/v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM b/v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM new file mode 100644 index 0000000..5561366 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM @@ -0,0 +1,1771 @@ + + + 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 + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGMSG.INC b/v4.0/src/CMD/ASSIGN/ASSGMSG.INC new file mode 100644 index 0000000..65b7d72 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGMSG.INC @@ -0,0 +1,74 @@ +BADDOS equ 1 +STAT equ 2 +PARSE01 equ 01 +PARSE02 equ 02 +PARSE03 equ 03 +PARSE04 equ 04 +PARSE05 equ 05 +PARSE06 equ 06 +PARSE07 equ 07 +PARSE08 equ 08 +PARSE09 equ 09 +PARSE10 equ 10 + +OLD_DRV db 0,0 +NEW_DRV db 0,0 + +FLAG1 equ LEFT_ALIGN+CHAR_FIELD_ASCIIZ + +;****************************************************************************** +; VALUES FOR THE MSG_DESC CONTROL BLOCK +ONE_SUBS EQU 1 ;ONE VARIABLE FIELD IN MESSAGE +TWO_SUBS EQU 2 ;TWO VARIABLE FIELDS IN MESSAGE +THREE_SUBS EQU 3 ;THREE VARIABLE FIELDS IN MESSAGE +CLASS_1 EQU EXT_ERR_CLASS ;CLASS 1 (DOS EXTENDED ERRORS) +CLASS_2 EQU PARSE_ERR_CLASS ;CLASS 2 (PARSE ERRORS) +CLASS_A EQU UTILITY_MSG_CLASS ;CLASS A TYPE MESSAGE + +;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE, +;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN +;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED. + +MSG_DESC STRUC +MSG_NUM DW 0 ;MESSAGE NUMBER (TO AX) +MSG_HAND DW 0 ;HANDLE OF OUTPUT DEVICE (TO BX) +MSG_SUBLIST DW 0 ;POINTER TO SUBLIST (TO SI) +MSG_COUNT DW 0 ;SUBSTITUTION COUNT (TO CX) +MSG_CLASS DB 0 ;MESSAGE CLASS (IN HIGH BYTE, TO DH) + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) +MSG_DESC ENDS +; VALUES FOR THE SUBLIST CONTROL BLOCK +PC_ID_0 EQU 0 ;ID OF " - " TRAILER TO MESSAGE +PC_ID_1 EQU 1 ;ID OF PERCENT VARIABLE FIELD +PC_ID_2 EQU 2 ;ID OF PERCENT VARIABLE FIELD +PC_ID_3 EQU 3 ;ID OF PERCENT VARIABLE FIELD +MAX_0 EQU 0 ;MAXIMUM WIDTH OF STRING FIELD (0=NO LIMIT) +MIN_1 EQU 1 ;MINIMUM WIDTH OF STRING FIELD +;Message SUB-LIST + SUBLIST1 LABEL DWORD ;PARM LIST + ;(Original %1: set to %2:) + DB 11 ;PARMLIST size + DB 0 ;reserved + DW OLD_DRV ;; ptr to data +SEG_1 DW ? + DB 1 ;; n of %n + DB FLAG1 ;; data type + DB max_0 ;;max width + DB min_1 ;;min width + DB PAD_CHAR ;;char defined to be space + +DRV_LETS LABEL WORD +;Message SUB-LIST2 + SUBLIST2 LABEL DWORD ;PARM LIST + ;(File not found - 'PATH_SPEC') + DB 11 ;PARMLIST size + DB 0 ;reserved + DW NEW_DRV ;; ptr to data - offset +SEG_2 DW ? ;; ptr to data + DB 2 ;; n of %n + DB FLAG1 ;; data type + DB max_0 ;;max width + DB min_1 ;;min width + DB PAD_CHAR ;;char defined to be space + + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGPARM.ASM b/v4.0/src/CMD/ASSIGN/ASSGPARM.ASM new file mode 100644 index 0000000..74067bf --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGPARM.ASM @@ -0,0 +1,141 @@ + + PAGE ,132 ; + TITLE ASSPARM.SAL - ASSIGN SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: ASSGPARM.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of ASSIGN. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .EXE. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.SAL statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.SAL statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.SAL) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the ASMUT 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: A000 Version 4.00: add PARSER, System Message Handler, +; +; COPYRIGHT: "Microsoft DOS ASSIGN Utility" +; "Version 4.00 (C)Copyright 1988 Microsoft Corp" +; "Licensed Material - Program Property of Microsoft " +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 + %OUT COMPONENT=ASSIGN, MODULE=ASSPARM.SAL... + ENDIF +; = = = = = = = = = = = = + HEADER +; = = = = = = = = = = = = + +HEADER MACRO TEXT +.XLIST + SUBTTL TEXT +.LIST + PAGE + ENDM + +; = = = = = = = = = = = = + HEADER ; ;AN000; +CODE SEGMENT PARA PUBLIC ; ;AN000; + ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE ; ;AN000; + + PUBLIC SYSPARSE ;SUBROUTINE ENTRY POINT ;AN000; + +CAPSW EQU 1 ;SUPPORT FILENAME TBL CAPS +FARSW EQU 0 ;PARSER CALL NEAR +FILESW EQU 0 ;CHECK FOR FILESPEC +DATESW EQU 0 ;SUPPRESS DATE CHECKING +TIMESW EQU 0 ;SUPPRESS TIME CHECKING +CMPXSW EQU 0 ;SUPPRESS CHECKING COMPLEX LIST +NUMSW EQU 0 ;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT +VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 +VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 +VAL3SW EQU 1 ;SUPPORT OF VALUE DEFINITION 3 +DRVSW EQU 0 ;SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT + + IF1 ; ;AN000; + %OUT COMPONENT=ASSIGN, SUBCOMPONENT=PARSE, MODULE=PARSE.ASM... + %OUT COMPONENT=ASSIGN, SUBCOMPONENT=PARSE, MODULE=PSDATA.INC... + ENDIF ; ;AN000; + + ;PARSE WORK AREA & EQUATES + +.xlist + INCLUDE PARSE.ASM +.list + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGPARM.INC b/v4.0/src/CMD/ASSIGN/ASSGPARM.INC new file mode 100644 index 0000000..933d3cb --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGPARM.INC @@ -0,0 +1,242 @@ + + ASS_PARMS label dword + dw ASS_PARMSX + db 1 ;list of extra delimiters + db 3 ;0 length + db ";+=" + + ASS_PARMSX label byte + db 0,1 + +;Min 0 - no drive or switch specified +;Max 1 - maximal allowance of drive letters +;repeats + + dw ASS_POS1 ;positional ctl ptr + db 1 ;# of switches + dw ASS_SW1 ;switch ptr + + ASS_POS1 label word + dw 2010h ;Simple string, + ;ignore colon, & + ;repeat + ;allowed + dw 0002h ;Cap result by + ; character table + dw Result_Val ;tbl + dw Res_CTLVAL ;value list + db 0 ;no switch or + ;keyword synonyms + db 0 ;alternative keyword + + ASS_SW1 label word + dw 0 ;20010h ;Simple string, + ;ignore colon & repeat + ;allowed + dw 0002h ;Cap result by + ;character table + dw Result_Valsw ;tbl + dw 0 ; ;value list + db 2 ;switch or + ;keyword synonyms + SW_Syn1 db "/STATUS",0 ;alternate keyword + SW_Syn2 db "/STA",0 ;alternate keyword + + + Res_CTLVAL label word + db 3 ;List of simple strings + db 0 ;not in range defn. + db 0 ;not in numeric defn. + db 26 ;# of strings defined + db "A" ;item tag + ;value returned + dw DRVA_PTR ;string ptr + db "B" ;item tag + ;value returned + dw DRVB_PTR ;string ptr + db "C" ;item tag + ;value returned + dw DRVC_PTR ;string ptr + db "D" ;item tag + ;value returned + dw DRVD_PTR ;string ptr + db "E" ;item tag + ;value returned + dw DRVE_PTR ;string ptr + db "F" ;item tag + ;value returned + dw DRVF_PTR ;string ptr + db "G" ;item tag + ;value returned + dw DRVG_PTR ;string ptr + db "H" ;item tag + ;value returned + dw DRVH_PTR ;string ptr + db "I" ;item tag + ;value returned + dw DRVI_PTR ;string ptr + db "J" ;item tag + ;value returned + dw DRVJ_PTR ;string ptr + db "K" ;item tag + ;value returned + dw DRVK_PTR ;string ptr + db "L" ;item tag + ;value returned + dw DRVL_PTR ;string ptr + db "M" ;item tag + ;value returned + dw DRVM_PTR ;string ptr + db "N" ;item tag + ;value returned + dw DRVN_PTR ;string ptr + db "O" ;item tag + ;value returned + dw DRVO_PTR ;string ptr + db "P" ;item tag + ;value returned + dw DRVP_PTR ;string ptr + db "Q" ;item tag + ;value returned + dw DRVQ_PTR ;string ptr + db "R" ;item tag + ;value returned + dw DRVR_PTR ;string ptr + db "S" ;item tag + ;value returned + dw DRVS_PTR ;string ptr + db "T" ;item tag + ;value returned + dw DRVT_PTR ;string ptr + db "U" ;item tag + ;value returned + dw DRVU_PTR ;string ptr + db "V" ;item tag + ;value returned + dw DRVV_PTR ;string ptr + db "W" ;item tag + ;value returned + dw DRVW_PTR ;string ptr + db "X" ;item tag + ;value returned + dw DRVX_PTR ;string ptr + db "Y" ;item tag + ;value returned + dw DRVY_PTR ;string ptr + db "Z" ;item tag + ;value returned + dw DRVZ_PTR ;string ptr + + DRVA_PTR LABEL word + db "A",0 + + DRVB_PTR LABEL word + db "B",0 + + DRVC_PTR LABEL word + db "C",0 + + DRVD_PTR LABEL word + db "D",0 + + DRVE_PTR LABEL word + db "E",0 + + DRVF_PTR LABEL word + db "F",0 + + DRVG_PTR LABEL word + db "G",0 + + DRVH_PTR LABEL word + db "H",0 + + DRVI_PTR LABEL word + db "I",0 + + DRVJ_PTR LABEL word + db "J",0 + + DRVK_PTR LABEL word + db "K",0 + + DRVL_PTR LABEL word + db "L",0 + + DRVM_PTR LABEL word + db "M",0 + + DRVN_PTR LABEL word + db "N",0 + + DRVO_PTR LABEL word + db "O",0 + + DRVP_PTR LABEL word + db "P",0 + + DRVQ_PTR LABEL word + db "Q",0 + + DRVR_PTR LABEL word + db "R",0 + + DRVS_PTR LABEL word + db "S",0 + + DRVT_PTR LABEL word + db "T",0 + + DRVU_PTR LABEL word + db "U",0 + + DRVV_PTR LABEL word + db "V",0 + + DRVW_PTR LABEL word + db "W",0 + + DRVX_PTR LABEL word + db "X",0 + + DRVY_PTR LABEL word + db "Y",0 + + DRVZ_PTR LABEL word + db "Z",0 + + RESULT_VAL label word + RESULT_VALSW label word + + RES_TYPE db 0 ;Result_type + RES_ITAG db 0 ;Matched + ;item tag + RES_SYN dw 0 ;synonym + ;returned + RES_SOFF dw 0 ;drive type + ;or beginning + ;of string + ;may be string + RES_SEG dw 0 ;string offset + ;if type specified + + +;========================================================================= +; Sublist Definition Area +;========================================================================= + +Parse_Sublist label word + + db Sublist_Length ;sublist length ;an002; dms; + db Reserved ;reserved for future growth ;an002; dms; +Parse_Sub_Off dw ? ;offset of replaceable parm ;an002; dms; +Parse_Sub_Seg dw ? ;segment of replaceable parm ;an002; dms; + db 0 ;replaceable parm 0 ;an002; dms; + db Left_Align+Char_Field_ASCIIZ ; ;an002; dms; + db 40 ;max width ;an002; dms; + db 1 ;min width ;an002; dms; + db 20h ;blank fill ;an002; dms; + + + + diff --git a/v4.0/src/CMD/ASSIGN/ASSIGN.SKL b/v4.0/src/CMD/ASSIGN/ASSIGN.SKL new file mode 100644 index 0000000..5233c46 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSIGN.SKL @@ -0,0 +1,9 @@ +:util ASSIGN +:class 2 ;parse errors: + +:class A ;"Original %1: set to %2:" +:use 1 COMMON1 ;MSG 1 is always + ;"Incorrect DOS version" +:def 2 "Original %1: set to %2:",cr,lf +:end + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/MAKEFILE b/v4.0/src/CMD/ASSIGN/MAKEFILE new file mode 100644 index 0000000..1974c33 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/MAKEFILE @@ -0,0 +1,43 @@ +#************************** makefile for cmd\assign *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: assign.com + +assign.ctl: assign.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +assgparm.obj: assgparm.asm \ + $(inc)\psdata.inc \ + $(inc)\parse.asm \ + makefile + +assgmain.obj: assgmain.asm \ + $(inc)\dosmac.inc \ + $(inc)\sysvar.inc \ + $(inc)\mult.inc \ + $(inc)\pdb.inc \ + $(inc)\syscall.inc \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc \ + assgparm.inc \ + assgmsg.inc \ + assign.ctl \ + assign.cla \ + assign.cl1 \ + assign.cl2 \ + $(inc)\curdir.inc \ + makefile + +assign.com: assgmain.obj assgparm.obj + link assgmain.obj+assgparm.obj,assign,,; + exe2bin assign.exe assign.com + del assign.exe -- cgit v1.2.3