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
|