summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/MACRO.ASM
blob: dea0771ddc678ed455a8812c633281389f88a3b1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
;	SCCSID = @(#)macro.asm	1.2 85/07/11
TITLE	MACRO - Pathname and macro related internal routines
NAME	MACRO
;
;   $AssignOper     written
;   FIND_DPB	    written
;   InitCDS	    written
;   $UserOper	    written
;   GetVisDrv	    written
;   GetThisDrv	    written
;   GetCDSFromDrv   written
;
;   Revision history:
;
;	Created: MZ 4 April 1983
;		 MZ 18 April 1983   Make TransFCB handle extended FCBs
;		 AR 2 June 1983     Define/Delete macro for NET redir.
;		 MZ 3 Nov 83	    Fix InitCDS to reset length to 2
;		 MZ 4 Nov 83	    Fix NetAssign to use STRLEN only
;		 MZ 18 Nov 83	    Rewrite string processing for subtree
;				    aliasing.
;
;   MSDOS performs several types of name translation.  First, we maintain for
;   each valid drive letter the text of the current directory on that drive.
;   For invalid drive letters, there is no current directory so we pretend to
;   be at the root.  A current directory is either the raw local directory
;   (consisting of drive:\path) or a local network directory (consisting of
;   \\machine\path.  There is a limit on the point to which a ..  is allowed.
;
;   Given a path, MSDOS will transform this into a real from-the-root path
;   without .  or ..  entries.	Any component that is > 8.3 is truncated to
;   this and all * are expanded into ?'s.
;
;   The second part of name translation involves subtree aliasing.  A list of
;   subtree pairs is maintained by the external utility SUBST.	The results of
;   the previous 'canonicalization' are then examined to see if any of the
;   subtree pairs is a prefix of the user path.  If so, then this prefix is
;   replaced with the other subtree in the pair.
;
;   A third part involves mapping this "real" path into a "physical" path.  A
;   list of drive/subtree pairs are maintained by the external utility JOIN.
;   The output of the previous translation is examined to see if any of the
;   subtrees in this list are a prefix of the string.  If so, then the prefix
;   is replaced by the appropriate drive letter.  In this manner, we can
;   'mount' one device under another.
;
;   The final form of name translation involves the mapping of a user's
;   logical drive number into the internal physical drive.  This is
;   accomplished by converting the drive number into letter:CON, performing
;   the above translation and then converting the character back into a drive
;   number.
;
;   curdir_list     STRUC
;   curdir_text     DB	    DIRSTRLEN DUP (?) ; text of assignment and curdir
;   curdir_flags    DW	    ?		    ; various flags
;   curdir_devptr   DD	    ?		    ; local pointer to DPB or net device
;   curdir_ID	    DW	    ?		    ; cluster of current dir (net ID)
;		    DW	    ?
;   curdir_end	    DW	    ?		    ; end of assignment
;   curdir_list     ENDS
;   curdir_netID    EQU     DWORD PTR curdir_ID
;   ;Flag word masks
;   curdir_isnet    EQU     1000000000000000B
;   curdir_inuse    EQU     0100000000000000B
;
;   There are two main entry points:  TransPath and TransFCB.  TransPath will
;   take a path and form the real text of the pathname with all .  and ..
;   removed.  TransFCB will translate an FCB into a path and then invoke
;   TransPath.
;
;   Implementation note:  CURDIR_End field points to the point in the text
;   string where the user may back up to via ..  It is the location of a
;   separator character.  For the root, it points at the leading /.  For net
;   assignments it points at the end (nul) of the initial assignment:
;   A:/     \\foo\bar	    \\foo\bar\blech\bozo
;     ^ 	     ^		     ^
; A: -> d: /path/ path/ text
;
;   A000    version 4.00  Jan. 1988

.xlist
;
; get the appropriate segment definitions
;
include dosseg.asm

CODE	SEGMENT BYTE PUBLIC  'CODE'
	ASSUME	SS:DOSGroup,CS:DOSGroup

.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
.cref
.list
.sall

Installed = TRUE

	I_need	ThisCDS,DWORD		; pointer to CDS used
	I_need	CDSAddr,DWORD		; pointer to CDS table
	I_need	CDSCount,BYTE		; number of CDS entries
	I_need	CurDrv,BYTE		; current macro assignment (old
					; current drive)
	I_need	NUMIO,BYTE		; Number of physical drives
	I_need	fSharing,BYTE		; TRUE => no redirection allowed
	I_need	DummyCDS,80h		; buffer for dummy cds
	I_need	DIFFNAM,BYTE		; flag for MyName being set
	I_need	MYNAME,16		; machine name
	I_need	MYNUM,WORD		; machine number
	I_need	DPBHEAD,DWORD		; beginning of DPB chain
	I_need	EXTERR_LOCUS,BYTE	; Extended Error Locus
	I_need	DrvErr,BYTE		; drive error

BREAK <$AssignOper -- Set up a Macro>

; Inputs:
;	AL = 00 get assign mode 		    (ReturnMode)
;	AL = 01 set assign mode 		    (SetMode)
;	AL = 02 get attach list entry		    (GetAsgList)
;	AL = 03 Define Macro (attch start)
;	    BL = Macro type
;	       = 0 alias
;	       = 1 file/device
;	       = 2 drive
;	       = 3 Char device -> network
;	       = 4 File device -> network
;	    DS:SI -> ASCIZ source name
;	    ES:DI -> ASCIZ destination name
;	AL = 04 Cancel Macro
;	    DS:SI -> ASCIZ source name
;	AL = 05 Modified get attach list entry
;	AL = 06 Get ifsfunc item
;	AL = 07 set in_use of a drive's CDS
;	     DL = drive number, 0=default  0=A,,
;	AL = 08 reset in_use of a drive's CDS
;	     DL = drive number, 0=A, 1=B,,,
; Function:
;	Do macro stuff
; Returns:
;	Std Xenix style error return

	procedure   $AssignOper,NEAR
ASSUME	DS:NOTHING,ES:NOTHING

	CMP	AL,7				      ; set in_use ?		;AN000;
	JNZ	chk08				      ; no			;AN000;
srinuse:									;AN000;
	PUSH	AX				      ; save al 		;AN000;
	MOV	AL,DL				      ; AL= drive id		;AN000;
	CALL	GetCDSFromDrv			      ; ds:si -> cds		;AN000;
	POP	AX				      ; 			;AN000;
	JC	baddrv				      ; bad drive		;AN000;
	CMP	WORD PTR [SI.curdir_devptr],0	      ; dpb ptr =0 ?		;AN000;
	JZ	baddrv				      ;     no			;AN000;
	CMP	AL,7				      ; set ?			;AN000;
	JNZ	resetdrv			      ; no			;AN000;
	OR	[SI.curdir_flags],curdir_inuse	      ; set in_use		;AN000;
	JMP	SHORT okdone			      ; 			;AN000;
resetdrv:									;AN000;
	AND	[SI.curdir_flags],NOT curdir_inuse    ; reset in_use		;AN000;
	JMP	SHORT okdone			      ; 			;AN000;
baddrv: 									;AN000;
	MOV	AX,error_invalid_drive		      ; error			;AN000;
	JMP	SHORT ASS_ERR			      ; 			;AN000;
chk08:										;AN000;
	CMP	AL,8				      ; reset inuse ?		;AN000;
	JZ	srinuse 			      ; yes			;AN000;

	IF	NOT INSTALLED
	transfer NET_ASSOPER
	ELSE
	PUSH	AX
	MOV	AX,(multnet SHL 8) OR 30
	INT	2FH
	POP	BX			; Don't zap error code in AX
	JC	ASS_ERR
okdone:
	transfer SYS_RET_OK

ASS_ERR:
	transfer SYS_RET_ERR
	ENDIF

EndProc $AssignOper

Break <FIND_DPB - Find a DPB from a drive number>

;   Inputs:	AL has drive number A = 0
;   Outputs:	Carry Set
;		    No DPB for this drive number
;		Carry Clear
;		    DS:SI points to DPB for drive
;   registers modified: DS,SI
Procedure FIND_DPB,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	LDS	SI,[DPBHEAD]
DPB_LOOP:
	CMP	SI,-1
	JZ	NO_DPB
	CMP	AL,[SI.dpb_drive]
	retz				; Carry clear
	LDS	SI,[SI.dpb_next_dpb]
	JMP	DPB_LOOP

NO_DPB:
	STC
	return
EndProc FIND_DPB

Break <InitCDS - set up an empty CDS>

;   Inputs:	ThisCDS points to CDS
;		AL has uppercase drive letter
;   Outputs:	ThisCDS is now empty
;		ES:DI point to CDS
;		Carry set if no DPB associated with drive
;   registers modified: AH,ES,DI
Procedure InitCDS,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	MOV	AH,':'
	PUSH	AX
	SUB	AL,"A"-1                ; A = 1
	CMP	[NUMIO],AL
	POP	AX
	LES	DI,[THISCDS]
	MOV	ES:[DI.curdir_flags],0	; "free" CDS
	JB	RET_OK			; Drive does not map a physical drive
	MOV	WORD PTR ES:[DI.curdir_text],AX
	PUSH	AX
	MOV	AX,"\"
	MOV	WORD PTR ES:[DI.curdir_text+2],AX   ; NUL terminate
	POP	AX
	OR	ES:[DI.curdir_flags],curdir_inuse
	MOV	ES:[DI.curdir_END],2	; MZ 3 Nov 83
	MOV	ES:[DI.curdir_ID],0
	MOV	ES:[DI.curdir_ID+2],0
	PUSH	AX
	PUSH	DS
	PUSH	SI
	SUB	AL,"A"                  ; A = 0
	invoke	FIND_DPB
	JC	PRET			; OOOOPPPPPSSSS!!!!
	MOV	WORD PTR ES:[DI.curdir_devptr],SI
	MOV	WORD PTR ES:[DI.curdir_devptr+2],DS
PRET:
	POP	SI
	POP	DS
	POP	AX
RET_OK: return
EndProc InitCDS

Break <$UserOper - get/set current user ID (for net)>

;
;   $UserOper - retrieve or initiate a user id string.	MSDOS will only
;	maintain this string and do no verifications.
;
;   Inputs:	AL has function type (0-get 1-set 2-printer-set 3-printer-get
;				      4-printer-set-flags,5-printer-get-flags)
;		DS:DX is user string pointer (calls 1,2)
;		ES:DI is user buffer (call 3)
;		BX is assign index (calls 2,3,4,5)
;		CX is user number (call 1)
;		DX is flag word (call 4)
;   Outputs:	If AL = 0 then the current user string is written to DS:DX
;			and user CX is set to the user number
;		If AL = 3 then CX bytes have been put at input ES:DI
;		If AL = 5 then DX is flag word

Procedure   $UserOper,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	PUSH	AX
	SUB	AL,1			; quick dispatch on 0,1
	POP	AX
	JB	UserGet 		; return to user the string
	JZ	UserSet 		; set the current user
	CMP	AL,5			; test for 2,3,4 or 5
	JBE	UserPrint		; yep
	MOV	EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
	error	error_Invalid_Function	; not 0,1,2,3

UserGet:
; Transfer MYNAME to DS:DX
; Set Return CX to MYNUM
	PUSH	DS			; switch registers
	POP	ES
	MOV	DI,DX			; destination
	MOV	CX,[MYNUM]		; Get number
	invoke	get_user_stack
	MOV	[SI.User_CX],CX 	; Set number return
	Context DS			; point to DOSGroup
ASSUME	DS:DOSGROUP
	MOV	SI,OFFSET DOSGroup:MyName   ; point source to user string
UserMove:
ASSUME	DS:NOTHING
	MOV	CX,15
	REP	MOVSB			; blam.
	XOR	AX,AX			; 16th byte is 0
	STOSB
UserBye:
	transfer    sys_ret_ok		; no errors here

UserSet:
ASSUME	DS:NOTHING
; Transfer DS:DX to MYNAME
; CX to MYNUM
	MOV	[MYNUM],CX
	MOV	SI,DX			; user space has source
	Context ES
	MOV	DI,OFFSET DOSGroup:MyName   ; point dest to user string
	INC	[DiffNam]		  ; signal change
	JMP	UserMove

UserPrint:
	ASSUME	ES:NOTHING
IF NOT Installed
	transfer PRINTER_GETSET_STRING
ELSE
	PUSH	AX
	MOV	AX,(multNET SHL 8) OR 31
	INT	2FH
	POP	DX			; Clean stack
	JNC	OKPA
	transfer SYS_RET_ERR

OKPA:
	transfer SYS_RET_OK
ENDIF

EndProc $UserOper

Break	<GetVisDrv - return visible drive>

;
;   GetVisDrv - correctly map non-spliced inuse drives
;
;   Inputs:	AL has drive identifier (0=default)
;   Outputs:	Carry Set - invalid drive/macro
;		Carry Clear - AL has physical drive (0=A)
;		    ThisCDS points to CDS
;   Registers modified: AL

Procedure   GetVisDrv,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	CALL	GetThisDrv		; get inuse drive
	retc
	SaveReg <DS,SI>
	LDS	SI,ThisCDS
	TEST	[SI].curdir_flags,curdir_splice
	RestoreReg  <SI,DS>
	retz				; if not spliced, return OK
	MOV	[DrvErr],error_invalid_drive ;IFS.				;AN000;
	STC				; signal error
	return
EndProc GetVisDrv

Break <Getthisdrv - map a drive designator (0=def, 1=A...)>

;
;   GetThisDrv - look through a set of macros and return the current drive and
;	macro pointer
;
;   Inputs:	AL has drive identifier (1=A, 0=default)
;   Outputs:
;		Carry Set - invalid drive/macro
;		Carry Clear - AL has physical drive (0=A)
;		   ThisCDS points to macro
;   Registers modified: AL

Procedure   GetThisDrv,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	OR	AL,AL			; are we using default drive?
	JNZ	GetMap			; no, go get the CDS pointers
	MOV	AL,[CurDrv]		; get the current drive
	INC	AL			; Counteract next instruction
GetMap:
	DEC	AL			; 0 = A
	SaveReg <DS,SI> 		; save world
	mov	[EXTERR_LOCUS],errLOC_Disk
	TEST	fSharing,-1		; Logical or Physical?
	JZ	Not_SRVC		; Logical
	SaveReg <AX,ES,DI>
	MOV	WORD PTR ThisCDS,OFFSET DOSGroup:DummyCDS
	MOV	WORD PTR ThisCDS+2,CS	;	ThisCDS = &DummyCDS;
	ADD	AL,'A'
	CALL	InitCDS 		;	InitCDS(c);
	TEST	ES:[DI.curdir_flags],curdir_inuse	; Clears carry
	RestoreReg  <DI,ES,AX>
	JZ	GetBerr 		; Not a physical drive.
	JMP	SHORT GetBye		; carry clear

Not_SRVC:
	invoke	GetCDSFromDrv
	JC	GetBerr2		; Unassigned CDS -> return error already set
	TEST	[SI.curdir_flags],curdir_inuse	; Clears Carry
	JNZ	GetBye			; carry clear
GetBerr:
	MOV	AL,error_not_DOS_disk	;AN000;IFS. Formatted IFS drive
	CMP	WORD PTR [SI.curdir_devptr],0	 ;AN000;IFS. dpb ptr =0 ?
	JNZ	notfat			;AN000;IFS. no
GetBerr2:
	MOV	AL,error_invalid_drive	;AN000;;IFS. invalid FAT drive
notfat: 				;AN000;
	MOV	[DrvErr],AL		;AN000;;IFS. save this for IOCTL
	mov	[EXTERR_LOCUS],errLOC_UNK
	STC
GetBye: RestoreReg  <SI,DS>		; restore world
	return
EndProc GetThisDrv

Break <GetCDSFromDrv - convert a drive number to a CDS pointer>

;
;   GetCDSFromDrv - given a physical drive number, convert it to a CDS
;	pointer, returning an error if the drive number is greater than the
;	number of CDS's
;
;   Inputs:	AL is physical unit # A=0...
;   Outputs:	Carry Set if Bad Drive
;		Carry Clear
;		    DS:SI -> CDS
;		    [THISCDS] = DS:SI
;   Registers modified: DS,SI

Procedure   GetCDSFromDrv,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	CMP	AL,[CDSCount]		; is this a valid designator
	JB	GetCDS			; yes, go get the macro
	STC				; signal error
	return				; bye
GetCDS:
	SaveReg <BX,AX>
	LDS	SI,[CDSAddr]		; get pointer to table
	MOV	BL,SIZE CurDir_list	; size in convenient spot
	MUL	BL			; get net offset
	ADD	SI,AX			; convert to true pointer
	MOV	WORD PTR [ThisCDS],SI	; store convenient offset
	MOV	WORD PTR [ThisCDS+2],DS ; store convenient segment
	RestoreReg  <AX,BX>
	CLC				; no error
	return				; bye!
EndProc GetCDSFromDrv

CODE ends
END