4 TITLE ASSGMAIN
.SAL - ASSIGN MAIN PROGRAM
5 ;****************** START OF SPECIFICATIONS *****************************
6 ; MODULE NAME: ASSGMAIN.SAL
8 ; DESCRIPTIVE NAME: Reassigns drive specifications.
10 ;FUNCTION: This program reassigns the specified drives to a new drive
13 ; ENTRY POINT: ENTRY_POINT
17 ; ASSIGN [DRIVE] [DELIMITER] [DRIVE] [SW]
18 ; where DRIVE = optional colon
19 ; where DELIMITER = +;=TAB LF SPACE
20 ; where SW = /STATUS or /STA
23 ; /STATUS - reports back to the user
24 ; the currently changed
25 ; drive assignments and the
26 ; new assignment drive
29 ; If a drive value has not been
30 ; ASSIGN will report back nothing.
33 ; Instructs DOS to route disk I/O
34 ; for one drive into disk I/O to another
38 ; EXIT-NORMAL: Assigned drives or reassigned drives
40 ; EXIT-ERROR: Any one of the possible parse errors
42 ; INTERNAL REFERENCES:
43 ; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.SAL)
48 ; EXTERNAL REFERENCES:
52 ; This module should be processed with the SALUT preprocessor
53 ; with the re-alignment not requested, as:
57 ; To assemble these modules, the sequential
58 ; ordering of segments may be used.
60 ; For LINK instructions, refer to the PROLOG of the main module,
63 ; REVISION HISTORY: AN000 - Version 4.00: PARSER, System Message Handler,
66 ; COPYRIGHT: "Microsoft DOS ASSIGN Utility"
67 ; "Version 4.00 (C)Copyright 1988 Microsoft"
68 ; "Licensed Material - Program Property of Microsoft"
73 ; AN001 -> PTM P3954 Release the environmental vector and close
76 ; AN002 -> PTM P3918 Parse error messages must conform to spec.
77 ; All parse error messages should display
78 ; the offending parameters.
81 ;****************** END OF SPECIFICATIONS *****************************
83 ;*********************************************
85 ;* UTILITY NAME: ASSIGN.COM *
87 ;* SOURCE FILE NAME: ASSIGN.SAL *
89 ;* STATUS: ASSIGN utility *
90 ;* PC-DOS Version 3.40 *
92 ;* SYNTAX (Command line) *
94 ;* ASSIGN [DRIVE] [DELIMITER] [DRIVE] [SW] *
95 ;* where DRIVE = optional colon *
96 ;* where DELIMITER = +;=TAB LF SPACE *
97 ;* where SW = /STATUS or /STA *
100 ;* /STATUS - reports back to the user *
101 ;* the currently changed *
102 ;* drive assignments and the *
103 ;* new assignment drive *
105 ;* If a drive value has not been *
106 ;* ASSIGN will report back nothing. *
108 ;* UTILITY FUNCTION: *
109 ;* Instructs DOS to route disk I/O *
110 ;* for one drive into disk I/O to another *
112 ;* a=c sets a: to c: *
113 ;*********************************************
119 INCLUDE SYSMSG
.INC ;AN000;
125 MSG_UTILNAME
<ASSIGN
>
129 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
130 BREAK <MACRO DEFINITIONS
>
138 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
139 CallOperRange
macro low
,high
,routine
;;NS-macro to call subroutines
140 ?
call = low
;;NS-in the given call range
141 ;;NS-starting call value = low #
142 rept (high
-low
)+1 ;;NS-calculate the entry point
143 CallOper ?
call,routine
;;NS-into the table then execute
144 ?
call = ?
call + 1 ;;NS-increment call value to next
147 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
148 CallOper
macro call,routine
;;NS-macro that calls a single
149 ;;NS-subroutine that is used in
150 ;;NS-the above macro loop CallOperange
151 ORG (SysTab
-ASSIGN_BASE
)+(call*2) ;;NS-Calculate entry point into
152 DW OFFSET
CODE:routine
;;NS-code where SysTab is the
153 ENDM
;;NS-entry point to the tables
154 ;;NS-ASSIGN_BASE is at 0:0000
155 ;;NS-the (call*2) is calculated
156 ;;NS-to take into account two bytes
157 ;;NS-and final OFFSET statement points
158 ;;NS-code to be executed at the given
160 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
161 ; $SALUT (0,36,40,48)
162 MyINT21
macro ;;NS-macro used to save
163 pushf ;;NS-the flags to maintain
164 call system
;;NS-DOS environment
166 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
167 SaveReg
MACRO reglist
;; push those registers
169 ?stackdepth
= ?stackdepth
+ 1
174 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
175 RestoreReg
MACRO reglist
;; pop those registers
177 ?stackdepth
= ?stackdepth
- 1
183 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
184 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
185 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
187 BREAK <DOS FUNCTIONS
, AND OTHER EQUATES
>
188 ; $SALUT (0,23,28,41)
191 NO_ERROR equ
0 ;return code zero from the parser
192 ;********** CNS *****************
193 ;Std_Con_String_Output EQU 9 ; 9
194 PSP_Env equ 2
ch ;Environmental vector segment in PSP ;an001; dms;
195 Get_PSP equ 62h
; DOS function call to get PSP address ;an001; dms;
196 Handle_Close equ 3eh
;close handle ;an001; dms;
198 Set_Default_Drive EQU
14 ; E
199 Get_Default_Drive EQU
25 ; 19
200 Set_Interrupt_Vector EQU
37 ; 25
201 Get_Version EQU
48 ; 30
202 Keep_Process EQU
49 ; 31
203 Get_Interrupt_Vector EQU
53 ; 35
204 Get_Drive_Freespace EQU
54 ; 36
207 Get_In_Vars EQU
82 ; 52
208 Get_Set_Media_ID equ 69h
; 69h
210 IOCTL_READ_BLOCK EQU 4404H
;READ FROM BLOCK DEVICE
211 IOCTL_WRITE_BLOCK EQU 4405H
;WRITE TO A BLOCK DEVICE
212 IOCTL_BLOCK_CHANGE EQU 4408H
;BLOCK DEVICE CHANGEABLE
213 IOCTL_BLOCK_REMOTE EQU 4409H
;BLOCK DEVICE REMOTE
220 ABS_DISK_READ EQU 25H
221 ABS_DISK_WRITE EQU 26H
222 stay equ 27h
;NS stay interrupt value
223 int_IBM EQU 2
AH ;critical section maintenance
224 MULTIPLEXOR EQU 2FH
;MULTIPLEXOR INTERRUPT VECTOR NUMBER
226 ; CONSTANTS USED ACROSS THE MULTIPLEXOR INTERFACE
227 MPLEX_ID EQU
06H ;ID OF ASSIGN IN MPLEX CHAIN
228 MPLEX_R_U_THERE EQU
0 ;MPLEX FUNCTION: ARE YOU THERE?
229 MPLEX_GET_SEG EQU
1 ;MPLEX FUNCTION: GET SEG OF INSTALLED ASSIGN
230 MPLEX_INSTALLED EQU
0FFH ;"I AM HERE" RETURN VALUE
233 cr equ
0dh ;CARRIAGE RETURN
234 LF EQU
0AH ;LINE FEED
235 f_Interrupt EQU
0000001000000000B ;NS - mask used for interrupt
237 BREAK <ENTRY POINT FOR
CODE, EXTRNS
>
238 ; $SALUT (4,15,21,41)
240 code segment para
public ;NS code all in one segment
246 ASSIGN_BASE: ;NS- starting point of loaded file
250 jmp INITIALIZATION
;JUMP TO INITIALIZATION
251 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
252 BREAK <TABLES
AND LOCAL WORKAREAS
>
253 drives db 1,2,3,4,5,6,7,8,9 ;drive values used in comparison
254 db 10,11,12,13,14,15,16,17,18,19 ;against default or found drive
255 db 20,21,22,23,24,25,26
257 drive_save db ?
; saved drive byte
258 drive_address dw ?
; location (from DS) of drive byte
259 drive_save2 db ?
; second saved drive byte
260 ;******************************************************************************
261 ;******************************************************************************
264 int25_vec dd ?
;NS - Hooks for the Int 2f handler preparation
265 int26_vec dd ?
;NS - Hooks for the Int 2f handler preparation
266 int2F_vec dd ?
;NS - Area to be hooked in and remain resident
267 user_ret dd ?
; ???????????????????????????????????????
268 saveIntF dw ?
; ???????????????????????????????????????
269 I21_Func db ?
; Save area for INT21 function requested -->RW
274 SysTab
label word ;NS-Beginning of the call,subroutine table
276 CallOperRange
01h,0Ch,DoNothing
; done ????????????????????????
277 CallOper
0Dh,DoReset
; done ????????????????????????
278 CallOper
0Eh,DoSetDefault
279 CallOperRange
0Fh,17h
,DoFCB
; done ????????????????????????
280 CallOper 18h
,DoReset
; done ????????????????????????
281 CallOper 19h
,DoGetDefault
; ????????????????????????
282 CallOperRange 1
Ah,1
Bh,DoReset
; done ????????????????????????
283 CallOper 1
Ch,DoDL
; done ????????????????????????
284 CallOperRange 1
Dh,20h
,DoReset
; done ????????????????????????
285 CallOperRange 21h
,24h
,DoFCB
; done ????????????????????????
286 CallOperRange 25h
,26h
,DoReset
; done ????????????????????????
287 CallOperRange 27h
,28h
,DoFCB
; done ????????????????????????
288 CallOperRange 29h
,31h
,DoReset
; done ????????????????????????
289 CallOper 32h
,DoDL
; done ????????????????????????
290 CallOperRange 33h
,35h
,DoReset
; done ????????????????????????
291 CallOper 36h
,DoDL
; done ????????????????????????
292 CallOperRange 37h
,38h
,DoReset
; done ????????????????????????
293 CallOperRange 39h
,3
Dh,DoAscii
; done ????????????????????????
294 CallOperRange 3Eh
,40h
,DoReset
; done ????????????????????????
295 CallOper 41h
,DoAscii
; done ????????????????????????
296 CallOper 42h
,DoReset
; done ????????????????????????
297 CallOper 43h
,DoAscii
; done ????????????????????????
298 CallOper 44h
,DoIOCTL
; done ????????????????????????
299 CallOperRange 45h
,46h
,DoReset
; done ????????????????????????
300 CallOper 47h
,DoDL
; done ????????????????????????
301 CallOperRange 48h
,4
Ah,DoReset
; done ????????????????????????
302 CallOper 4
Bh,DoExec
; done ????????????????????????
303 CallOperRange 4
Ch,4
Dh,DoReset
; done ????????????????????????
304 CallOper 4Eh
,DoAscii
; done ????????????????????????
305 CallOperRange 4Fh
,55h
,DoReset
; done ????????????????????????
306 CallOper 56h
,DoRename
; done ????????????????????????
307 CallOperRange 57h
,59h
,DoReset
; done ????????????????????????
308 CallOperRange 5
Ah,5
Bh,DoAscii
; done ????????????????????????
309 CallOperRange 5
Ch,5Fh
,DoReset
; done ????????????????????????
310 CallOper 60h
,DoTranslate
; done ????????????????????????
311 CallOperRange 61h
,63h
,DoReset
; done ????????????????????????
312 CallOperRange 64h
,69h
,DoSetGetMedia
;done ????????????????????????
313 CallOperRange 6
ah,6
bh,DoNothing
;done ????????????????????????
314 CallOper 6
ch,DoAscii_DS_SI
;done ?????????????????????????
315 ; ????????????????????????
318 MAXCLL EQU 6
CH ; High bound of table
320 org (systab
-ASSIGN_BASE
) + (2 * (MAXCLL
+ 1)) ;NS - Beginning of code starts at
321 ;NS - Beginning of table + 128 bytes
322 BREAK <ASSIGN INTERRUPT HANDLER
>
324 mov SaveIntf
,f_interrupt
;NS- Move in the mask into a saved area
325 SaveReg
<AX,BX> ;NS- ??????????????????????????????????
326 cmp ah,MAXCLL
; Do a high bound check on the call
327 ; so we don't index past the end of
328 ja DoNothing
; the table on a bogus call
330 mov al,ah ;NS- Call must be in the 0 - 63h range
331 cbw ;NS- zero out the high byte now
332 ;NS- AX has 0 & call number
333 shl ax,1 ;NS- Double the value in AX
334 mov bx,ax ;NS- Move the value into BX to
335 jmp systab
[bx] ;NS- access the call number & subroutine
336 ;NS- bx bytes into the tbl
337 ;***********************************************************************************
339 EnterAssign: ;NS- make sure system intact by doing
340 call LeaveAllAssign
;NS- error recovery check
342 push ax ;NS- before making code
343 mov ax,8000h
+ critAssign
;NS- non- reentrant if unable
344 INT INT_IBM
;(2AH) NS- to screen out successfully
346 POP AX ;NS- LeaveAllAssign will be executed
347 RET ;return NS- and the critical section will be reset
348 ;************************************************************************************
349 LeaveAssign: ;NS- restore re-entrancy to
350 push ax ;NS- the code after & only
351 mov ax,8100h
+ critAssign
;NS- after this call has been
352 INT INT_IBM
;(2AH) NS- made or the error recovery
354 POP AX ;NS- call has been made
357 ;************************************************************************************
358 LeaveAllAssign: ;NS- Error recovery call
359 push ax ;NS- to restore the Assigns
360 mov ax,8908h
;NS- critical section
361 int INT_IBM
;(2AH) NS- if ASSIGN has encountered
363 pop ax ;NS- a problem on entrance or departure
365 ;************************************************************************************
367 ; Reset the exclusion flag ;NS- Reset to Assign
368 ; ;NS- critical section state
370 call LeaveAllAssign
;NS-
372 ;****************************************************************************************
374 ; The system call needed no special processing. Go do it directly.
376 DoNothing: ;NS-System registers and flags still
377 RestoreReg
<bx,ax> ;NS-intact it has not been clobbered
378 jmp system
;NS-by ASSIGN code
381 ;************************************************************************************
383 ; Munge the drive byte in an FCB pointed to by DS:DX.
384 ; "MUNGE" ? (Webster will turn over in his gravy...)
387 mov bx,dx ; indexable pointer
388 mov al,[bx] ; get drive
389 cmp al,0ffh ; extended fcb?
392 add bx,7 ; yes, advance past it
393 mov al,[bx] ; get read drive byte
395 or al,al ; default drive?
398 mov al,default_drive
; get default drive
400 ; DS:BX points to the drive byte being munged. AL is the old value. Save
406 call EnterAssign
; NS-Enter Assign's critical section
408 mov drive_save
,al ; NS-save the drive assignment
409 call mapdrv1
; NS-now let's map it to the
411 mov [bx],al ; NS-numeric drive associated in
412 ; NS-in drive range 1 to 26
413 ;******************************************************************************
414 ; The FCB has been converted. Now let's POP off the user's info and do the
415 ; system call. Note that we are no longer reentrant!
417 mov drive_address
,bx ; NS- location of drive value
418 RestoreReg
<BX,AX> ; get back original registers
419 pop word ptr user_ret
; restore his IP
420 pop word ptr user_ret
+2 ; restore his CS
421 call GotoCLI
; NS- Clear out old interrupts
422 ; NS- before an IRET is issued
423 ; NS- update the current
424 call system
; flags saved => this is a system call
426 pushf ; NS- re-adjust the stack
427 call RestInt
; NS- and setup the environment
429 SaveReg
<ax,bx> ; NS- with drive and the drive address
430 mov bx,drive_address
; NS- before leaving the Assign critical
431 mov al,drive_save
; NS- section
434 push word ptr user_ret
+2 ; push back user's cs
435 push word ptr user_ret
; push back user's ip
441 ;************************************************************************************
443 ; Munge the user's ASCIZ string at DS:DX.
446 mov bx,dx ; point to area
447 cmp byte ptr [bx+1],':' ; drive letter present?
448 jnz DoNothing
; nope, ignore this
450 ; There is a drive leter present. Grab it and convert it
452 mov al,[bx] ; get drive letter
453 call EnterAssign
; NS- Re-enter ASSIGN crit section
455 mov drive_save
,al ; remember previous contents
456 call maplet
; convert to real drive letter
458 mov [bx],al ; place in new drive letter
460 RestoreReg
<BX,AX> ; get back original registers
461 pop word ptr user_ret
; restore his IP
462 pop word ptr user_ret
+2 ; restore his CS
463 call GotoCLI
; clean up stack
465 call system
; flags saved => this is a system call
467 pushf ; save all drive info
468 call RestInt
; NS- clean up environment before
470 SaveReg
<ax,bx> ; NS- returning to the user's environment
471 mov bx,drive_address
; NS- to ask on the next ASSIGN entrance
475 push word ptr user_ret
+2 ; push back user's cs
476 push word ptr user_ret
; push back user's ip
477 Call LeaveAssign
; NS- exit ASSIGN crit. section
482 ;************************************************************************************
484 ; Munge the user's ASCIZ string at DS:SI.
487 mov bx,si ; point to area
488 cmp byte ptr [bx+1],':' ; drive letter present?
489 ; $if ne ; drive letter not present
491 jmp DoNothing
; nope, ignore this
495 ; There is a drive leter present. Grab it and convert it
497 mov al,[bx] ; get drive letter
498 call EnterAssign
; NS- Re-enter ASSIGN crit section
500 mov drive_save
,al ; remember previous contents
501 call maplet
; convert to real drive letter
503 mov [bx],al ; place in new drive letter
505 RestoreReg
<BX,AX> ; get back original registers
506 pop word ptr user_ret
; restore his IP
507 pop word ptr user_ret
+2 ; restore his CS
508 call GotoCLI
; clean up stack
510 call system
; flags saved => this is a system call
512 pushf ; save all drive info
513 call RestInt
; NS- clean up environment before
515 SaveReg
<ax,bx> ; NS- returning to the user's environment
516 mov bx,drive_address
; NS- to ask on the next ASSIGN entrance
520 push word ptr user_ret
+2 ; push back user's cs
521 push word ptr user_ret
; push back user's ip
522 Call LeaveAssign
; NS- exit ASSIGN crit. section
527 ;************************************************************************************
530 ; DoDL - the drive to map is in DL.
533 or dl,dl ; NS- check for drive mapping
534 ; $IF Z ;AC000;;USE DEFAULT DRIVE
538 jmp DoNothing
; NS- default drive was requested
539 ; NS- thus no mapping needed
542 mov al,dl ; NS- not default case so no need doctor
543 call EnterAssign
; NS- so enter ASSIGN crit. section again
545 mov drive_save
,al ; preserve old drive
548 mov dl,al ; drive is mapped
549 RestoreReg
<BX,AX> ; get back registers
550 mov I21_Func
,ah ; Save requested function call -->RW
551 pop word ptr user_ret
; restore his IP
552 pop word ptr user_ret
+2 ; restore his CS
555 call system
; flags saved => this is a system call
560 cmp I21_Func
,GET_DRIVE_FREESPACE
;(36h) If call returns info in DX, -->RW
561 ; NS- DL in both cases Func 36
562 ; NS- Func 1Ch are both used for
563 ; NS- drive input we don't want to
564 ; NS- the old drives so they should not
565 ; restored as the old value - use ASSIGN's
566 je Dont_Restore_DL
;AC000;;THEN DO CHANGE IT
568 cmp I21_Func
,1
ch ; If call returns info in DX, -->RW
569 ;(NOTE 1CH IS NOT DEFINED IN SYSCALL.INC. EK)
570 je Dont_Restore_DL
;AC000;;THEN DO CHANGE IT
572 mov dl,drive_save
; restore his dl
576 push word ptr user_ret
+2 ; push back user's cs
577 push word ptr user_ret
; push back user's ip
581 ;************************************************************************************
583 ; Map the IOCTL drives in BX ; NS- this section handles
584 ; NS- INT21 calls to get drive info
588 cmp ax,IOCTL_READ_BLOCK
;(4404h) IOCTL read string from block dev
591 cmp ax,IOCTL_WRITE_BLOCK
;(4405h) IOCTL write string from block dev
594 cmp ax,IOCTL_BLOCK_CHANGE
;(4408h) IOCTL is removable
597 cmp ax,IOCTL_BLOCK_REMOTE
;(4409h) IOCTL block dev redir (network)
598 jnz DNJ2
;AC000;;NORMAL CALL
602 or bx,bx ; NS- drive letter associated in BL
605 mov al,bl ; not the default case
608 mov drive_save
,al ; remember drive
609 call mapdrv1
; NS- time to map drive to new assoc.
611 mov bl,al ; drive is mapped
612 RestoreReg
<AX,AX> ; get back registers (throw away BX)
613 pop word ptr user_ret
; restore his IP
614 pop word ptr user_ret
+2 ; restore his CS
617 call system
; flags saved => this is a system call
622 mov bl,drive_save
; restore his dl
623 push word ptr user_ret
+2 ; push back user's cs
624 push word ptr user_ret
; push back user's ip
634 RestoreReg
<BX,AX> ;an000; dms;restore regs
635 SaveReg
<AX,BX> ;an000; dms;save regs
636 cmp ah,Get_Set_Media_ID
;an000; dms;trap on get/set media id
637 ; $if z ;an000; dms;found
639 or bl,bl ;an000; dms;drive letter entered
640 ; $if nz ;an000; dms;yes
642 mov al,bl ; not the default case
645 mov drive_save
,al ; remember drive
646 call mapdrv1
; NS- time to map drive to new assoc.
648 mov bl,al ; drive is mapped
649 RestoreReg
<AX,AX> ; get back registers (throw away BX)
650 pop word ptr user_ret
; restore his IP
651 pop word ptr user_ret
+2 ; restore his CS
654 call system
; flags saved => this is a system call
659 mov bl,drive_save
; restore his dl
660 push word ptr user_ret
+2 ; push back user's cs
661 push word ptr user_ret
; push back user's ip
663 ; $else ;an000; dms;not valid function 69h
666 jmp DoNothing
;an000; dms;pass to interrupt
667 ; $endif ;an000; dms;
672 jmp DoNothing
;an000; dms;pass to interrupt
673 ; $endif ;an000; dms;
678 ;************************************************************************************
680 ; Map the drive letter and forget about it. EXEC never returns.
686 ; $IF Z ;AC000;;IS LOAD GO, NOT USE NORMAL STUFF
689 mov bx,dx ; point to area
691 cmp byte ptr [bx+1],':' ; drive letter present?
695 ; There is a drive leter present. Grab it and convert it
697 mov al,[bx] ; get drive letter
698 call maplet
; convert to real drive letter
700 mov [bx],al ; place in new drive letter
704 jmp DoNothing
; restore and go on!
711 ;************************************************************************************
713 ; Map the drive letter at DS:SI. We need to un-map it at the end.
716 mov bx,SI ; point to area
717 cmp byte ptr [bx+1],':' ; drive letter present?
718 jnz DNJ3
; nope, ignore this
720 ; There is a drive leter present. Grab it and convert it
722 mov al,[bx] ; get drive letter
725 mov drive_save
,al ; remember previous contents
726 call maplet
; convert to real drive letter
728 mov [bx],al ; place in new drive letter
730 RestoreReg
<BX,AX> ; get back original registers
731 pop word ptr user_ret
; restore his IP
732 pop word ptr user_ret
+2 ; restore his CS
735 call system
; flags saved => this is a system call
745 push word ptr user_ret
+2 ; push back user's cs
746 push word ptr user_ret
; push back user's ip
752 ;************************************************************************************
754 ; Munge the user's ASCIZ string at DS:DX and es:di
757 mov bx,dx ; point to area
763 cmp ah,':' ; drive letter present?
767 call maplet
; convert to real drive letter
769 mov [bx],al ; place in new drive letter
773 mov ax,es:[di] ;NS- Get the 2nd drive from the command linepSOP
774 mov drive_save2
,al ;NS- Save possible drive
775 cmp ah,':' ;NS- exclude if no colon present
779 call maplet
;NS- go convert letter to actual drive #
781 mov es:[di],al ;NS- new drive value
785 RestoreReg
<BX,AX> ; get back original registers
786 pop word ptr user_ret
; restore his IP
787 pop word ptr user_ret
+2 ; restore his CS
790 call system
; flags saved => this is a system call
796 mov al,drive_save2
; NS- get the second drive update
797 mov es:[di],al ; NS- on the command line
798 mov bx,drive_address
;
802 push word ptr user_ret
+2 ; push back user's cs
803 push word ptr user_ret
; push back user's ip
808 ;************************************************************************************
810 ; DoGetDefault - return our idea of the current drive...
828 ;************************************************************************************
830 ; DoSetDefault - try to set to the mapped current drive. If we can do it,
831 ; then OK, else oops!
835 mov al,dl ; get new drive
836 inc al ; convert it to 1-based
839 mov drive_save
,al ; remember what we're doing
840 call mapdrv1
; convert drive
842 dec al ; convert back to 0-based
843 mov dl,al ; stick back in correct register
844 mov drive_save2
,al ; remember more of what we're doing
845 MyInt21
; try the set
847 push ax ; save return info from set
848 mov ah,Get_Default_Drive
;(29h)
852 dec dl ; Restore users original value
853 cmp al,drive_save2
; Did the set work?
858 mov default_drive
,al ; Set ours too, it's valid!
862 pop ax ; Set return info
867 ;************************************************************************************
869 ; Maintain the CLI state upon the next IRET. Flags for the IRET are on the
870 ; stack just under the return address. This means saving the current state
871 ; of the int flag and then turning off the saved version.
878 mov ax,[bp + 2 + 2 + 2]
879 and SaveIntf
,ax ; save those interrupts
880 and word ptr [bp + 2 + 2 + 2],not f_interrupt
885 ;************************************************************************************
886 ; Restore he saved interrupt flag for the user. His flags are on the stack
887 ; just above the RET.
895 or [bp + 2 + 2 + 2],ax
900 ;************************************************************************************
901 mapdrv0: ;a = 0 , b = 1
914 ;************************************************************************************
920 cmp al,0 ; check for default
929 push bx ;a = 1, b = 2
933 mov bx,offset drives
-1
943 ;************************************************************************************
967 ;************************************************************************************
979 CMP AH,mplex_id
;(06h) is this our multiplex?
983 jmp int2F_vec
; No, Chain to next guy
988 CMP AL,mplex_get_seg
;(01h)
989 ;0 AND 1 ARE THE ONLY ALLOWED FUNCTIONS
990 ; $IF NA ;AC000;;IF NOT SOME OTHER NUMBER,
992 ; $IF E ;AC000;;IF FUNCTION REQUEST IS 01
994 ;RETURN THE SEGID IN ES
996 POP ES ; Call 1 gets our segment in ES
1000 MOV AL,MPLEX_INSTALLED
;(0FFh) I AM here
1006 ;************************************************************************************
1020 ; $EXITIF NZ,NUL ;AC000;
1023 ; $ENDLOOP LOOP ;AC000;
1026 xor ax,ax ; reset z flag
1035 prog_size
= ($-ASSIGN_BASE
+15)/16
1038 ;************************************************************************************
1040 ;************************************************************************************
1041 ;*********************************************
1043 ;* Subroutine name: Initialization *
1045 ;* Purpose: Process the command line. *
1046 ;* If there are no errors update *
1047 ;* the drive table according to *
1048 ;* the drive assignments, terminate *
1049 ;* and stay resident. If status switch *
1050 ;* set and the drive values have been *
1051 ;* altered display drive is set to *
1054 ;* Input: Command line (described in header) *
1056 ;* Output: Table will be updated and resident*
1057 ;* code will be hooked in. *
1059 ;* Normal Exit: Valid drives, sufficient *
1061 ;* Error Conditions: *
1062 ;* Incorrect DOS Version *
1063 ;* Invalid Parameter *
1070 ;*********************************************
1071 ; *****************************************
1072 ; * INITIALIZATION *
1073 ; *****************************************
1075 ; * CALL SYSLOADMSG *
1076 ; * Do DOS Versinon Check *
1077 ; * CALL SYSDISPMSG *
1078 ; * IF <> X.X then *
1079 ; * Display message *
1080 ; * Message number 1 *
1081 ; * (001 - Incorrect DOS Version) *
1086 ; * Establish address of the *
1087 ; * PDB environment *
1088 ; * (Process Data Block ) *
1089 ; * .IF NO SPACE free de-allocate (49)*
1090 ; * memory at the environment *
1093 ; *****************************************
1094 ;*******************************************************************************
1097 BREAK <INITIALIZATION
- NOT STAY RESIDENT
>
1099 EXTRN SYSPARSE
:NEAR ;AN000;
1101 ODDX equ
01H ;AN000;
1102 EVENX equ
00H ;AN000;
1103 PAD_CHAR equ
' ' ;AN000;
1104 SEMICOLON equ
';' ;AN000;
1105 SPACE equ
' ' ;AN000;
1106 EQUAL equ
'=' ;AN000;
1107 PLUS equ
'+' ;AN000;
1108 good_parse_finish equ
0ffffh ;an000;
1109 ;******************************************************************************
1110 STATUS_ONLY db 0 ;AN000;
1111 STRING_CTR db 0 ;AN000;
1112 STATUS_FLAG db 0 ;AN000;
1113 ERR_CODE db 0 ;AN000;
1114 POS_FLAG db 'n' ;AN000;
1115 PARMS_AVAIL db 'n' ;AN000;
1116 PAR_RETC dw 0 ;AN000; used for the return code
1117 DRV_X db 0 ;AN000; from the parser
1118 save_dr_tbl_ptr dw ?
;an000;drive table pointer
1120 Parm_Ptr1 dw ?
;an002;ptr to parse parm
1121 Parm_Ptr2 dw ?
;an002;ptr to parse parm
1124 STring dd ?
;AN000;string holder
1127 INCLUDE ASSGPARM
.INC ;AN000;
1128 INCLUDE ASSGMSG
.INC ;AN000;
1131 assume
cs:code, ds:code, ss:code, es:code
1135 push ax ;an000; save ax
1136 mov ax,ds ;an000; get the current ds
1137 mov SEG_1
,ax ;an000; set sublist table
1138 mov SEG_2
,ax ;an000; set sublist table
1139 pop ax ;an000; restore ax
1141 call SYSLOADMSG
;AN000; ;does DOS version check
1144 ;remainder of info given
1145 call SYSDISPMSG
;AN000; ;by the msg retriever
1148 call EXIT_PROG
;AC000; ;(4CH) Terminate function
1155 ;************************************* CNS ************************************
1156 ; *****************************************
1157 ; * INITIALIZATION *
1158 ; *****************************************
1160 ; * Make internal DOS function call (52h)*
1161 ; * to process the data block *
1162 ; * information after mem is available *
1163 ; ******************************************
1164 ;************************************* CNS ************************************
1166 mov ax,ds:[pdb_environ
] ;get your Process Data Block Address
1167 or ax,ax ;check to see if space available
1171 push es ; save code segment value
1172 mov es,ax ; de-allocate memory
1173 mov ah,dealloc
;(49H)
1176 pop es ;restore code segment value
1182 push es ;an000; save es
1183 mov ah,Get_In_Vars
;(52H)
1187 mov Word ptr inv
+2,es
1188 pop es ;an000; restore es
1190 ;******************************************************************************
1192 ; *****************************************
1193 ; * Establish addressability *
1194 ; * to command line parms (DS:SI) *
1195 ; * Establish addressability to PARM *
1196 ; * control block (ES:DI) *
1198 ; *****************************************
1199 ;*******************************************************************************
1200 ;parser es & ds now points at the command line
1201 cld ;clear the directional flag
1202 ;decrement mode - maintanis pointer without
1205 mov di,offset ASS_PARMS
;AC000; ;set index to the location of your PARAMETER
1206 ;PARSER control block
1207 mov si,81h
;AC000; ;set index to the beginning of the commandline
1208 ;at 81h to the first 128 bytes
1210 ;******************************************************************************
1212 ;******************************************************************************
1213 ;*********************************************
1215 ;* Subroutine : Process_path *
1216 ;* Function : Process command line. *
1217 ;* Repeat searching for drive *
1218 ;* spec. If valid update *
1221 ;* Normal exit: End of line *
1224 ;* Abort exit: Invalid drive *
1226 ;*********************************************
1227 ; *****************************************
1229 ; * WHILE PAR_RETC eq NO_ERROR (0) *
1232 ; * .IF (POSITIONAL) *
1233 ; * Result is positional & Ctr even *
1236 ; * .IF the string is valid *
1238 ; * calculate table drv posit. *
1239 ; * based on the ascii value *
1244 ; * Result is positional & CTR odd *
1245 ; * save the ascii_value *
1246 ; * Check the String *
1247 ; * .IF the string is valid *
1249 ; * update the drive table *
1256 ; *****************************************
1258 ;******************************************************************************
1259 xor cx,cx ;an000; set cx to 0 for parse
1260 xor dx,dx ;an000; set dx to 0 for parse
1262 mov Parm_Ptr1
,si ;an002; dms;ptr to 1st. parm
1263 mov Parm_Ptr2
,si ;an002; dms;ptr to 1st. parm
1264 call SYSPARSE
;AN000; dms;priming parse
1265 mov par_retc
,ax ;AN000; dms;set flag
1269 CMP ax,no_error
;AN000;Is compare the return
1270 ; $LEAVE NE ;AN000;code 0 no error keep
1273 call CHK_PARSER
;AN000;
1275 mov Parm_Ptr2
,si ;an002; dms;ptr to 1st. parm
1276 call SYSPARSE
;AN000;go parse the command line
1277 mov par_retc
,ax ;AN000; dms;set flag
1278 ;AN000;restore the parm return code
1284 cmp ax,good_parse_finish
;an000; dms;see if a parse error
1285 ; $if ne ;an000; dms;if a parse error
1287 push ax ;an002; dms save ax
1288 mov ax,Parm_Ptr2
;an002; dms;get original parm ptr
1289 mov Parm_Ptr1
,ax ;an002; dms;place in variable
1290 pop ax ;an002; dms;restore ax
1291 call PARSE_ERR
;an000; dms;display error & exit
1292 ; $endif ;an000; dms;
1295 cmp PARMS_AVAIL
,'y' ;AN000;
1296 ; $IF E ;AN000; If there are parms available
1298 cmp ax,0 ;AN000; see if the return code was no error
1299 ; $IF G ;AN000; if greater than 0
1302 call PARSE_ERR
;AN000; you got a parser error
1303 ;AN000; so report & exit
1304 ; $ENDIF ;AN000; you also get an error
1308 mov al,String_ctr
;AN000;
1313 ; $IF NE ;AN000; if the drives did not pair off
1320 cmp POS_FLAG
,'n' ;AN000;has a drive been specified
1321 ; $IF E,AND ;AN000;and has a switch also been
1323 cmp STATUS_FLAG
,1 ;AN000;specified if so hook in code
1324 ; $IF E ;AN000;and then report status
1326 mov STATUS_ONLY
,1 ;AN000;set flag specifing user input full
1327 ; $ENDIF ;AN000;command line
1329 ;AN000; hook in the code
1335 cmp STATUS_ONLY
,0 ;AN000;
1339 call Get_Vectors
;get current vectors ;an001; dms;
1340 call Set_Vectors
;set new vectors ;an001; dms;
1342 ; $ELSE ;AN000;END of HOOK-IN
1346 call REPORT_STATUS
;AN000;
1347 call EXIT_PROG
;AN000;
1352 ;*********************************** CNS ***************************************
1353 RELOAD_CURDIR PROC
NEAR
1355 ;*****************************************************************************
1357 ; We have an interesting problem here. What if the user is assigning away
1358 ; his current drive? Here's the solution:
1360 ; o We get the current drive here.
1361 ; o We reload the mapping table.
1362 ; o We set the current drive.
1364 MOV AH,Get_Default_Drive
;(19H)
1367 PUSH AX ; save away the table
1369 MOV AX,(MPLEX_ID
SHL 8)+MPLEX_GET_SEG
;(0601H) Get the SEG of the installed ASSIGN
1370 INT MULTIPLEXOR
;(2FH) in ES
1372 mov si,offset drives
;move in the new drive table
1374 mov cx,26 ; move a-z
1379 POP DX ; restore the old current drive
1380 MOV AH,Set_Default_Drive
;(0EH)
1383 call EXIT_PROG
;go_home:
1385 INT PGM_TERM
;(20H) Exit SHOULD not return, but be safe
1390 ;*********************************** CNS ***************************************
1391 ;Input: Parser control block
1392 ;Output: Result Parser control block
1393 ;Register usage: AX,BX,CX,DX,ES,DS,SI,DI
1396 ;*********************************** CNS ***************************************
1398 CHK_PARSER PROC
NEAR
1400 xor cx,cx ;an000; clear out cx
1401 xor ax,ax ;AN000; clear out ax
1402 mov al,String_ctr
;AN000; grab current assign ctr
1403 mov bx,0002h ;an000; set bx to 2
1404 div bl ;AN000; divide so we get rem.
1405 cmp RES_TYPE
,2 ;an000; check for 1st drive
1406 ; $IF E,AND ;AN000; drive letter?
1408 cmp ah,EVENX
;AN000; and no remainder?
1411 inc STRING_CTR
;AN000; increment counter
1412 mov PARMS_AVAIL
,'y' ;AN000; signal parms entered
1413 push ax ;AN000; save ax
1414 mov al,res_itag
;AN000; grab parm entered
1415 mov drv_x
,al ;AN000; save it for later use
1416 call drvchk
;AC000; check for valid drive
1417 cbw ;AC000; convert drive byte found to a word
1418 mov bx,offset drives
-1 ;AC000; get the drive table
1419 add bx,ax ;AC000; get the drive address
1420 mov save_dr_tbl_ptr
,bx ;an000; save the drive table pointer
1421 pop ax ;an000; restore ax
1425 cmp RES_TYPE
,2 ;AN000; check for 2nd drive
1426 ; $IF E,AND ;AN000; drive entered?
1428 cmp ah,EVENX
;AN000; and not first?
1431 inc STRING_CTR
;AN000; increment counter
1432 mov PARMS_AVAIL
,'y' ;AN000; signal parms entered
1433 push ax ;AN000; save ax
1434 mov al,res_itag
;AN000; grab parm entered
1435 mov drv_x
,al ;AN000; save it for later use
1436 call drvchk
;AC000; if so see if it was valid
1437 mov bx,save_dr_tbl_ptr
;an000; set bx to drive table
1438 mov [bx],al ;AC000; if valid update the table
1439 mov POS_FLAG
,'y' ;AN000; yes you have valid positionals
1440 pop ax ;an000; restore ax
1441 mov Parm_Ptr1
,si ;an002; dms;ptr to 1st. parm
1445 cmp RES_SYN
,0 ;AN000; See if a switch was specified
1446 ; $IF NE ;AN000; If so,
1448 mov STATUS_flag
,1 ;AN000; set the status flag on
1449 mov PARMS_AVAIL
,'y' ;AN000; and report that a valid parameter
1450 mov byte ptr SW_Syn1
,20h
;an000; remove switch from list
1451 mov byte ptr SW_Syn2
,20h
;an000; remove switch from list
1452 mov Parm_Ptr1
,si ;an002; dms;ptr to 1st. parm
1453 ; $ENDIF ;AN000; was on the command line
1462 ;*********************************** CNS ***************************************
1464 ; check drive validity
1468 sub al,"A" ; NS- error checking
1469 ; $IF NB ;AN000; ;if alphabetic,
1477 cmp al,es:[bx].sysi_ncds
;AN000; ;NS- check in case current directory
1478 ; $IF NAE ;AN000; ;NS- has been altered
1482 les bx,es:[bx].sysi_cds
1484 mov bl,size curdir_list
1488 test es:[bx].curdir_flags
,curdir_inuse
1499 ; $ENDIF ;AC000; curdir in use?
1501 ; $ENDIF ;AC000; curdir been altered?
1503 ; $ENDIF ;AC000; alphabetic?
1506 mov ax,parse10
;AN000; Invalid parameter
1507 call PARSE_ERR
;an000; display the error & end
1509 ;******************************* CNS *******************************************
1510 ;Purpose: Print the mapping status of the drive table.
1511 ;Input : Drive table
1512 ;Registers affected: BX,CX,DX,AX
1514 ;Output : Display of all drive values stored not equal to their sequential
1517 ;******************************* CNS *******************************************
1518 REPORT_STATUS PROC
NEAR
1520 push es ;an000; save es
1521 push es ;an000; swap es with
1523 mov curr_es_seg
,ax ;an000; save es in curr_es_seg
1525 mov ax,0601h ;an000; our int 2fh
1526 int 2fh
;an000; returns segment of drive vector
1527 assume
es:nothing
;an000; tell the linker
1529 mov cl,01 ;AN000; ;initialize the counter
1530 ;AN000; advance to next drive
1531 mov bx,offset drives
;AN000; load drive table
1534 cmp cl,26 ;AN000; see if we scanned all drives
1536 ; $LEAVE A ;AN000; exit loop if we have
1539 cmp cl,es:[bx] ;AN000; ;compare the table value
1540 ;to the table contents
1543 push bx ;an000; save bx - we stomp it
1544 push cx ;an000; save cx - we stomp it
1545 mov al,es:[bx] ;AN000; get the table contents to convert
1546 push es ;an000; save es for print
1547 mov bx,curr_es_seg
;an000; get the current segment
1548 mov es,bx ;an000; get the segment into es
1549 assume
es:code ;an000; tell linker it is code
1551 add cl,40H
;AN000; convert to ascii representation
1552 add al,40h
;an000; convert to ascii
1553 mov OLD_DRV
,cl ;AN000; place in parms for printing
1554 mov NEW_DRV
,al ;AN000; by message retriever
1556 mov ax,0002h ;an000; message #2
1557 mov bx,stdout
;an000; print to standard out
1558 mov cx,0002h ;an000; two replaceable parms
1559 mov si,offset sublist1
;an000; offset of sublist
1560 mov di,0000h ;an000; no buffer for user input
1561 mov dl,no_input
;AN000; no user input to mes. ret.
1562 mov dh,utility_msg_class
;an000; utility messages only
1564 call SYSDISPMSG
;AN000; ;go to message retriever
1565 pop es ;an000; restore es
1566 assume
es:nothing
;an000; tell the linker
1567 pop cx ;an000; restore cx
1568 pop bx ;an000; restore bx
1573 inc bx ;an000; next drive in vector
1574 inc cl ;AN000; next letter to address
1579 pop es ;an000; restore es
1580 assume
es:code ;an000; tell the linker
1586 ;******************************* CNS *******************************************
1587 ; Purpose: Exit program
1588 ; Input : Error code AL
1589 ; Output : Error code AL
1591 ;******************************* CNS *******************************************
1596 mov ah,EXIT
;AC000;(4ch) RETURN TO DOS WITH ERRORLEVEL
1597 int DOS_CALL
;AC000;
1603 ;******************************* CNS *******************************************
1605 ;=========================================================================
1606 ; PARSE_ERR : This routine prints out the applicable parse
1607 ; error that is returned in AX by SYSPARSE.
1609 ; Inputs : AX - Parse error number to be printed
1610 ; Outputs : Applicable parse error
1611 ;=========================================================================
1614 PARSE_ERR proc
near ;an000; dms;report an error
1616 push ax ;an000;save ax
1617 mov byte ptr ds:[si],0 ;an002;null terminate string
1618 mov dx,Parm_Ptr1
;an002;move ptr to sublist
1619 mov Parse_Sub_Off
,dx ;an002;
1620 mov Parse_Sub_Seg
,ds ;an002;
1622 mov bx,STDERR
;an000;print to standard out
1623 mov cx,1 ;an002;1 replaceable parm
1624 mov si,offset Parse_Sublist
;an002;sublist for replaceable parm
1625 mov dl,NO_INPUT
;AN000;no input to message retriever
1626 mov dh,PARSE_ERR_CLASS
;AN000;display parse errors
1627 call SYSDISPMSG
;AN000;display error
1629 pop ax ;AN000;restore errcode
1630 call EXIT_PROG
;AN000;exit ASSIGN due to error
1633 PARSE_ERR endp
;an000; dms;
1635 Release_Environment proc
near ;an001; dms;
1637 push ax ;save regs ;an001; dms;
1638 push bx ; ;an001; dms;
1639 push es ; ;an001; dms;
1640 mov ah,Get_PSP
; get the PSP segment ;an001; dms;
1641 int 21h
; invoke INT 21h ;an001; dms;
1642 mov es,bx ; BX contains PSP segment - put in ES ;an001; dms;
1643 mov bx,word ptr es:[PSP_Env
]; get segment of environmental vector ;an001; dms;
1644 mov es,bx ; place segment in ES for Free Memory ;an001; dms;
1645 mov ah,Dealloc
; Free Allocated Memory ;an001; dms;
1646 int 21h
; invoke INT 21h ;an001; dms;
1647 pop es ; restore regs ;an001; dms;
1648 pop bx ; ;an001; dms;
1649 pop ax ; ;an001; dms;
1651 ret ; return to caller ;an001; dms;
1653 Release_Environment endp
1655 Close_Handles proc
near ;close handles 0-4 ;an001; dms;
1657 push bx ;save regs ;an001; dms;
1658 mov bx,4 ;close all standard files ;an001; dms;
1662 mov ah,Handle_Close
;close file handle ;an001; dms;
1663 int 21h
; ;an001; dms;
1664 dec bx ;next handle ;an001; dms;
1665 jns Close_Handle_Loop
;continue ;an001; dms;
1667 pop bx ;restore regs ;an001; dms;
1670 Close_Handles endp
; ;an001; dms;
1672 Get_Vectors proc
near ;get original vectors ;an001; dms;
1674 mov ax,(GET_INTERRUPT_VECTOR
SHL 8)+ABS_DISK_READ
;(3525h) get the int 25 vector
1677 mov word ptr [int25_vec
],bx
1678 mov word ptr [int25_vec
+2],es
1680 mov ax,(GET_INTERRUPT_VECTOR
SHL 8)+ABS_DISK_WRITE
;(3526H) get the int 26 vector
1683 mov word ptr [int26_vec
],bx
1684 mov word ptr [int26_vec
+2],es
1686 mov ax,(GET_INTERRUPT_VECTOR
SHL 8)+MULTIPLEXOR
;(352FH) get the int 2F vector
1689 mov word ptr [int2F_vec
],bx
1690 mov word ptr [int2F_vec
+2],es
1692 mov ax,(Get_Interrupt_Vector
SHL 8)+DOS_CALL
;(3521H)
1695 mov word ptr cs:[system
],bx
1696 mov word ptr cs:[system
+2],es
1698 MOV AX,(MPLEX_ID
SHL 8)+MPLEX_R_U_THERE
;(0600H) See if we are in system already
1699 INT MULTIPLEXOR
;(2FH)
1702 ; $IF NZ ;AC000; NOT INSTALLED
1705 call RELOAD_CURDIR
;AC000;
1712 Get_Vectors endp
; ;an001; dms;
1715 Set_Vectors proc
near ;set to new vectors ;an001; dms;
1717 mov ah,Get_Default_Drive
;(19H)
1721 mov [default_drive
],al ;NS- add one to the value to get the
1722 call mapdrv1
;NS- actual drive value before mapping
1724 dec al ;NS- dec one to setup for select function
1725 mov dl,al ;select its replacement
1726 mov ah,Set_Default_Drive
;(0EH)
1729 mov dx,offset int25
;set int 25 vector
1730 mov ax,(SET_INTERRUPT_VECTOR
SHL 8) + ABS_DISK_READ
;(2525H)
1733 mov dx,offset int26
;set int 26 vector
1734 mov ax,(SET_INTERRUPT_VECTOR
SHL 8) + ABS_DISK_WRITE
;(2526H)
1736 ;NS- Hook in resident portion
1737 mov dx,offset int2F
;set int 2F vector
1738 mov ax,(SET_INTERRUPT_VECTOR
SHL 8) + MULTIPLEXOR
;(252FH)
1741 mov dx,offset ASSIGN_HANDLER
;set the system int vector
1742 mov ax,(SET_INTERRUPT_VECTOR
SHL 8) + DOS_CALL
;(2521H)
1745 call Close_Handles
;close handles 0-4 ;an001; dms;
1746 call Release_Environment
;release the environmental vector ;an001; dms;
1748 mov dx,prog_size
;end but stay resident
1749 mov ah,KEEP_PROCESS
;(31h) NS- ASSIGN loaded in mem
1754 Set_Vectors endp
; ;an001; dms;
1759 MSG_SERVICES
<MSGDATA
>
1760 msg_services
<NEARmsg
>
1761 msg_services
<LOADmsg
>
1762 msg_services
<DISPLAYmsg
,CHARmsg
>
1763 msg_services
<assign
.cla
,assign
.cl1
>
1764 msg_services
<assign
.cl2
>