summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DOS
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/DOS')
-rw-r--r--v4.0/src/DOS/ABORT.ASM137
-rw-r--r--v4.0/src/DOS/ALLOC.ASM392
-rw-r--r--v4.0/src/DOS/BUF.ASM982
-rw-r--r--v4.0/src/DOS/CLOSE.ASM432
-rw-r--r--v4.0/src/DOS/CPMIO.ASM448
-rw-r--r--v4.0/src/DOS/CPMIO2.ASM354
-rw-r--r--v4.0/src/DOS/CREATE.ASM380
-rw-r--r--v4.0/src/DOS/CRIT.ASM92
-rw-r--r--v4.0/src/DOS/CTRLC.ASM771
-rw-r--r--v4.0/src/DOS/DELETE.ASM777
-rw-r--r--v4.0/src/DOS/DEV.ASM841
-rw-r--r--v4.0/src/DOS/DINFO.ASM131
-rw-r--r--v4.0/src/DOS/DIR.ASM445
-rw-r--r--v4.0/src/DOS/DIR2.ASM1353
-rw-r--r--v4.0/src/DOS/DIRCALL.ASM415
-rw-r--r--v4.0/src/DOS/DISK.ASM1073
-rw-r--r--v4.0/src/DOS/DISK2.ASM784
-rw-r--r--v4.0/src/DOS/DISK3.ASM662
-rw-r--r--v4.0/src/DOS/DISP.ASM579
-rw-r--r--v4.0/src/DOS/DISPATCH.ASM214
-rw-r--r--v4.0/src/DOS/DOSMES.ASM442
-rw-r--r--v4.0/src/DOS/DOSPRINT.ASM36
-rw-r--r--v4.0/src/DOS/DUP.ASM68
-rw-r--r--v4.0/src/DOS/EXEC.ASM931
-rw-r--r--v4.0/src/DOS/EXTATTR.ASM679
-rw-r--r--v4.0/src/DOS/FAT.ASM695
-rw-r--r--v4.0/src/DOS/FCB.ASM504
-rw-r--r--v4.0/src/DOS/FCBIO.ASM1185
-rw-r--r--v4.0/src/DOS/FCBIO2.ASM722
-rw-r--r--v4.0/src/DOS/FILE.ASM909
-rw-r--r--v4.0/src/DOS/FINFO.ASM286
-rw-r--r--v4.0/src/DOS/GETSET.ASM912
-rw-r--r--v4.0/src/DOS/HANDLE.ASM893
-rw-r--r--v4.0/src/DOS/HIGHSW.ASM29
-rw-r--r--v4.0/src/DOS/IFS.ASM523
-rw-r--r--v4.0/src/DOS/IOCTL.ASM745
-rw-r--r--v4.0/src/DOS/ISEARCH.ASM364
-rw-r--r--v4.0/src/DOS/KSTRIN.ASM690
-rw-r--r--v4.0/src/DOS/LOCK.ASM372
-rw-r--r--v4.0/src/DOS/MACRO.ASM445
-rw-r--r--v4.0/src/DOS/MACRO2.ASM1281
-rw-r--r--v4.0/src/DOS/MAKEFILE221
-rw-r--r--v4.0/src/DOS/MISC.ASM572
-rw-r--r--v4.0/src/DOS/MISC2.ASM594
-rw-r--r--v4.0/src/DOS/MKNODE.ASM890
-rw-r--r--v4.0/src/DOS/MSCODE.ASM16
-rw-r--r--v4.0/src/DOS/MSCONST.ASM153
-rw-r--r--v4.0/src/DOS/MSCPMIO.ASM17
-rw-r--r--v4.0/src/DOS/MSCTRLC.ASM16
-rw-r--r--v4.0/src/DOS/MSDISP.ASM17
-rw-r--r--v4.0/src/DOS/MSDOS.LNK59
-rw-r--r--v4.0/src/DOS/MSDOS.SKL17
-rw-r--r--v4.0/src/DOS/MSHALO.ASM247
-rw-r--r--v4.0/src/DOS/MSINIT.ASM667
-rw-r--r--v4.0/src/DOS/MSIOCTL.ASM5
-rw-r--r--v4.0/src/DOS/MSPROC.ASM15
-rw-r--r--v4.0/src/DOS/MSSW.ASM27
-rw-r--r--v4.0/src/DOS/MS_CODE.ASM614
-rw-r--r--v4.0/src/DOS/MS_TABLE.ASM710
-rw-r--r--v4.0/src/DOS/NSTDOS.ASM7
-rw-r--r--v4.0/src/DOS/OPEN.ASM569
-rw-r--r--v4.0/src/DOS/PARSE.ASM447
-rw-r--r--v4.0/src/DOS/PATH.ASM363
-rw-r--r--v4.0/src/DOS/PRINT.ASM199
-rw-r--r--v4.0/src/DOS/PROC.ASM187
-rw-r--r--v4.0/src/DOS/RENAME.ASM434
-rw-r--r--v4.0/src/DOS/ROM.ASM938
-rw-r--r--v4.0/src/DOS/SEARCH.ASM346
-rw-r--r--v4.0/src/DOS/SEGCHECK.ASM288
-rw-r--r--v4.0/src/DOS/SHARE.ASM151
-rw-r--r--v4.0/src/DOS/SHRPRINT.ASM35
-rw-r--r--v4.0/src/DOS/SRVCALL.ASM306
-rw-r--r--v4.0/src/DOS/STDASW.ASM29
-rw-r--r--v4.0/src/DOS/STDCODE.ASM17
-rw-r--r--v4.0/src/DOS/STDCPMIO.ASM16
-rw-r--r--v4.0/src/DOS/STDCTRLC.ASM15
-rw-r--r--v4.0/src/DOS/STDDATA.ASM33
-rw-r--r--v4.0/src/DOS/STDDISP.ASM16
-rw-r--r--v4.0/src/DOS/STDDOSME.ASM20
-rw-r--r--v4.0/src/DOS/STDIOCTL.ASM5
-rw-r--r--v4.0/src/DOS/STDPROC.ASM15
-rw-r--r--v4.0/src/DOS/STDSW.ASM32
-rw-r--r--v4.0/src/DOS/STDTABLE.ASM16
-rw-r--r--v4.0/src/DOS/STRIN.ASM403
-rw-r--r--v4.0/src/DOS/TIME.ASM380
-rw-r--r--v4.0/src/DOS/UTIL.ASM232
86 files changed, 34329 insertions, 0 deletions
diff --git a/v4.0/src/DOS/ABORT.ASM b/v4.0/src/DOS/ABORT.ASM
new file mode 100644
index 0000000..43268e3
--- /dev/null
+++ b/v4.0/src/DOS/ABORT.ASM
@@ -0,0 +1,137 @@
1; SCCSID = @(#)abort.asm 1.4 85/10/02
2TITLE DOS_ABORT - Internal SFT close all files for proc call for MSDOS
3NAME DOS_ABORT
4
5; Internal Abort call closes all handles and FCBs associated with a process.
6; If process has NET resources a close all is sent out over the net.
7;
8; DOS_ABORT
9;
10; Modification history:
11;
12; Created: ARR 30 March 1983
13;
14
15;
16; get the appropriate segment definitions
17;
18
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xlist
25.xcref
26INCLUDE DOSSYM.INC
27INCLUDE DEVSYM.INC
28.cref
29.list
30
31Installed = TRUE
32
33 I_Need PROC_ID,WORD ; current process ID
34 I_Need USER_ID,WORD ; current user ID
35 i_need CurrentPDB,WORD
36 i_need sft_addr,DWORD
37 i_need THISSFT,DWORD
38 i_need JSHARE,DWORD
39 I_need sftFCB,DWORD ; pointer to SFTs for FCB cache
40
41Break <DOS_ABORT -- CLOSE all files for process>
42
43; Inputs:
44; [CurrentPDB] set to PID of process aborting
45; Function:
46; Close all files and free all SFTs for this PID
47; Returns:
48; None
49; All destroyed except stack
50
51 Procedure DOS_ABORT,NEAR
52 ASSUME DS:NOTHING,ES:NOTHING
53
54 MOV ES,[CurrentPDB]
55 MOV CX,ES:[PDB_JFN_Length] ; Number of JFNs
56reset_free_jfn:
57 MOV BX,CX
58 PUSH CX
59 DEC BX ; get jfn (start with last one)
60
61 invoke $close
62 POP CX
63 LOOP reset_free_jfn ; and do 'em all
64;
65; Note: We do need to explicitly close FCBs. Reasons are as follows: If we
66; are running in the no-sharing no-network environment, we are simulating the
67; 2.0 world and thus if the user doesn't close the file, that is his problem
68; BUT... the cache remains in a state with garbage that may be reused by the
69; next process. We scan the set and blast the ref counts of the FCBs we own.
70;
71; If sharing is loaded, then the following call to close process will
72; correctly close all FCBs. We will then need to walk the list AFTER here.
73;
74; Finally, the following call to NET_Abort will cause an EOP to be sent to all
75; known network resources. These resources are then responsible for cleaning
76; up after this process.
77;
78; Sleazy, eh?
79;
80 context DS
81 CallInstall Net_Abort, multNet, 29
82if installed
83 call JShare + 4 * 4
84else
85 call mftCloseP
86endif
87 assume ds:nothing
88;
89; Scan the FCB cache for guys that belong to this process and zap their ref
90; counts.
91;
92 les di,sftFCB ; grab the pointer to the table
93 mov cx,es:[di].sfCount
94 jcxz FCBScanDone
95 LEA DI,[DI].sfTable ; point at table
96 mov ax,proc_id
97FCBTest:
98 cmp es:[di].sf_PID,ax ; is this one of ours
99 jnz FCBNext ; no, skip it
100 mov es:[di].sf_ref_count,0 ; yes, blast ref count
101FCBNext:
102 add di,size sf_Entry
103 loop FCBTest
104FCBScanDone:
105
106;
107; Walk the SFT to eliminate all busy SFT's for this process.
108;
109 XOR BX,BX
110Scan:
111 push bx
112 invoke SFFromSFN
113 pop bx
114 retc
115 cmp es:[di].sf_ref_count,0
116 jz next
117;
118; we have a SFT that is not free. See if it is for the current process
119;
120 mov ax,proc_id
121 cmp es:[di].sf_pid,ax
122 jnz next
123 mov ax,user_id
124 cmp es:[di].sf_uid,ax
125 jnz next
126;
127; This SFT is labelled as ours.
128;
129 mov es:[di].sf_ref_count,0
130next:
131 inc bx
132 jmp scan
133
134EndProc DOS_Abort
135
136CODE ENDS
137 END
diff --git a/v4.0/src/DOS/ALLOC.ASM b/v4.0/src/DOS/ALLOC.ASM
new file mode 100644
index 0000000..37b6298
--- /dev/null
+++ b/v4.0/src/DOS/ALLOC.ASM
@@ -0,0 +1,392 @@
1; SCCSID = @(#)alloc.asm 1.1 85/04/09
2TITLE ALLOC.ASM - memory arena manager
3NAME Alloc
4;
5; Memory related system calls and low level routines for MSDOS 2.X.
6; I/O specs are defined in DISPATCH.
7;
8; $ALLOC
9; $SETBLOCK
10; $DEALLOC
11; $AllocOper
12; arena_free_process
13; arena_next
14; check_signature
15; Coalesce
16;
17; Modification history:
18;
19; Created: ARR 30 March 1983
20;
21
22.xlist
23;
24; get the appropriate segment definitions
25;
26include dosseg.asm
27
28CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME SS:DOSGROUP,CS:DOSGROUP
30
31.xcref
32INCLUDE DOSSYM.INC
33INCLUDE DEVSYM.INC
34.cref
35.list
36
37.lall
38
39SUBTTL memory allocation utility routines
40PAGE
41;
42; arena data
43;
44 i_need arena_head,WORD ; seg address of start of arena
45 i_need CurrentPDB,WORD ; current process data block addr
46 i_need FirstArena,WORD ; first free block found
47 i_need BestArena,WORD ; best free block found
48 i_need LastArena,WORD ; last free block found
49 i_need AllocMethod,BYTE ; how to alloc first(best)last
50 I_need EXTERR_LOCUS,BYTE ; Extended Error Locus
51
52;
53; arena_free_process
54; input: BX - PID of process
55; output: free all blocks allocated to that PID
56;
57 procedure arena_free_process,NEAR
58 ASSUME DS:NOTHING,ES:NOTHING
59 MOV DI,arena_signature
60 MOV AX,[arena_head]
61 CALL Check_Signature ; ES <- AX, check for valid block
62
63arena_free_process_loop:
64 retc
65 PUSH ES
66 POP DS
67 CMP DS:[arena_owner],BX ; is block owned by pid?
68 JNZ arena_free_next ; no, skip to next
69 MOV DS:[arena_owner],DI ; yes... free him
70
71arena_free_next:
72 CMP BYTE PTR DS:[DI],arena_signature_end
73 ; end of road, Jack?
74 retz ; never come back no more
75 CALL arena_next ; next item in ES/AX carry set if trash
76 JMP arena_free_process_loop
77
78EndProc arena_free_process
79
80;
81; arena_next
82; input: DS - pointer to block head
83; output: AX,ES - pointers to next head
84; carry set if trashed arena
85;
86 procedure arena_next,NEAR
87 ASSUME DS:NOTHING,ES:NOTHING
88 MOV AX,DS ; AX <- current block
89 ADD AX,DS:[arena_size] ; AX <- AX + current block length
90 INC AX ; remember that header!
91;
92; fall into check_signature and return
93;
94; CALL check_signature ; ES <- AX, carry set if error
95; RET
96EndProc arena_next
97
98;
99; check_signature
100; input: AX - address of block header
101; output: ES=AX, carry set if signature is bad
102;
103 procedure check_signature,NEAR
104 ASSUME DS:NOTHING,ES:NOTHING
105 MOV ES,AX ; ES <- AX
106 CMP BYTE PTR ES:[DI],arena_signature_normal
107 ; IF next signature = not_end THEN
108 retz ; GOTO ok
109 CMP BYTE PTR ES:[DI],arena_signature_end
110 ; IF next signature = end then
111 retz ; GOTO ok
112 STC ; set error
113 return
114
115EndProc Check_signature
116
117;
118; Coalesce - combine free blocks ahead with current block
119; input: DS - pointer to head of free block
120; output: updated head of block, AX is next block
121; carry set -> trashed arena
122;
123 procedure Coalesce,NEAR
124 ASSUME DS:NOTHING,ES:NOTHING
125 CMP BYTE PTR DS:[DI],arena_signature_end
126 ; IF current signature = END THEN
127 retz ; GOTO ok
128 CALL arena_next ; ES, AX <- next block, Carry set if error
129 retc ; IF no error THEN GOTO check
130
131coalesce_check:
132 CMP ES:[arena_owner],DI
133 retnz ; IF next block isnt free THEN return
134 MOV CX,ES:[arena_size] ; CX <- next block size
135 INC CX ; CX <- CX + 1 (for header size)
136 ADD DS:[arena_size],CX ; current size <- current size + CX
137 MOV CL,ES:[DI] ; move up signature
138 MOV DS:[DI],CL
139 JMP coalesce ; try again
140EndProc Coalesce
141
142SUBTTL $Alloc - allocate space in memory
143PAGE
144;
145; Assembler usage:
146; MOV BX,size
147; MOV AH,Alloc
148; INT 21h
149; AX:0 is pointer to allocated memory
150; BX is max size if not enough memory
151;
152; Description:
153; Alloc returns a pointer to a free block of
154; memory that has the requested size in paragraphs.
155;
156; Error return:
157; AX = error_not_enough_memory
158; = error_arena_trashed
159;
160 procedure $ALLOC,NEAR
161 ASSUME DS:NOTHING,ES:NOTHING
162
163 EnterCrit critMem
164 XOR AX,AX
165 MOV DI,AX
166
167 MOV [FirstArena],AX ; init the options
168 MOV [BestArena],AX
169 MOV [LastArena],AX
170
171 PUSH AX ; alloc_max <- 0
172 MOV AX,[arena_head] ; AX <- beginning of arena
173 CALL Check_signature ; ES <- AX, carry set if error
174 JC alloc_err ; IF error THEN GOTO err
175
176alloc_scan:
177 PUSH ES
178 POP DS ; DS <- ES
179 CMP DS:[arena_owner],DI
180 JZ alloc_free ; IF current block is free THEN examine
181
182alloc_next:
183 CMP BYTE PTR DS:[DI],arena_signature_end
184 ; IF current block is last THEN
185 JZ alloc_end ; GOTO end
186 CALL arena_next ; AX, ES <- next block, Carry set if error
187 JNC alloc_scan ; IF no error THEN GOTO scan
188
189alloc_err:
190 POP AX
191
192alloc_trashed:
193 LeaveCrit critMem
194 error error_arena_trashed
195
196alloc_end:
197 CMP [FirstArena],0
198 JNZ alloc_do_split
199
200alloc_fail:
201 invoke get_user_stack
202 POP BX
203 MOV [SI].user_BX,BX
204 LeaveCrit critMem
205 error error_not_enough_memory
206
207alloc_free:
208 CALL coalesce ; add following free block to current
209 JC alloc_err ; IF error THEN GOTO err
210 MOV CX,DS:[arena_size]
211
212 POP DX ; check for max found size
213 CMP CX,DX
214 JNA alloc_test
215 MOV DX,CX
216
217alloc_test:
218 PUSH DX
219 CMP BX,CX ; IF BX > size of current block THEN
220 JA alloc_next ; GOTO next
221
222 CMP [FirstArena],0
223 JNZ alloc_best
224 MOV [FirstArena],DS ; save first one found
225alloc_best:
226 CMP [BestArena],0
227 JZ alloc_make_best ; initial best
228 PUSH ES
229 MOV ES,[BestArena]
230 CMP ES:[arena_size],CX ; is size of best larger than found?
231 POP ES
232 JBE alloc_last
233alloc_make_best:
234 MOV [BestArena],DS ; assign best
235alloc_last:
236 MOV [LastArena],DS ; assign last
237 JMP alloc_next
238
239;
240; split the block high
241;
242alloc_do_split_high:
243 MOV DS,[LastArena]
244 MOV CX,DS:[arena_size]
245 SUB CX,BX
246 MOV DX,DS
247 JE alloc_set_owner ; sizes are equal, no split
248 ADD DX,CX ; point to next block
249 MOV ES,DX ; no decrement!
250 DEC CX
251 XCHG BX,CX ; bx has size of lower block
252 JMP alloc_set_sizes ; cx has upper (requested) size
253
254;
255; we have scanned memory and have found all appropriate blocks
256; check for the type of allocation desired; first and best are identical
257; last must be split high
258;
259alloc_do_split:
260 CMP BYTE PTR [AllocMethod], 1
261 JA alloc_do_split_high
262 MOV DS,[FirstArena]
263 JB alloc_get_size
264 MOV DS,[BestArena]
265alloc_get_size:
266 MOV CX,DS:[arena_size]
267 SUB CX,BX ; get room left over
268 MOV AX,DS
269 MOV DX,AX ; save for owner setting
270 JE alloc_set_owner ; IF BX = size THEN (don't split)
271 ADD AX,BX
272 INC AX ; remember the header
273 MOV ES,AX ; ES <- DS + BX (new header location)
274 DEC CX ; CX <- size of split block
275alloc_set_sizes:
276 MOV DS:[arena_size],BX ; current size <- BX
277 MOV ES:[arena_size],CX ; split size <- CX
278 MOV BL,arena_signature_normal
279 XCHG BL,DS:[DI] ; current signature <- 4D
280 MOV ES:[DI],BL ; new block sig <- old block sig
281 MOV ES:[arena_owner],DI
282
283alloc_set_owner:
284 MOV DS,DX
285 MOV AX,[CurrentPDB]
286 MOV DS:[arena_owner],AX
287 MOV AX,DS
288 INC AX
289 POP BX
290 LeaveCrit critMem
291 transfer SYS_RET_OK
292
293EndProc $alloc
294
295SUBTTL $SETBLOCK - change size of an allocated block (if possible)
296PAGE
297;
298; Assembler usage:
299; MOV ES,block
300; MOV BX,newsize
301; MOV AH,setblock
302; INT 21h
303; if setblock fails for growing, BX will have the maximum
304; size possible
305; Error return:
306; AX = error_invalid_block
307; = error_arena_trashed
308; = error_not_enough_memory
309; = error_invalid_function
310;
311 procedure $SETBLOCK,NEAR
312 ASSUME DS:NOTHING,ES:NOTHING
313 EnterCrit critMem
314 MOV DI,arena_signature
315 MOV AX,ES
316 DEC AX
317 CALL check_signature
318 JNC setblock_grab
319
320setblock_bad:
321 JMP alloc_trashed
322
323setblock_grab:
324 MOV DS,AX
325 CALL coalesce
326 JC setblock_bad
327 MOV CX,DS:[arena_size]
328 PUSH CX
329 CMP BX,CX
330 JBE alloc_get_size
331 JMP alloc_fail
332EndProc $setblock
333
334SUBTTL $DEALLOC - free previously allocated piece of memory
335PAGE
336;
337; Assembler usage:
338; MOV ES,block
339; MOV AH,dealloc
340; INT 21h
341;
342; Error return:
343; AX = error_invalid_block
344; = error_arena_trashed
345;
346 procedure $DEALLOC,NEAR
347 ASSUME DS:NOTHING,ES:NOTHING
348 EnterCrit critMem
349 MOV DI,arena_signature
350 MOV AX,ES
351 DEC AX
352 CALL check_signature
353 JC dealloc_err
354 MOV ES:[arena_owner],DI
355 LeaveCrit critMem
356 transfer SYS_RET_OK
357
358dealloc_err:
359 LeaveCrit critMem
360 error error_invalid_block
361EndProc $DEALLOC
362
363SUBTTL $AllocOper - get/set allocation mechanism
364PAGE
365;
366; Assembler usage:
367; MOV AH,AllocOper
368; MOV BX,method
369; MOV AL,func
370; INT 21h
371;
372; Error return:
373; AX = error_invalid_function
374;
375 procedure $AllocOper,NEAR
376 ASSUME DS:NOTHING,ES:NOTHING
377 CMP AL,1
378 JB AllocOperGet
379 JZ AllocOperSet
380 MOV EXTERR_LOCUS,errLoc_mem ; Extended Error Locus
381 error error_invalid_function
382AllocOperGet:
383 MOV AL,BYTE PTR [AllocMethod]
384 XOR AH,AH
385 transfer SYS_RET_OK
386AllocOperSet:
387 MOV [AllocMethod],BL
388 transfer SYS_RET_OK
389EndProc $AllocOper
390
391CODE ENDS
392 END
diff --git a/v4.0/src/DOS/BUF.ASM b/v4.0/src/DOS/BUF.ASM
new file mode 100644
index 0000000..f6a6b7d
--- /dev/null
+++ b/v4.0/src/DOS/BUF.ASM
@@ -0,0 +1,982 @@
1; SCCSID = @(#)buf.asm 1.1 85/04/09
2TITLE BUF - MSDOS buffer management
3NAME BUF
4; Low level routines for buffer cache management
5;
6; GETCURHEAD
7; SET_MAP_PAGE
8; SAVE_MAP
9; RESTORE_MAP
10; SETVISIT
11; ScanPlace
12; PLACEBUF
13; PLACEHEAD
14; PointComp
15; GETBUFFR
16; GETBUFFRB
17; FlushBuf
18; BufWrite
19; SKIPVISIT
20; SET_RQ_SC_PARMS
21;
22; Revision history:
23;
24; AN000 version 4.00 Jan. 1988
25; A004 PTM 3765 -- Disk reset failed
26
27; NEW PROCS FOR BUFFERS FIX:
28
29; SAVE_USER_MAP
30; RESTORE_USER_MAP
31; DETECT_COLLISION
32; SETUP_EMS_BUFFERS
33;
34
35
36;
37; get the appropriate segment definitions
38;
39.xlist
40INCLUDE dosseg.asm
41
42CODE SEGMENT BYTE PUBLIC 'CODE'
43 ASSUME SS:DOSGROUP,CS:DOSGROUP
44
45.xcref
46INCLUDE DOSSYM.INC
47INCLUDE DEVSYM.INC
48include version.inc
49.cref
50.list
51
52Installed = TRUE
53
54 i_need BuffHead,DWORD
55 i_need PreRead,WORD
56 i_need LastBuffer,DWORD
57 i_need CurBuf,DWORD
58 i_need WPErr,BYTE
59 i_need ALLOWED,BYTE
60 i_need FAILERR,BYTE
61 i_need HIGH_SECTOR,WORD ; DOS 4.00 >32mb ;AN000;
62 i_need CurHashEntry,DWORD ; DOS 4.00 current Hash entry ;AN000;
63 i_need BUF_HASH_PTR,DWORD ; DOS 4.00 Hash table pointer ;AN000;
64 i_need BUF_HASH_COUNT,WORD ; DOS 4.00 Hash table entries ;AN000;
65 i_need SC_CACHE_PTR,DWORD ; DOS 4.00 seconadary cache table ;AN000;
66 i_need SC_CACHE_COUNT,WORD ; DOS 4.00 secondary cache entries ;AN000;
67 i_need BUF_EMS_MODE,BYTE ; DOS 4.00 EMS mode ;AN000;
68 i_need BUF_EMS_HANDLE,WORD ; DOS 4.00 buffer EMS handle ;AN000;
69 i_need SC_SECTOR_SIZE,WORD ; DOS 4.00 sector size ;AN000;
70 i_need SC_DRIVE,BYTE ; DOS 4.00 drive ;AN000;
71 i_need ACT_PAGE,WORD ; DOS 4.00 active logical EMS page ;AN000;
72 i_need DOS34_FLAG,WORD ; DOS 4.00 common flag ;AN000;
73 i_need BUF_EMS_SEG_CNT,WORD ; DOS 4.00 EMS seg count ;AN000;
74 i_need BUF_EMS_MAP_BUFF,BYTE ; DOS 4.00 EMS map buffer ;AN000;
75 i_need FIRST_BUFF_ADDR,WORD ; DOS 4.00 beginning of the chain ;AN000;
76 i_need BUF_EMS_PAGE_FRAME,WORD ; DOS 4.00 EMS page frame ;AN000;
77
78IF BUFFERFLAG
79 i_need BUF_EMS_PFRAME,WORD
80 i_need BUF_EMS_LAST_PAGE,WORD
81 i_need BUF_EMS_FIRST_PAGE,WORD
82 i_need BUF_EMS_SAFE_FLAG,byte
83 i_need BUF_EMS_NPA640,WORD
84 i_need NEXTADD,WORD
85 i_need DMAADD,DWORD
86 i_need BYTCNT1,WORD
87 i_am BUF_EMS_MAP_BUF,12,<0,0,0,0,0,0,0,0,0,0,0,0>
88 i_am CURADD,WORD
89 i_am low_ems_buf,512
90 extrn SAVE_USER_MAP:near
91 extrn RESTORE_USER_MAP:near
92ENDIF
93
94
95Break <GETCURHEAD -- Get current buffer header>
96
97; Inputs:
98; DX= sector number (LOW)
99; [HIGH_SECTOR]= sector number (HIGH)
100; Function:
101; Hash into a buffer group and activate the extended memory if
102; necessary
103; Outputs:
104; [CurHashEntry] = current Hash entry addr
105; DS:DI = 1st buffer addr of the current Hash entry
106; No other registers altered
107
108 procedure GETCURHEAD,NEAR
109 ASSUME DS:NOTHING,ES:NOTHING
110
111 PUSH DX ;LB. save regs ;AN000;
112 PUSH AX ;LB. ;AN000;
113 PUSH BX ;LB. ;AN000;
114 MOV AX,DX ;LB. ;AN000;
115; MOV DX,[HIGH_SECTOR] ;LB. HASH(sector#) and get entry # ;AN000;
116 XOR DX,DX ;LB. to avoid divide overflow ;AN000;
117 DIV [BUF_HASH_COUNT] ;LB. get remainder ;AN000;
118 ADD DX,DX ;LB. 8 bytes per entry ;AN000;
119 ADD DX,DX ;LB. ;AN000;
120 ADD DX,DX ;LB. times 8 ;AN000;
121
122 LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000;
123 ADD DI,DX ;LB position to entry ;AN000;
124Map_Entry2:
125 MOV WORD PTR [CurHashEntry+2],DS ;LB. update current Hash entry ptr ;AN000;
126 MOV WORD PTR [CurHashEntry],DI ;LB. ;AN000;
127 MOV WORD PTR [LASTBUFFER],-1 ;LB. invalidate last buffer ;AN000;
128 MOV BX,[DI.EMS_PAGE_NUM] ;LB. logical page ;AN000;
129
130IF NOT BUFFERFLAG
131 LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000;
132 MOV [FIRST_BUFF_ADDR],DI ;LB. 1/19/88 save first buffer addr ;AN000;
133 CALL SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000;
134ELSE
135 push ax
136 mov ax, [NEXTADD]
137 mov [CURADD], ax
138 pop ax
139 CALL SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000;
140 LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000;
141 MOV [FIRST_BUFF_ADDR],DI ;LB. 1/19/88 save first buffer addr ;AN000;
142ENDIF
143
144 ;AN000;
145 POP BX ;LB. ;AN000;
146 POP AX ;LB. ;AN000;
147 POP DX ;LB. ;AN000;
148 return ;LB. ;AN000;
149EndProc GETCURHEAD ;AN000;
150
151 ;AN000;
152Break <SET_MAP_PAGE - map handle and page > ;AN000;
153; Inputs: ;AN000;
154; BX= logical page ;AN000;
155; Function: ;AN000;
156; Map handle and logical page to frame 0 page 0 ;AN000;
157; Outputs: ;AN000;
158; AH=0 success ;AN000;
159; No other registers altered ;AN000;
160 ;AN000;
161Procedure SET_MAP_PAGE,NEAR ;AN000;
162 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
163
164; int 3
165 ;AN000;
166 CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
167 JZ No_map ;LB. no ;AN000;
168
169IF NOT BUFFERFLAG
170 CMP [ACT_PAGE],BX ;LB. already mapped ? ;AN000;
171 JZ No_map ;LB. yes ;AN000;
172ENDIF
173 MOV [ACT_PAGE],BX ;LB. save active page mapped ;AN000;
174
175IF BUFFERFLAG
176 cmp [BUF_EMS_SAFE_FLAG], 1
177 je no_coll
178; int 3
179 call detect_collision
180no_coll:
181ENDIF
182
183 MOV DX,[BUF_EMS_HANDLE] ;LB. ;AN000;
184 MOV AH,44H ;LB. activate current handle ;AN000;
185 MOV AL,BYTE PTR [BUF_EMS_PAGE_FRAME] ;LB. page frame number ;AN000;
186 INT 67H ;LB. ;AN000;
187No_map: ;AN000;
188 return ;AN000;
189EndProc SET_MAP_PAGE ;AN000;
190 ;AN000;
191
192IF BUFFERFLAG
193
194Break <SAVE_MAP - save map > ;AN000;
195; Inputs: ;AN000;
196; none ;AN000;
197; Function: ;AN000;
198; save map ;AN000;
199; Outputs: ;AN000;
200; none ;AN000;
201; No other registers altered ;AN000;
202 ;AN000;
203Procedure SAVE_MAP,NEAR ;AN000;
204 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
205 ;AN000;
206 CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
207 JZ No_save ;LB. no ;AN000;
208 MOV [ACT_PAGE],-1 ;LB. invalidate active page ;AN000;
209 MOV WORD PTR [LASTBUFFER],-1 ;LB. and last buffer pointer ;AN000;
210 PUSH AX ;LB. save regs ;AN000;
211 PUSH DS ;LB. save regs ;AN000;
212 PUSH ES ;LB. ;AN000;
213 PUSH SI ;LB. ;AN000;
214 PUSH DI ;LB. ;AN000;
215 MOV SI,OFFSET DOSGROUP:BUF_EMS_SEG_CNT ;LB. ;AN000;
216 MOV DI,OFFSET DOSGROUP:BUF_EMS_MAP_BUF ;LB. ;AN000;
217
218 PUSH CS
219 POP ES
220 PUSH CS ;LB. ;AN000;
221 POP DS ;LB. ds:si -> ems seg count ;AN000;
222
223 MOV AX,4F00H ;LB. save map ;AN000;
224 EnterCrit critDisk ;LB. enter critical section ;AN000;
225 INT 67H ;LB. ;AN000;
226 LeaveCrit critDisk ;LB. leave critical section ;AN000;
227 POP DI ;LB. ;AN000;
228 POP SI ;LB. restore regs ;AN000;
229 POP ES ;LB. ;AN000;
230 POP DS ;LB. ;AN000;
231 POP AX ;LB. restore ;AN000;
232No_save: ;AN000;
233 return ;AN000;
234EndProc SAVE_MAP ;AN000;
235 ;AN000;
236
237Break <RESTORE_MAP- retore map > ;AN000;
238; Inputs: ;AN000;
239; none ;AN000;
240; Function: ;AN000;
241; restore_map ;AN000;
242; Outputs: ;AN000;
243; none ;AN000;
244; No other registers altered ;AN000;
245 ;AN000;
246Procedure RESTORE_MAP,NEAR ;AN000;
247 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
248 ;AN000;
249 CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
250 JZ No_restore ;LB. no ;AN000;
251 PUSH AX ;LB. save regs ;AN000;
252 PUSH DS ;LB. save regs ;AN000;
253 PUSH SI ;LB. ;AN000;
254 MOV SI,OFFSET DOSGROUP:BUF_EMS_MAP_BUF ;LB. ;AN000;
255
256 PUSH CS
257 POP DS
258 MOV AX,4F01H ;LB. restore map ;AN000;
259 EnterCrit critDisk ;LB. enter critical section ;AN000;
260 INT 67H ;LB. ;AN000;
261 LeaveCrit critDisk ;LB. leave critical section ;AN000;
262 POP SI ;LB. restore regs ;AN000;
263 POP DS ;LB. ;AN000;
264 POP AX ;LB. ;AN000;
265No_restore: ;AN000;
266 return ;AN000;
267EndProc RESTORE_MAP ;AN000;
268
269ENDIF
270 ;AN000;
271 ;AN000;
272
273Break <SCANPLACE, PLACEBUF -- PUT A BUFFER BACK IN THE POOL>
274
275; Inputs:
276; Same as PLACEBUF
277; Function:
278; Save scan location and call PLACEBUF
279; Outputs:
280; DS:DI Points to saved scan location
281; SI destroyed, other registers unchanged
282
283 procedure ScanPlace,near
284ASSUME DS:NOTHING,ES:NOTHING
285
286;; PUSH ES
287;; LES SI,[DI.buf_link] ; Save scan location
288 MOV SI,[DI.buf_next] ; Save scan location
289 CALL PLACEBUF
290;; PUSH ES
291;; POP DS ; Restore scan location
292 MOV DI,SI
293;; POP ES
294 return
295EndProc ScanPlace
296
297; Rewritten PLACEBUF (LKR), eliminates loops
298;
299; Input:
300; DS:DI points to buffer (DS->BUFFINFO array, DI=offset in array)
301; Function:
302; Remove buffer from queue and re-insert it in proper place.
303; NO registers altered
304
305 procedure PLACEBUF,NEAR
306ASSUME DS:NOTHING,ES:NOTHING
307
308; invoke save_world
309 push AX ;Save only regs we modify ;AN000;
310 push BX ;AN000;
311 push SI ;AN000;
312 push ES ;AN000;
313
314 les SI,[CurHashEntry] ;ES:SI -> Current Hash entry ;AN000;
315 mov BX,word ptr ES:[SI.BUFFER_BUCKET] ;BX = offset of head of list ;AN000;
316
317 cmp [DI.buf_next],BX ;Buf = last? ;AN000;
318 je nret ;Yes, special case ;AN000;
319 cmp DI,BX ;Buf = first? ;AN000;
320 je bufloop ;Yes, special case ;AN000;
321 mov SI,[DI.buf_prev] ;No, SI = prior Buf ;AN000;
322 mov AX,[DI.buf_next] ;Now delete Buf from list ;AN000;
323 mov [SI.buf_next],AX ;AN000;
324 push SI ;Save si ;AN000;
325 mov SI,[DI.buf_next] ;Update backward pointer ;AN000;
326 mov AX,[DI.buf_prev] ; ;AN000;
327 mov [SI.buf_prev],AX ; ;AN000;
328 pop si ;Restore si ;AN000;
329lookend: ;(label is now a misnomer) ;AN000;
330 mov SI,[BX.buf_prev] ;SI-> last buffer ;AN000;
331 mov [SI.buf_next],DI ;Add Buf to end of list ;AN000;
332 mov [BX.buf_prev],DI ;AN000;
333 mov [DI.buf_prev],SI ;Update linkage in Buf too ;AN000;
334 mov [DI.buf_next],BX ;AN000;
335nret: ;AN000;
336 ;AN000;
337; invoke restore_world ;AN000;
338 pop ES ;Restore regs we modified ;AN000;
339 pop SI ;AN000;
340 pop BX ;AN000;
341 pop AX ;AN000;
342 ;AN000;
343 cmp [DI.buf_ID],-1 ; Buffer FREE? ;AN000;
344 retnz ; No ;AN000;
345 invoke PLACEHEAD ; Buffer is free, belongs at hea;AN000;
346 return ;AN000;
347bufloop: ;(label is now a misnomer) ;AN000;
348 mov BX,[DI.buf_next] ;Set new head position ;AN000;
349 mov word ptr ES:[SI.BUFFER_BUCKET],BX ;AN000;
350 jmp nret ;Continue with repositioning ;AN000;
351
352EndProc PLACEBUF
353
354; SAME AS PLACEBUF except places buffer at head
355; NOTE:::::: ASSUMES THAT BUFFER IS CURRENTLY THE LAST
356; ONE IN THE LIST!!!!!!!
357; Rewritten PLACEBUF, takes buffer from end of list to head of list
358
359 procedure PLACEHEAD,NEAR ;AN000;
360ASSUME DS:NOTHING,ES:NOTHING ;AN000;
361 push ES ;AN000;
362 push SI ;AN000;
363 les SI,[CurHashEntry] ;AN000;
364 mov word ptr ES:[SI.BUFFER_BUCKET],DI ;AN000;
365 pop SI ;AN000;
366 pop ES ;AN000;
367 return ;AN000;
368EndProc PLACEHEAD ;AN000;
369
370
371Break <POINTCOMP -- 20 BIT POINTER COMPARE>
372
373; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality
374; DO NOT USE FOR < or >
375; No Registers altered
376
377 procedure PointComp,NEAR
378ASSUME DS:NOTHING,ES:NOTHING
379
380 CMP SI,DI
381 retnz
382 PUSH CX
383 PUSH DX
384 MOV CX,DS
385 MOV DX,ES
386 CMP CX,DX
387 POP DX
388 POP CX
389 return
390EndProc PointComp
391
392Break <GETBUFFR -- GET A SECTOR INTO A BUFFER>
393
394; Input:
395; AL = 0 means sector must be pre-read
396; ELSE no pre-read
397; DX = Desired physical sector number (LOW)
398; [HIGH_SECTOR]= Desired physical sector number (HIGH)
399; ES:BP = Pointer to drive parameters
400; [ALLOWED] set in case of INT 24
401; Function:
402; Get the specified local sector into one of the I/O buffers
403; And shuffle the queue
404; Output:
405; [CURBUF] Points to the Buffer for the sector
406; THE BUFFER TYPE FIELD OF buf_flags = 0, caller must set it
407; Carry set if error (currently user FAILed to INT 24)
408; DS,DX,ES:BP unchanged, all other registers destroyed
409
410 procedure GETBUFFR,NEAR
411 DOSAssume CS,<DS>,"GetBuffr"
412 ASSUME ES:NOTHING
413
414 XOR SI,SI
415
416 entry GETBUFFRB
417
418 Assert ISDPB,<ES,BP>,"GetBuffr"
419 MOV [PREREAD],AX
420 MOV AL,ES:[BP.dpb_drive]
421 LDS DI,[LASTBUFFER]
422ASSUME DS:NOTHING
423 MOV CX,[HIGH_SECTOR] ; F.C. >32mb ;AN000;
424 CMP DI,-1 ; Recency pointer valid?
425 JZ SKBUF ; No
426
427 CMP DX,WORD PTR [DI.buf_sector]
428 JNZ SKBUF ; Wrong sector
429 CMP CX,WORD PTR [DI.buf_sector+2] ; F.C. >32mb ;AN000;
430 JNZ SKBUF ; F.C. >32mb ;AN000;
431 CMP AL,[DI.buf_ID]
432 JNZ SKBUF ; Wrong Drive
433
434 JMP JUSTBUF ; Just asked for same buffer
435SKBUF:
436 CALL GETCURHEAD ;LB. get cuurent Hash entry ;AN000;
437; LDS DI,[BUFFHEAD]
438NXTBFF:
439 CMP DX,WORD PTR [DI.buf_sector] ; F.C. >32mb ;AN000;
440 JNZ BUMP
441 CMP CX,WORD PTR [DI.buf_sector+2] ; F.C. >32mb ;AN000;
442 JNZ BUMP ; F.C. >32mb ;AN000;
443 CMP AL,[DI.buf_ID]
444if not bufferflag
445 JZ SETINF
446else
447 jnz bump
448 jmp setinf
449endif
450BUMP:
451 mov DI,[DI.buf_next] ;;;;;;1/19/88 ;AN000;
452 cmp DI,[FIRST_BUFF_ADDR] ;;;;;;1/19/88 ;AN000;
453 JNZ NXTBFF
454;;;; LDS DI,[CurHashEntry] ;LB. secondary cache's use ;AN000;
455;;;; LDS DI,[DI.BUFFER_BUCKET] ;LB. ;AN000;
456 ; LDS DI,[BUFFHEAD]
457 PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000;
458 PUSH SI
459 PUSH DX
460 PUSH BP
461 PUSH ES
462 CALL BUFWRITE ; Write out the dirty buffer
463 POP ES
464 POP BP
465 POP DX
466 POP SI
467 POP [HIGH_SECTOR] ;F.C. >32mb ;AN000;
468if not bufferflag
469 JC GETBERR
470else
471 jnc skip_getberr
472 jmp getberr
473skip_getberr:
474endif
475 CALL SET_RQ_SC_PARMS ;LB. set parms ;AN000;
476 XOR AH,AH ; initial flags
477 TEST BYTE PTR [PREREAD],-1 ; Read in the new sector
478 JNZ SETBUF
479 LEA BX,[DI.BufInSiz] ; Point at buffer
480 MOV CX,1
481 PUSH SI
482 PUSH DI
483 PUSH DX
484; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88
485if bufferflag
486; int 3
487 cmp [buf_ems_mode], -1
488 jz normread
489 push bx
490 push ds ; save ds:bx --> ems_buffer
491 push cs
492 pop ds
493 mov bx, offset dosgroup:low_ems_buf ; ds:bx --> low_ems_buffer
494normread:
495endif
496 OR SI,SI
497 JZ NORMSEC
498 invoke FATSECRD
499 MOV AH,buf_isFAT ; Set buf_flags
500 JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs
501NORMSEC:
502 invoke DREAD ; Buffer is marked free if read barfs
503 MOV AH,0 ; Set buf_flags to no type, DO NOT XOR!
504GOTTHESEC: ; Carry set by either FATSECRD or DREAD
505if bufferflag
506 pushf
507 jc skipreadtrans
508 cmp [buf_ems_mode], -1
509 je skipreadtrans
510
511 popf
512 pop ds
513 pop bx ; restore ems_buffer pointer
514 pushf
515
516 push cx ; save regs to be used by rep mov
517 push ds
518 push es
519
520 mov di, bx
521 push ds
522 pop es ; es:di --> ems_buf
523 mov si, offset dosgroup:low_ems_buf
524 push cs
525 pop ds ; ds:si --> low_ems_buf
526 mov cx, 512/2
527 rep movsw
528
529 pop es ; restore regs.
530 pop ds
531 pop cx
532skipreadtrans:
533 popf
534endif
535 POP DX
536 POP DI
537 POP SI
538 JC GETBERR
539SETBUF:
540 MOV CX,[HIGH_SECTOR] ; F.C. >32mb ;AN000;
541 MOV WORD PTR [DI.buf_sector+2],CX ; F.C. >32mb ;AN000;
542 MOV WORD PTR [DI.buf_sector],DX ; F.C. >32mb ;AN000;
543 MOV WORD PTR [DI.buf_DPB],BP
544 MOV WORD PTR [DI.buf_DPB+2],ES
545 MOV AL,ES:[BP.dpb_drive]
546 MOV WORD PTR [DI.buf_ID],AX ; Sets buf_flags too, to AH
547SETINF:
548 MOV [DI.buf_wrtcnt],1 ; Default to not a FAT sector ;AC000;
549 XOR AX,AX ;>32mb ;AN000;
550 OR SI,SI
551 JZ SETSTUFFOK
552 MOV AL,ES:[BP.dpb_FAT_count]
553 MOV [DI.buf_wrtcnt],AL ;>32mb ;AN000;
554 MOV AX,ES:[BP.dpb_FAT_size]
555SETSTUFFOK:
556 MOV [DI.buf_wrtcntinc],AX ;>32mb ;AC000;
557 CALL PLACEBUF
558JUSTBUF:
559 MOV WORD PTR [CURBUF+2],DS
560 MOV WORD PTR [LASTBUFFER+2],DS
561 MOV WORD PTR [CURBUF],DI
562 MOV WORD PTR [LASTBUFFER],DI
563 CLC
564GETBERR:
565 Context DS
566 return
567EndProc GETBUFFR
568
569Break <FLUSHBUF -- WRITE OUT DIRTY BUFFERS>
570
571; Input:
572; DS = DOSGROUP
573; AL = Physical unit number local buffers only
574; = -1 for all units and all remote buffers
575; Function:
576; Write out all dirty buffers for unit, and flag them as clean
577; Carry set if error (user FAILed to I 24)
578; Flush operation completed.
579; DS Preserved, all others destroyed (ES too)
580
581 procedure FlushBuf,NEAR
582 DOSAssume CS,<DS>,"FlushBuf"
583 ASSUME ES:NOTHING
584
585 MOV AH,-1
586; LDS DI,[BUFFHEAD]
587ASSUME DS:NOTHING
588
589 LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000;
590 MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000;
591 XOR DX,DX ;LB. set initial index to 0 ;AN000;
592
593NXTBUFF2:
594 PUSH CX ;LB. save Hash entry count ;AN000;
595 TEST [DOS34_FLAG],FROM_DISK_RESET ;MS. from disk reset ;AN004;
596 JNZ Zapzap ;MS. yes ;AN004;
597 CMP [DI.Dirty_Count],0 ;LB. dirty entry ? ;AN000;
598 JZ getnext ;LB. no ;AN000;
599Zapzap: ;AN004;
600 PUSH DS ;LB. save regs ;AN000;
601 PUSH DI ;LB. ;AN000;
602 invoke Map_Entry ;LB. ds:di -> first buffer addr ;AN000;
603NXTBUFF:
604 CALL CHECKFLUSH ; Ignore Carry return from CHECKFLUSH.
605 ; FAILERR is set if user FAILed.
606 PUSH AX
607 MOV AL,[DI.buf_ID]
608 CMP AL,BYTE PTR [WPERR]
609 JZ ZAP
610 TEST [DOS34_FLAG],FROM_DISK_RESET ;MS. from disk reset ;AN000;
611 JNZ Zap ;MS. yes ;AN000;
612
613NOZAP:
614 POP AX
615 mov DI,[DI.buf_next] ;;;;1/19/88 ;AN000;
616 CMP DI,[FIRST_BUFF_ADDR] ;;;;1/19/88 ;AN000;
617 JNZ NXTBUFF
618
619 POP DI ;LB. ;AN000;
620 POP DS ;LB. ;AN000;
621getnext:
622 ADD DI,size BUFFER_HASH_ENTRY ;LB. position to next entry ;AN000;
623 POP CX ;LB. restore entry count ;AN000;
624 LOOP NXTBUFF2 ;LB. get next entry buffer ;AN000;
625 Context DS
626 CMP [FAILERR],0
627 JNZ FLSHBad ; Carry clear if JMP
628 return
629FlshBad:
630 STC ; Return error if user FAILed
631 return
632Zap:
633 MOV WORD PTR [DI.buf_ID],00FFH ; Invalidate buffer, it is inconsistent
634 JMP NoZap
635
636EndProc FlushBuf
637
638 procedure CHECKFLUSH,NEAR
639ASSUME DS:NOTHING,ES:NOTHING
640; Carry set if problem (currently user FAILed to I 24)
641
642 Assert ISBUF,<DS,DI>,"CheckFlush"
643 CMP [DI.buf_ID],AH
644 retz ; Skip free buffers, carry clear
645 CMP AH,AL
646 JZ DOBUFFER ; Do all dirty buffers
647 CMP AL,[DI.buf_ID]
648 CLC
649 retnz ; Buffer not for this unit or SFT
650DOBUFFER:
651 TEST [DI.buf_flags],buf_dirty
652 retz ; Buffer not dirty, carry clear by TEST
653 PUSH AX
654 PUSH WORD PTR [DI.buf_ID]
655 CALL BUFWRITE
656 POP AX
657 JC LEAVE_BUF ; Leave buffer marked free (lost).
658 AND AH,NOT buf_dirty ; Buffer is clean, clears carry
659 MOV WORD PTR [DI.buf_ID],AX
660LEAVE_BUF:
661 POP AX ; Search info
662 return
663EndProc CHECKFLUSH
664
665Break <BUFWRITE -- WRITE OUT A BUFFER IF DIRTY>
666
667; Input:
668; DS:DI Points to the buffer
669; Function:
670; Write out all the buffer if dirty.
671; Output:
672; Buffer marked free
673; Carry set if error (currently user FAILed to I 24)
674; DS:DI Preserved, ALL others destroyed (ES too)
675
676 procedure BufWrite,NEAR
677ASSUME DS:NOTHING,ES:NOTHING
678
679 Assert ISBUF,<DS,DI>,"BufWrite"
680 MOV AX,00FFH
681 XCHG AX,WORD PTR [DI.buf_ID] ; Free, in case write barfs
682 CMP AL,0FFH
683 retz ; Buffer is free, carry clear.
684 TEST AH,buf_dirty
685 retz ; Buffer is clean, carry clear.
686 invoke DEC_DIRTY_COUNT ; LB. decrement dirty count
687 CMP AL,BYTE PTR [WPERR]
688 retz ; If in WP error zap buffer
689 MOV [SC_DRIVE],AL ;LB. set it for invalidation ;AN000;
690 LES BP,[DI.buf_DPB]
691 LEA BX,[DI.BufInSiz] ; Point at buffer
692 MOV DX,WORD PTR [DI.buf_sector] ;F.C. >32mb ;AN000;
693 MOV CX,WORD PTR [DI.buf_sector+2] ;F.C. >32mb ;AN000;
694 MOV [HIGH_SECTOR],CX ;F.C. >32mb ;AN000;
695 MOV CL,[DI.buf_wrtcnt] ;>32mb ;AC000;
696; MOV AL,CH ; [DI.buf_wrtcntinc]
697 XOR CH,CH
698 MOV AX,[DI.buf_wrtcntinc] ;>32mb ;AC000;
699 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
700 TEST [DI.buf_flags],buf_isDATA
701 JZ NO_IGNORE
702 OR [ALLOWED],allowed_IGNORE
703NO_IGNORE:
704 PUSH DI ; Save buffer pointer
705 XOR DI,DI ; Indicate failure
706WRTAGAIN:
707 SaveReg <DI,CX,AX>
708 MOV CX,1
709 SaveReg <BX,DX,DS>
710; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88
711
712if bufferflag
713; int 3
714 cmp [buf_ems_mode], -1
715 jz skipwritetrans
716
717 push es
718 push di
719 push si
720 push cx
721
722 mov si, bx ; ds:si --> ems_buffer
723 mov di, offset dosgroup:low_ems_buf
724 push cs
725 pop es ; es:di --> low_ems_buffer
726 mov cx, 512/2
727 rep movsw
728
729 pop cx
730 pop si
731 pop di
732 pop es
733
734 push ds
735 push bx
736 mov bx, offset dosgroup:low_ems_buf
737 push cs
738 pop ds ; ds:bx --> low_ems_buffer
739skipwritetrans:
740endif
741
742 invoke DWRITE ; Write out the dirty buffer
743
744if bufferflag
745 pushf ; save carry flag from DWRITE
746 cmp [buf_ems_mode], -1
747 jz normwrite
748 popf ; need to get at stack
749 pop bx ; ds:bx --> ems_buffer
750 pop ds
751 pushf ; put it back, so we can pop it
752normwrite:
753 popf ; restore carry flag
754endif
755
756 RestoreReg <DS,DX,BX>
757 RestoreReg <AX,CX,DI>
758 JC NOSET
759 INC DI ; If at least ONE write succeedes, the operation
760NOSET: ; succeedes.
761 ADD DX,AX
762 LOOP WRTAGAIN
763 OR DI,DI ; Clears carry
764 JNZ BWROK ; At least one write worked
765 STC ; DI never got INCed, all writes failed.
766BWROK:
767 POP DI
768 return
769EndProc BufWrite
770
771Break <SET_RQ_SC_PARMS-set requesting drive for SC>
772
773; Input:
774; ES:BP = drive parameter block
775; Function:
776; Set requesting drive, and sector size
777; Output:
778; [SC_SECTOR_SIZE]= drive sector size
779; [SC_DRIVE]= drive #
780;
781; All registers preserved
782
783 procedure SET_RQ_SC_PARMS,NEAR
784ASSUME DS:NOTHING,ES:NOTHING
785
786 CMP [SC_CACHE_COUNT],0 ;LB. do it only secondary cache exists ;AN000;
787 JZ nosec ;LB. ;AN000;
788 PUSH DX ;LB. save dx ;AN000;
789 MOV DX,ES:[BP.dpb_sector_size] ;LB. save sector size ;AN000;
790 MOV [SC_SECTOR_SIZE],DX ;LB. ;AN000;
791 MOV DL,ES:[BP.dpb_drive] ;LB. save drive # ;AN000;
792 MOV [SC_DRIVE],DL ;LB. ;AN000;
793 ;AN000;
794 POP DX ;LB. restore dx ;AN000;
795
796nosec:
797 return
798EndProc SET_RQ_SC_PARMS ;LB. return ;AN000;
799
800Break <INC_DIRTY_COUNT-increment dirty count>
801
802; Input:
803; none
804; Function:
805; increment dirty buffers count
806; Output:
807; dirty buffers count in the current hash entry is incremented
808;
809; All registers preserved
810
811 procedure INC_DIRTY_COUNT,NEAR
812ASSUME DS:NOTHING,ES:NOTHING
813
814 PUSH DS ;LB. save regs ;AN000;
815 PUSH SI ;LB. ;AN000;
816 LDS SI,[CurHashEntry] ;LB. get current hash entry ;AN000;
817 INC [SI.Dirty_Count] ;LB. add 1 ;AN000;
818 POP SI ;LB. restore regs ;AN000;
819 POP DS ;LB. ;AN000;
820 return
821EndProc INC_DIRTY_COUNT ;LB. return ;AN000;
822
823Break <DEC_DIRTY_COUNT-decrement dirty count>
824
825; Input:
826; none
827; Function:
828; decrement dirty buffers count
829; Output:
830; dirty buffers count in the current hash entry is decremented
831;
832; All registers preserved
833
834 procedure DEC_DIRTY_COUNT,NEAR
835ASSUME DS:NOTHING,ES:NOTHING
836
837 PUSH DS ;LB. save regs ;AN000;
838 PUSH SI ;LB. ;AN000;
839 LDS SI,[CurHashEntry] ;LB. get current hash entry ;AN000;
840 CMP [SI.Dirty_Count],0 ;LB. in case if 0 ;AN000;
841 JZ nodec ;LB. do nothing ;AN000;
842 DEC [SI.Dirty_Count] ;LB. sub 1 ;AN000;
843nodec:
844 POP SI ;LB. restore regs ;AN000;
845 POP DS ;LB. ;AN000;
846 return
847EndProc DEC_DIRTY_COUNT ;LB. return ;AN000;
848
849
850Break <MAP_ENTRY- map the buffers of this entry>
851
852; Input:
853; DS:DI ponits to hash entry
854; Function:
855; map the buferrs of this entry
856; Output:
857; the buffers are mapped
858;
859; All registers preserved
860
861 procedure Map_Entry,NEAR
862ASSUME DS:NOTHING,ES:NOTHING
863
864 PUSH DX ;LB. save regs ;AN000;
865 PUSH AX ;LB. ;AN000;
866 PUSH BX ;LB. ;AN000;
867 JMP Map_Entry2 ;LB. ;AN000;
868EndProc Map_Entry ;LB. ;AN000;
869
870
871IF BUFFERFLAG
872
873;-------------------------------------------------------------------------
874; Procedure name : detect collision
875; Inputs : [DMAADD] - user Xaddr
876; [CURADD] - current offset
877; [BYTCNT1] - for partial sector read
878; SAFE_FLAG - cleared - indicating that the
879; current page is unsafe.
880;
881; Outputs : es - physical page segment to use
882; di - corresponding page number
883; SAFE_FLAG is set is a collision is detected
884; and the current page is switched form
885; LAST_PAGE to FIRST_PAGE.
886;---------------------------------------------------------------------------
887;
888
889Procedure detect_collision, near
890ASSUME DS:NOTHING,ES:NOTHING
891
892 push ax
893 push bx
894 push cx
895
896 cmp [BUF_EMS_MODE], -1
897 jz fin_detect_coll
898
899 mov ax, [CURADD] ; current offset
900
901 cmp [BYTCNT1], 0
902 je no_partial_sector
903 add ax, [BYTCNT1]
904
905no_partial_sector:
906 mov cl, 4
907 shr ax, cl ; convert to paragraphs
908 mov bx, word ptr [DMAADD+2] ; get original segment
909 add ax, bx ; get current segment
910
911 and ax, 0fc00h ; get ems page of current segment
912 cmp ax, [BUF_EMS_LAST_PAGE] ; is the current segment = last segment
913 jne fin_detect_coll ; page is still safe
914
915; int 3
916 push ax
917 mov ax, word ptr [DMAADD]
918 mov ax, [NEXTADD]
919 mov ax, [CURADD]
920 mov ax, [BYTCNT1]
921 pop ax
922
923 call restore_user_map
924 mov word ptr [LASTBUFFER], -1
925 mov ax, [BUF_EMS_FIRST_PAGE]
926 mov [BUF_EMS_PFRAME], ax
927 mov ax, [BUF_EMS_FIRST_PAGE+2]
928 mov [BUF_EMS_PAGE_FRAME], ax
929 mov [BUF_EMS_SAFE_FLAG], 1
930 call Setup_EMS_buffers
931 call save_user_map
932
933fin_detect_coll:
934 pop cx
935 pop bx
936 pop ax
937 ret
938
939EndProc detect_collision
940
941Procedure Setup_EMS_Buffers,Near
942 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
943
944 cmp [BUF_EMS_MODE], -1
945 jz setup_ems_ret
946
947 push bx
948 push cx
949 push ax
950 push ds
951 push di
952
953 mov bx, [BUF_HASH_COUNT] ; # of hash table entries
954 lds di, [BUF_HASH_PTR] ; ds:di -> hash table
955
956 xor cx, cx
957
958next_bucket:
959 mov ax, [BUF_EMS_PFRAME]
960 mov word ptr ds:[di.BUFFER_BUCKET+2], ax
961 add di, 8 ; next has entry.
962 inc cx
963 cmp cx, bx
964 jne next_bucket
965
966 pop di
967 pop ds
968 pop ax
969 pop cx
970 pop bx
971
972setup_ems_ret:
973 ret
974
975EndProc Setup_EMS_Buffers
976
977ENDIF
978
979
980CODE ENDS
981 END
982 \ No newline at end of file
diff --git a/v4.0/src/DOS/CLOSE.ASM b/v4.0/src/DOS/CLOSE.ASM
new file mode 100644
index 0000000..8156ac8
--- /dev/null
+++ b/v4.0/src/DOS/CLOSE.ASM
@@ -0,0 +1,432 @@
1; SCCSID = @(#)close.asm 1.1 85/04/09
2TITLE DOS_CLOSE/COMMIT - Internal SFT close and commit call for MSDOS
3NAME DOS_CLOSE
4; Internal Close and Commit calls to close a local or NET SFT.
5;
6; DOS_CLOSE
7; DOS_COMMIT
8; FREE_SFT
9; SetSFTTimes
10;
11; Revision history:
12;
13; AN000 version 4.00 Jan. 1988
14; A005 PTM 3718 --- lost clusters when fastopen installed
15; A011 PTM 4766 --- C2 fastopen problem
16
17;
18; get the appropriate segment definitions
19;
20.xlist
21include dosseg.asm
22
23CODE SEGMENT BYTE PUBLIC 'CODE'
24 ASSUME SS:DOSGROUP,CS:DOSGROUP
25
26.xcref
27INCLUDE DOSSYM.INC
28INCLUDE DEVSYM.INC
29.cref
30.list
31
32Installed = TRUE
33
34 I_need Attrib,BYTE
35 i_need THISSFT,DWORD
36 i_need CURBUF,DWORD
37 i_need THISDRV,BYTE
38 i_need ALLOWED,BYTE
39 i_need EXTERR_LOCUS,BYTE
40 I_need FailErr,BYTE
41 I_Need PROC_ID,WORD
42 I_Need USER_ID,WORD
43 i_need JShare,DWORD
44 i_need HIGH_SECTOR,WORD ;F.C. >32mb
45 i_need OLD_FIRSTCLUS,WORD ;F.O. >32mb
46if debug
47 I_need BugLev,WORD
48 I_need BugTyp,WORD
49include bugtyp.asm
50endif
51
52Break <DOS_CLOSE -- CLOSE FILE from SFT>
53
54; Inputs:
55; [THISSFT] set to the SFT for the file being used
56; Function:
57; Close the indicated file via the SFT
58; Returns:
59; sf_ref_count decremented otherwise
60; ES:DI point to SFT
61; Carry set if error
62; AX has error code
63; DS preserved, others destroyed
64
65 procedure DOS_CLOSE,NEAR
66 DOSAssume CS,<DS>,"DOS_Close"
67 ASSUME ES:NOTHING
68
69 LES DI,[THISSFT]
70 Assert ISSFT,<ES,DI>,<"DOS_CLOSE">
71 fmt TypAccess,LevBUSY,<"$p: CLOSE SFT: $x:$x\n">,<ES,DI>
72 MOV BX,ES:[DI.sf_flags]
73;
74; Network closes are handled entirely by the net code.
75;
76 TEST BX,sf_isnet
77 JZ LocalClose
78; invoke OWN_SHARE ;IFS. IFS owns share ? ;AN000;
79; JZ noshare ;IFS. yes ;AN000;
80; EnterCrit critDisk ;IFS. ;AN000;
81; CALL SetSFTTimes ;IFS. set time for all SFT ;AN000;
82; LeaveCrit critDisk ;IFS. ;AN000;
83noshare:
84 CallInstall Net_Close,multnet,6
85; JC nomore ;IFS. error ;AN000;
86; invoke OWN_SHARE ;IFS. IFS owns share ? ;AN000;
87; JZ nomore ;IFS. yes ;AN000;
88; invoke ShareEnd ;IFS. remove SFT entry from share ;AN000;
89nomore:
90 return
91
92;
93; All closes release the sharing information.
94; No commit releases sharing information
95;
96; All closes decrement the ref count.
97; No commit decrements the ref count.
98;
99LocalClose:
100 EnterCrit critDisk
101 CALL SetSFTTimes
102 CALL Free_SFT ; dec ref count or mark as busy
103
104 TEST BX,devid_device ;FS. device ? ;AN000;
105 JNZ nofastsk ;FS. yes ;AN000;
106 MOV CX,ES:[DI.sf_firclus] ;FS. cx= first cluster ;AN000;
107 OR CX,CX ;FS. cx=0 ? ;AN000;
108 JZ nofastsk ;FS. yes, dont do it ;AN000;
109 LDS SI,ES:[DI.sf_devptr] ;FS. ;AN000;
110 MOV DL,[SI.dpb_drive] ;FS. dl= drive ;AN000;
111 invoke FastSeek_Close ;FS. invoke fastseek ;AN000;
112nofastsk:
113 Context DS
114 SaveReg <AX,BX>
115 invoke ShareEnd
116 RestoreReg <BX,AX>
117;
118; Commit enters here. AX from commit MUST be <> 1, BX is flags word
119;
120CloseEntry:
121 PUSH AX
122;
123; File clean or device does not get stamped nor disk looked at.
124;
125 TEST BX,devid_file_clean + devid_device
126 JZ rdir
127 JMP Free_SFT_OK ; either clean or device
128;
129; Retrieve the directory entry for the file
130;
131rdir:
132 CALL DirFromSFT
133ASSUME DS:NOTHING
134 MOV AL,error_access_denied
135 JNC clook
136 JMP CloseFinish ; pretend the close worked.
137clook:
138;
139; ES:DI points to entry
140; DS:SI points to SFT
141; ES:BX points to buffer header
142;
143 SaveReg <DI,SI>
144 LEA SI,[SI].sf_name
145;
146; ES:DI point to directory entry
147; DS:SI point to unpacked name
148;
149 invoke XCHGP
150;
151; ES:DI point to unpacked name
152; DS:SI point to directory entry
153;
154 invoke MetaCompare
155 invoke XCHGP
156 RestoreReg <SI,DI>
157 JZ CLOSE_GO ; Name OK
158Bye: MOV DI,SI
159 PUSH DS
160 POP ES ; ES:DI points to SFT
161 PUSH SS
162 POP DS
163 STC
164 MOV AL,error_file_not_found
165 JMP CloseFinish
166
167CLOSE_GO:
168 TEST [SI].sf_mode,sf_isfcb ; FCB ?
169 JZ nofcb ; no, set dir attr, sf_attr
170 MOV CH,ES:[DI].dir_attr
171 MOV AL,[SI].sf_attr
172 MOV Attrib,AL
173 invoke MatchAttributes
174 JNZ Bye ; attributes do not match
175 JMP SHORT setattr ;FT.
176nofcb:
177 MOV AL,[SI].sf_attr ;FT. ;AN000;
178 MOV ES:[DI].dir_attr,AL ;FT. ;AN000;
179setattr:
180 OR BYTE PTR ES:[DI.dir_attr],attr_archive ;Set archive
181 MOV AX,ES:[DI.dir_first] ;AN011;F.O. save old first clusetr
182 MOV [OLD_FIRSTCLUS],AX ;AN011;F.O. save old first clusetr
183
184 MOV AX,[SI.sf_firclus]
185 MOV ES:[DI.dir_first],AX ;Set firclus pointer
186 MOV AX,WORD PTR [SI.sf_size]
187 MOV ES:[DI.dir_size_l],AX ;Set size
188 MOV AX,WORD PTR [SI.sf_size+2]
189 MOV ES:[DI.dir_size_h],AX
190 MOV AX,[SI.sf_date]
191 MOV ES:[DI.dir_date],AX ;Set date
192 MOV AX,[SI.sf_time]
193 MOV ES:[DI.dir_time],AX ;Set time
194;; File Tagging
195
196; MOV AX,[SI.sf_codepage] ;AN000;
197; MOV ES:[DI.dir_codepg],AX ;AN000;Set code page
198; MOV AX,[SI.sf_extcluster] ;AN000;
199; MOV ES:[DI.dir_extcluster],AX ;AN000; ;Set XA cluster
200; MOV AL,[SI.sf_attr_hi] ;AN000;
201; MOV ES:[DI.dir_attr2],AL ;AN000; ;Set high attr
202
203;; File Tagging
204 TEST ES:[BX.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
205 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
206 invoke INC_DIRTY_COUNT ;LB. ;AN000;
207 OR ES:[BX.buf_flags],buf_dirty ;Buffer dirty
208yesdirty:
209 SaveReg <DS,SI>
210 MOV CX,[SI.sf_firclus] ; do this for Fastopen
211 MOV AL,[THISDRV]
212;;; 10/1/86 update fastopen cache
213 PUSH DX
214 MOV AH,0 ; dir entry update
215 MOV DL,AL ; drive number A=0, B=1,,,
216 OR CX,CX ;AN005; first cluster 0; may be truncated
217 JNZ do_update2 ;AN005; no, do update
218 MOV AH,3 ;AN005; do a delete cache entry
219 MOV DI,WORD PTR [SI.sf_dirsec] ;AN005; cx:di = dir sector
220 MOV CX,WORD PTR [SI.sf_dirsec+2] ;AN005;
221 MOV DH,[SI.sf_dirpos] ;AN005; dh= dir pos
222 JMP SHORT do_update ;AN011;F.O.
223do_update2: ;AN011;F.O.
224 CMP CX,[OLD_FIRSTCLUS] ;AN011;F.O. same as old first clusetr?
225 JZ do_update ;AN011;F.O. yes
226 MOV AH,2 ;AN011;F.O. delete the old entry
227 MOV CX,[OLD_FIRSTCLUS] ;AN011;F.O.
228do_update: ;AN005;
229 Context DS
230 invoke FastOpen_Update ; invoke fastopen
231 POP DX
232
233;;; 10/1/86 update fastopen cache
234 invoke FLUSHBUF ; flush all relevant buffers
235 RestoreReg <DI,ES>
236 MOV AL,error_access_denied
237 JC CloseFinish
238FREE_SFT_OK:
239 CLC ; signal no error.
240CloseFinish:
241;
242; Indicate to the device that the SFT is being closed.
243;
244;;;; 7/21/86
245 PUSHF ; save flag from DirFromSFT
246 invoke Dev_Close_SFT
247 POPF
248;;;; 7/21/86
249;
250; See if the ref count indicates that we have busied the SFT. If so, mark the
251; SFT as being free. Note that we do NOT need to be in critSFT as we are ONLY
252; going to be moving from busy to free.
253;
254 POP CX ; get old ref count
255 PUSHF
256 fmt TypAccess,LevBUSY,<"$p: DOSFreeSFT: $x:$x from $x\n">,<ES,DI,AX>
257 DEC CX ; if cx != 1
258 JNZ NoFree ; then do NOT free SFT
259 Assert ISSFT,<ES,DI>,"DOS_FREE_SFT"
260 MOV ES:[DI].sf_ref_Count,CX
261NoFree:
262 LeaveCrit critDisk
263 POPF
264 return
265EndProc DOS_Close
266
267;
268; ES:DI -> SFT. Decs sft_ref_count. If the count goes to 0, mark it as busy.
269; Flags preserved. Return old ref count in AX
270;
271; Note that busy is indicated by the SFT ref count being -1.
272;
273Procedure FREE_SFT,NEAR
274 DOSAssume CS,<DS>,"Free_SFT"
275 ASSUME ES:NOTHING
276
277 PUSHF ; Save carry state
278 MOV AX,ES:[DI.sf_ref_count]
279 DEC AX
280 JNZ SetCount
281 DEC AX
282SetCount:
283 XCHG AX,ES:[DI.sf_ref_count]
284 POPF
285 return
286
287EndProc Free_SFT
288
289;
290; DirFromSFT - locate a directory entry given an SFT.
291;
292; Inputs: ES:DI point to SFT
293; DS = DOSGroup
294; Outputs:
295; EXTERR_LOCUS = errLOC_Disk
296; CurBuf points to buffer
297; Carry Clear -> operation OK
298; ES:DI point to entry
299; ES:BX point to buffer
300; DS:SI point to SFT
301; Carry SET -> operation failed
302; registers trashified
303; Registers modified: ALL
304
305Procedure DirFromSFT,NEAR
306 ASSUME DS:DOSGroup,ES:NOTHING
307
308 MOV [EXTERR_LOCUS],errLOC_Disk
309 SaveReg <ES,DI>
310 MOV DX,WORD PTR ES:[DI.sf_dirsec+2] ;F.C. >32mb
311 MOV [HIGH_SECTOR],DX ;F.C. >32mb
312 MOV DX,WORD PTR ES:[DI.sf_dirsec]
313
314 PUSH [HIGH_SECTOR] ;F.C. >32mb
315 PUSH DX
316 invoke FATREAD_SFT ; ES:BP points to DPB, [THISDRV] set
317 ; [THISDPB] set
318 POP DX
319 POP [HIGH_SECTOR] ;F.C. >32mb
320 JC PopDone
321 XOR AL,AL ; Pre read
322 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
323 invoke GETBUFFR
324 JC PopDone
325 RestoreReg <SI,DS> ; Get back SFT pointer
326 ASSUME DS:NOTHING
327 LES DI,Curbuf
328 OR ES:[DI.buf_flags],buf_isDIR
329 MOV BX,DI ; ES:BX point to buffer header
330 LEA DI,[DI].BUFINSIZ ; Point to buffer
331 MOV AL,SIZE dir_entry
332 MUL [SI].sf_DirPos
333 ADD DI,AX ; Point at the entry
334
335 return ; carry is clear
336PopDone:
337 RestoreReg <DI,ES>
338 return
339EndProc DirFromSFT
340
341Break <DOS_Commit - update directory entries>
342
343; Inputs:
344; Same as DOS_CLOSE
345; Function:
346; Commit the file
347; Returns:
348; Same as DOS_CLOSE except ref_count field is not altered
349; DS preserved, others destroyed
350
351 procedure DOS_COMMIT,NEAR
352 DOSAssume CS,<DS>,"DOS_Commit"
353 ASSUME ES:NOTHING
354
355 LES DI,[THISSFT]
356 MOV BX,ES:[DI.sf_flags]
357 TEST BX,devid_file_clean + devid_device ;Clears carry
358 retnz
359 TEST BX,sf_isnet
360 JZ LOCAL_COMMIT
361IF NOT Installed
362 transfer NET_COMMIT
363ELSE
364 MOV AX,(multNET SHL 8) OR 7
365 INT 2FH
366 return
367ENDIF
368
369;
370; Perform local commit operation by doing a close but not releaseing the SFT.
371; There are three ways we can do this. One is to enter a critical section to
372; protect a potential free. The second is to increment the ref count to mask
373; the close decrementing.
374;
375; The proper way is to let the caller's of close decide if a decrement should
376; be done. We do this by providing another entry into close after the
377; decrement and after the share information release.
378;
379LOCAL_COMMIT:
380 EnterCrit critDisk
381 EnterCrit critDisk ;PTM. ;AN000;
382 call SetSFTTimes
383 MOV AX,-1
384 call CloseEntry
385 PUSHF ;PTM. ;AN000;
386 invoke DEV_OPEN_SFT ;PTM. increment device count ;AN000;
387 POPF ;PTM. ;AN000;
388 LeaveCrit CritDisk ;PTM. ;AN000;
389 return
390
391EndProc DOS_COMMIT
392
393Break <SetSFTTimes - signal a change in the times for an SFT>
394
395;
396; SetSFTTimes - Examine the flags for a SFT and set the time appropriately.
397; Reflect these times in other SFT's for the same file.
398;
399; Inputs: ES:DI point to SFT
400; BX = sf_flags set apprpriately
401; Outputs: Set sft times to current time iff File & dirty & !nodate
402; Registers modified: All except ES:DI, BX, AX
403;
404
405Procedure SetSFTTimes,NEAR
406 Assert ISSFT,<ES,DI>,"SetSFTTimes"
407;
408; File clean or device does not get stamped nor disk looked at.
409;
410 TEST BX,devid_file_clean + devid_device
411 retnz ; clean or device => no timestamp
412;
413; file and dirty. See if date is good
414;
415 TEST BX,sf_close_nodate
416 retnz ; nodate => no timestamp
417 SaveReg <AX,BX>
418 invoke DATE16 ; Date/Time to AX/DX
419 MOV ES:[DI.sf_date],AX
420 MOV ES:[DI.sf_time],DX
421 XOR AX,AX
422if installed
423 call JShare + 14 * 4
424else
425 call ShSU
426endif
427 RestoreReg <BX,AX>
428 return
429EndProc SetSFTTimes
430
431CODE ENDS
432 END
diff --git a/v4.0/src/DOS/CPMIO.ASM b/v4.0/src/DOS/CPMIO.ASM
new file mode 100644
index 0000000..9878d4d
--- /dev/null
+++ b/v4.0/src/DOS/CPMIO.ASM
@@ -0,0 +1,448 @@
1; SCCSID = @(#)cpmio.asm 1.1 85/04/10
2TITLE CPMIO - device IO for MSDOS
3NAME CPMIO
4;
5; Standard device IO for MSDOS (first 12 function calls)
6;
7
8.xlist
9.xcref
10include dosseg.asm
11.cref
12.list
13
14;
15; Old style CP/M 1-12 system calls to talk to reserved devices
16;
17; $Std_Con_Input_No_Echo
18; $Std_Con_String_Output
19; $Std_Con_String_Input
20; $RawConIO
21; $RawConInput
22; RAWOUT
23; RAWOUT2
24;
25; Revision history:
26;
27; A000 version 4.00 - Jan 1988
28; A002 PTM -- dir >lpt3 hangs
29;
30;
31;
32;
33;
34;
35;
36;
37;
38;
39
40CODE SEGMENT BYTE PUBLIC 'CODE'
41 ASSUME SS:DOSGROUP,CS:DOSGROUP
42
43.xcref
44.xlist
45INCLUDE DOSSYM.INC
46INCLUDE DEVSYM.INC
47include doscntry.inc ;AN000 2/12/KK
48.list
49.cref
50
51IFNDEF KANJI
52KANJI EQU 0 ;FALSE
53ENDIF
54
55; The following routines form the console I/O group (funcs 1,2,6,7,8,9,10,11).
56; They assume ES and DS NOTHING, while not strictly correct, this forces data
57; references to be SS or CS relative which is desired.
58
59 i_need CARPOS,BYTE
60 i_need STARTPOS,BYTE
61 i_need INBUF,128
62 i_need INSMODE,BYTE
63 i_need user_SP,WORD
64 EXTRN EscChar:BYTE ; lead byte for function keys
65 EXTRN CanChar:BYTE ; Cancel character
66 EXTRN OUTCHA:NEAR ;AN000 char out with status check 2/11/KK
67 i_need Printer_Flag,BYTE
68 i_need SCAN_FLAG,BYTE
69 i_need DATE_FLAG,WORD
70 i_need Packet_Temp,WORD ; temporary packet used by readtime
71 i_need DEVCALL,DWORD
72 i_need InterChar,BYTE ;AN000;interim char flag ( 0 = regular char)
73 i_need InterCon,BYTE ;AN000;console flag ( 1 = in interim mode )
74 i_need SaveCurFlg,BYTE ;AN000;console out ( 1 = print and do not advance)
75 i_need COUNTRY_CDPG,byte ;AN000; 2/12/KK
76 i_need TEMP_VAR,WORD ;AN000; 2/12/KK
77 i_need DOS34_FLAG,WORD ;AN000; 2/12/KK
78
79
80
81Break
82 IF DBCS ;AN000;
83
84;-------------------------------- Start of Korean Support 2/11/KK
85 procedure $STD_CON_INPUT_NO_ECHO,NEAR ;System call 8 ;AN000;
86ASSUME DS:NOTHING,ES:NOTHING ;AN000;
87
88StdCILop: ;AN000;
89 invoke INTER_CON_INPUT_NO_ECHO ;AN000;
90 transfer InterApRet ; go to return fuction ;AN000;
91
92EndProc $STD_CON_INPUT_NO_ECHO ;AN000;
93
94 procedure INTER_CON_INPUT_NO_ECHO,NEAR ;AN000;
95ASSUME DS:NOTHING,ES:NOTHING ;AN000;
96;-----------------------------------End of Korean Support 2/11/KK
97
98; Inputs:
99; None
100; Function:
101; Same as $STD_CON_INPUT_NO_ECHO but uses interim character read from
102; the device.
103; Returns:
104; AL = character
105; Zero flag SET if interim character, RESET otherwise
106
107 ELSE ;AN000;
108
109
110;
111; Inputs:
112; None
113; Function:
114; Input character from console, no echo
115; Returns:
116; AL = character
117
118 procedure $STD_CON_INPUT_NO_ECHO,NEAR ;System call 8
119ASSUME DS:NOTHING,ES:NOTHING
120
121 ENDIF
122 PUSH DS
123 PUSH SI
124INTEST:
125 invoke STATCHK
126 JNZ Get
127;*************************************************************************
128 cmp [Printer_Flag],0 ; is printer idle?
129 jnz no_sys_wait
130 mov ah,5 ; get input status with system wait
131 invoke IOFUNC
132no_sys_wait:
133;**************************************************************************
134 MOV AH,84h
135 INT int_IBM
136
137;;; 7/15/86 update the date in the idle loop
138;;; Dec 19, 1986 D.C.L. changed following CMP to Byte Ptr from Word Ptr
139;;;; to shorten loop in consideration of the PC Convertible
140
141 CMP byte ptr [DATE_FLAG],-1 ; date is updated may be every
142 JNZ NoUpdate ; 65535 x ? ms if no one calls
143 PUSH AX
144 PUSH BX ; following is tricky,
145 PUSH CX ; it may be called by critical handler
146 PUSH DX ; at that time, DEVCALL is used by
147 ; other's READ or WRITE
148 PUSH DS ; save DS = SFT's sgement
149 PUSH CS ; READTIME must use DS=CS
150 POP DS
151
152 MOV AX,0 ; therefore, we save DEVCALL
153 CALL Save_Restore_Packet ; save DEVCALL packet
154 invoke READTIME ; readtime
155 MOV AX,1
156 CALL Save_Restore_Packet ; restore DEVCALL packet
157
158 PUSH BX ; the follwing code is to
159 MOV BX,OFFSET DOSGROUP:DATE_FLAG
160 ADD BX,2 ; check the TAG
161 CMP word ptr CS:[BX],22642
162 JZ check_ok
163 invoke DOSINIT ; should never come here
164check_ok:
165 POP BX
166
167 POP DS ; restore DS
168 POP DX
169 POP CX
170 POP BX
171 POP AX
172NoUpdate:
173 INC [DATE_FLAG]
174
175;;; 7/15/86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
176 JMP Intest
177Get:
178 XOR AH,AH
179 invoke IOFUNC
180 POP SI
181 POP DS
182;;; 7/15/86
183 MOV BYTE PTR [SCAN_FLAG],0
184 CMP AL,0 ; extended code ( AL )
185 JNZ noscan
186 MOV BYTE PTR [SCAN_FLAG],1 ; set this flag for ALT_Q key
187
188noscan:
189;;; 7/15/86
190 IF DBCS ;AN000;
191 cmp cs:[InterChar],1 ;AN000; set the zero flag if the character3/31/KK ;AN000;
192 ENDIF ;AN000;
193 return
194 IF DBCS ;AN000;
195EndProc INTER_CON_INPUT_NO_ECHO ;AN000; ;2/11/KK ;AN000;
196 ELSE ;AN000;
197EndProc $STD_CON_INPUT_NO_ECHO
198 ENDIF ;AN000;
199
200Break
201
202; Inputs:
203; DS:DX Point to output string '$' terminated
204; Function:
205; Print the string on the console device
206; Returns:
207; None
208
209 procedure $STD_CON_STRING_OUTPUT,NEAR ;System call 9
210ASSUME DS:NOTHING,ES:NOTHING
211
212 MOV SI,DX
213STRING_OUT1:
214 LODSB
215 IF DBCS ;AN000;
216 invoke TESTKANJ ;AN000; 2/11/KK ;AN000;
217 jz SBCS00 ;AN000; 2/11/KK ;AN000;
218 invoke OUTT ;AN000; 2/11/KK ;AN000;
219 LODSB ;AN000; 2/11/KK ;AN000;
220 JMP NEXT_STR1 ;AN000; 2/11/KK ;AN000;
221SBCS00: ;AN000; 2/11/KK ;AN000;
222 ENDIF ;AN000;
223 CMP AL,'$'
224 retz
225NEXT_STR1:
226 invoke OUTT
227 JMP STRING_OUT1
228
229EndProc $STD_CON_STRING_OUTPUT
230
231IF DBCS ;AN000;
232include kstrin.asm ;AN000;
233ELSE ;AN000;
234include strin.asm
235ENDIF ;AN000;
236
237Break
238
239; Inputs:
240; DL = -1 if input
241; else DL is output character
242; Function:
243; Input or output raw character from console, no echo
244; Returns:
245; AL = character
246
247 procedure $RAW_CON_IO,NEAR ; System call 6
248ASSUME DS:NOTHING,ES:NOTHING
249
250 MOV AL,DL
251 CMP AL,-1
252 JZ RAW22 ;AN000;
253 JMP RAWOUT ;AN000;
254RAW22: ;AN000;
255 LES DI,DWORD PTR [user_SP] ; Get pointer to register save area
256 XOR BX,BX
257 invoke GET_IO_SFT
258 retc
259 IF DBCS ;AN000;
260 push word ptr [Intercon] ;AN000;
261 mov [Intercon],0 ;AN000; disable interim characters
262 ENDIF ;AN000;
263 MOV AH,1
264 invoke IOFUNC
265 JNZ RESFLG
266 IF DBCS ;AN000;
267 pop word ptr [InterCon] ;AN000; restore interim flag
268 ENDIF ;AN000;
269 invoke SPOOLINT
270 OR BYTE PTR ES:[DI.user_F],40H ; Set user's zero flag
271 XOR AL,AL
272 return
273
274RESFLG:
275 AND BYTE PTR ES:[DI.user_F],0FFH-40H ; Reset user's zero flag
276 IF DBCS ;AN000;
277 XOR AH,AH ;AN000;
278 invoke IOFUNC ;AN000; get the character
279 pop word ptr [InterCon] ;AN000;
280 return ;AN000;
281 ENDIF ;AN000; ;AN000;
282
283RILP:
284 invoke SPOOLINT
285
286; Inputs:
287; None
288; Function:
289; Input raw character from console, no echo
290; Returns:
291; AL = character
292
293 entry $RAW_CON_INPUT ; System call 7
294
295 PUSH BX
296 XOR BX,BX
297 invoke GET_IO_SFT
298 POP BX
299 retc
300 MOV AH,1
301 invoke IOFUNC
302 JNZ Got
303 MOV AH,84h
304 INT int_IBM
305 JMP RILP
306Got:
307 XOR AH,AH
308 invoke IOFUNC
309 IF DBCS ;AN000;
310 cmp [InterChar],1 ;AN000; 2/11/KK
311; 2/11/KK
312; Sets the application zero flag depending on the 2/11/KK
313; zero flag upon entry to this routine. Then returns 2/11/KK
314; from system call. 2/11/KK
315; 2/11/KK
316entry InterApRet ;AN000; 2/11/KK ;AN000;
317 pushf ;AN000; 3/16/KK
318 push ds ;AN000; 3/16/KK
319 push bx ;AN000; 3/16/KK
320 Context DS ;AN000; 3/16/KK
321 MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccDosCodePage
322 cmp word ptr [bx],934 ;AN000; 3/16/KK korean code page ?
323 pop bx ;AN000; 3/16/KK
324 pop ds ;AN000; 3/16/KK
325 je do_koren ;AN000; 3/16/KK
326 popf ;AN000; 3/16/KK
327 return ;AN000; 3/16/KK
328do_koren: ;AN000; 3/16/KK
329 popf ;AN000;
330 LES DI,DWORD PTR [user_SP] ;AN000; Get pointer to register save area KK
331 jnz sj0 ;AN000; 2/11/KK
332 OR BYTE PTR ES:[DI.user_F],40H ;AN000; Set user's zero flag 2/11/KK
333 return ;AN000; 2/11/KK
334sj0: ;AN000; 2/11/KK
335 AND BYTE PTR ES:[DI.user_F],0FFH-40H ;AN000; Reset user's zero flag 2/KK
336 ENDIF ;AN000;
337 return ;AN000;
338;
339; Output the character in AL to stdout
340;
341 entry RAWOUT
342
343 PUSH BX
344 MOV BX,1
345
346 invoke GET_IO_SFT
347 JC RAWRET1
348
349 MOV BX,[SI.sf_flags]
350
351 ;
352 ; If we are a network handle OR if we are not a local device then go do the
353 ; output the hard way.
354 ;
355
356 AND BX,sf_isNet + devid_device
357 CMP BX,devid_device
358 JNZ RawNorm
359 IF DBCS ;AN000;
360 TEST [SaveCurFlg],01H ;AN000; print but no cursor adv?
361 JNZ RAWNORM ;AN000; 2/11/KK
362 ENDIF ;AN000;
363
364; TEST BX,sf_isnet ; output to NET?
365; JNZ RAWNORM ; if so, do normally
366; TEST BX,devid_device ; output to file?
367; JZ RAWNORM ; if so, do normally
368
369 PUSH DS
370 LDS BX,[SI.sf_devptr] ; output to special?
371 TEST BYTE PTR [BX+SDEVATT],ISSPEC
372 POP DS
373 JZ RAWNORM ; if not, do normally
374 INT int_fastcon ; quickly output the char
375RAWRET:
376 CLC
377RAWRET1:
378 POP BX
379 return
380RAWNORM:
381 CALL RAWOUT3
382 JMP RAWRET
383
384;
385; Output the character in AL to handle in BX
386;
387 entry RAWOUT2
388
389 invoke GET_IO_SFT
390 retc
391RAWOUT3:
392 PUSH AX
393 JMP SHORT RAWOSTRT
394ROLP:
395 invoke SPOOLINT
396 OR [DOS34_FLAG],CTRL_BREAK_FLAG ;AN002; set control break
397 invoke DSKSTATCHK ;AN002; check control break
398RAWOSTRT:
399 MOV AH,3
400 invoke IOFUNC
401 JZ ROLP
402 POP AX
403 MOV AH,2
404 invoke IOFUNC
405 CLC ; Clear carry indicating successful
406 return
407EndProc $RAW_CON_IO
408
409; Inputs:
410; AX=0 save the DEVCALL request packet
411; =1 restore the DEVCALL request packet
412; Function:
413; save or restore the DEVCALL packet
414; Returns:
415; none
416
417 procedure Save_Restore_Packet,NEAR
418ASSUME DS:NOTHING,ES:NOTHING
419
420 PUSH DS
421 PUSH ES
422 PUSH SI
423 PUSH DI
424 CMP AX,0 ; save packet
425 JZ save_packet
426restore_packet:
427 MOV SI,OFFSET DOSGROUP:Packet_Temp ;sourec
428 MOV DI,OFFSET DOSGROUP:DEVCALL ;destination
429 JMP set_seg
430save_packet:
431 MOV DI,OFFSET DOSGROUP:Packet_Temp ;destination
432 MOV SI,OFFSET DOSGROUP:DEVCALL ;source
433set_seg:
434 MOV AX,CS ; set DS,ES to DOSGROUP
435 MOV DS,AX
436 MOV ES,AX
437 MOV CX,11 ; 11 words to move
438 REP MOVSW
439
440 POP DI
441 POP SI
442 POP ES
443 POP DS
444 return
445EndProc Save_Restore_Packet
446
447CODE ENDS
448 END
diff --git a/v4.0/src/DOS/CPMIO2.ASM b/v4.0/src/DOS/CPMIO2.ASM
new file mode 100644
index 0000000..2b31689
--- /dev/null
+++ b/v4.0/src/DOS/CPMIO2.ASM
@@ -0,0 +1,354 @@
1; SCCSID = @(#)cpmio2.asm 1.1 85/04/11
2TITLE CPMIO2 - device IO for MSDOS
3NAME CPMIO2
4
5.xlist
6.xcref
7include dosseg.asm
8.cref
9.list
10
11;
12; Old style CP/M 1-12 system calls to talk to reserved devices
13;
14; $Std_Con_Input
15; $Std_Con_Output
16; OUTT
17; TAB
18; BUFOUT
19; $Std_Aux_Input
20; $Std_Aux_Output
21; $Std_Printer_Output
22; $Std_Con_Input_Status
23; $Std_Con_Input_Flush
24;
25; Revision History:
26;
27; AN000 version 4.00 - Jan. 1988
28;
29
30CODE SEGMENT BYTE PUBLIC 'CODE'
31 ASSUME SS:DOSGROUP,CS:DOSGROUP
32
33.xcref
34.xlist
35INCLUDE DOSSYM.INC
36INCLUDE DEVSYM.INC
37.list
38.cref
39
40; The following routines form the console I/O group (funcs 1,2,6,7,8,9,10,11).
41; They assume ES and DS NOTHING, while not strictly correct, this forces data
42; references to be SS or CS relative which is desired.
43
44 i_need CARPOS,BYTE
45 i_need CHARCO,BYTE
46 i_need PFLAG,BYTE
47 i_need CurrentPDB,WORD ;AN000;
48 i_need InterCon,BYTE ;AN000;
49 i_need SaveCurFlg,BYTE ;AN000;
50
51
52Break
53
54; Inputs:
55; None
56; Function:
57; Input character from console, echo
58; Returns:
59; AL = character
60
61 procedure $STD_CON_INPUT,NEAR ;System call 1
62ASSUME DS:NOTHING,ES:NOTHING
63
64 IF DBCS ;AN000;
65 push word ptr [InterCon] ;AN000;
66 mov [InterCon],01H ;AN000;
67 invoke INTER_CON_INPUT_NO_ECHO ;AN000;
68 pop word ptr [InterCon] ;AN000;
69 pushf ;AN000;
70 push AX ;AN000;
71 mov [SaveCurFlg],0 ;AN000;
72 jnz sj0 ;AN000;
73 mov [SaveCurFlg],1 ;AN000;
74sj0: ;AN000;
75 invoke OUTT ;AN000;
76 mov [SaveCurFLg],0 ;AN000;
77 pop AX ;AN000;
78 popf ;AN000;
79 jz $STD_CON_INPUT ;AN000;
80 ELSE ;AN000;
81 invoke $STD_CON_INPUT_NO_ECHO
82 PUSH AX
83 invoke OUTT
84 POP AX
85 ENDIF ;AN000;
86 return
87EndProc $STD_CON_INPUT
88
89Break
90
91; Inputs:
92; DL = character
93; Function:
94; Output character to console
95; Returns:
96; None
97
98 procedure $STD_CON_OUTPUT,NEAR ;System call 2
99 public OUTCHA ;AN000;
100ASSUME DS:NOTHING,ES:NOTHING
101
102 MOV AL,DL
103
104 entry OUTT
105 CMP AL,20H
106 JB CTRLOUT
107 CMP AL,c_DEL
108 JZ OUTCH
109OUTCHA: ;AN000;
110 INC BYTE PTR [CARPOS]
111OUTCH:
112 PUSH DS
113 PUSH SI
114 INC BYTE PTR [CHARCO] ;invoke statchk...
115 AND BYTE PTR [CHARCO],00111111B ;AN000; every 64th char
116 JNZ OUTSKIP
117 PUSH AX
118 invoke STATCHK
119 POP AX
120OUTSKIP:
121 invoke RAWOUT ;output the character
122 POP SI
123 POP DS
124 IF DBCS ;AN000;
125 TEST [SaveCurFlg],01H ;AN000;print but no cursor adv? 2/13/KK
126 retnz ;AN000;if so then do not send to prt2/13/KK
127 ENDIF
128 TEST BYTE PTR [PFLAG],-1
129 retz
130 PUSH BX
131 PUSH DS
132 PUSH SI
133 MOV BX,1
134 invoke GET_IO_SFT
135 JC TRIPOPJ
136 MOV BX,[SI.sf_flags]
137 TEST BX,sf_isnet ; output to NET?
138 JNZ TRIPOPJ ; if so, no echo
139 TEST BX,devid_device ; output to file?
140 JZ TRIPOPJ ; if so, no echo
141 MOV BX,4
142 invoke GET_IO_SFT
143 JC TRIPOPJ
144 TEST [SI.sf_flags],sf_net_spool ; StdPrn redirected?
145 JZ LISSTRT2J ; No, OK to echo
146 MOV BYTE PTR [PFLAG],0 ; If a spool, NEVER echo
147TRIPOPJ:
148 JMP TRIPOP
149
150LISSTRT2J:
151 JMP LISSTRT2
152
153CTRLOUT:
154 CMP AL,c_CR
155 JZ ZERPOS
156 CMP AL,c_BS
157 JZ BACKPOS
158 CMP AL,c_HT
159 JNZ OUTCH
160 MOV AL,[CARPOS]
161 OR AL,0F8H
162 NEG AL
163
164 entry TAB
165
166 PUSH CX
167 MOV CL,AL
168 MOV CH,0
169 JCXZ POPTAB
170TABLP:
171 MOV AL," "
172 invoke OUTT
173 LOOP TABLP
174POPTAB:
175 POP CX
176 return
177
178ZERPOS:
179 MOV BYTE PTR [CARPOS],0
180 JMP OUTCH
181OUTJ: JMP OUTT
182
183BACKPOS:
184 DEC BYTE PTR [CARPOS]
185 JMP OUTCH
186
187 entry BUFOUT
188 CMP AL," "
189 JAE OUTJ ;Normal char
190 CMP AL,9
191 JZ OUTJ ;OUT knows how to expand tabs
192
193;DOS 3.3 7/14/86
194 CMP AL,"U"-"@" ; turn ^U to section symbol
195 JZ CTRLU
196 CMP AL,"T"-"@" ; turn ^T to paragraph symbol
197 JZ CTRLU
198NOT_CTRLU:
199;DOS 3.3 7/14/86
200
201 PUSH AX
202 MOV AL,"^"
203 invoke OUTT ;Print '^' before control chars
204 POP AX
205 OR AL,40H ;Turn it into Upper case mate
206CTRLU:
207 invoke OUTT
208 return
209EndProc $STD_CON_OUTPUT
210
211Break
212
213; Inputs:
214; None
215; Function:
216; Returns character from aux input
217; Returns:
218; Character in AL
219
220 procedure $STD_AUX_INPUT,NEAR ;System call 3
221ASSUME DS:NOTHING,ES:NOTHING
222
223 invoke STATCHK
224 MOV BX,3
225 invoke GET_IO_SFT
226 retc
227 JMP SHORT TAISTRT
228AUXILP:
229 invoke SPOOLINT
230TAISTRT:
231 MOV AH,1
232 invoke IOFUNC
233 JZ AUXILP
234 XOR AH,AH
235 invoke IOFUNC
236 return
237EndProc $STD_AUX_INPUT
238
239Break
240
241; Inputs:
242; Character in DL
243; Function:
244; Output character to aux output
245; Returns:
246; Nothing
247
248 procedure $STD_AUX_OUTPUT,NEAR ;System call 4
249ASSUME DS:NOTHING,ES:NOTHING
250
251 PUSH BX
252 MOV BX,3
253 JMP SHORT SENDOUT
254
255EndProc $STD_AUX_OUTPUT
256
257Break
258
259; Inputs:
260; DL = Character
261; Function:
262; Output the character to the list device
263; Returns:
264; None
265
266 procedure $STD_PRINTER_OUTPUT,NEAR ;System call 5
267ASSUME DS:NOTHING,ES:NOTHING
268
269 PUSH BX
270 MOV BX,4
271
272SENDOUT:
273 MOV AL,DL
274 PUSH AX
275 invoke STATCHK
276 POP AX
277 PUSH DS
278 PUSH SI
279LISSTRT2:
280 invoke RAWOUT2
281TRIPOP:
282 POP SI
283 POP DS
284 POP BX
285 return
286EndProc $STD_PRINTER_OUTPUT
287
288Break
289
290; Inputs:
291; None
292; Function:
293; Check console input status
294; Returns:
295; AL = -1 character available, = 0 no character
296
297 procedure $STD_CON_INPUT_STATUS,NEAR ;System call 11
298ASSUME DS:NOTHING,ES:NOTHING
299
300 invoke STATCHK
301 MOV AL,0 ; no xor!!
302 retz
303 OR AL,-1
304 return
305EndProc $STD_CON_INPUT_STATUS
306
307Break
308
309; Inputs:
310; AL = DOS function to be called after flush (1,6,7,8,10)
311; Function:
312; Flush console input buffer and perform call in AL
313; Returns:
314; Whatever call in AL returns or AL=0 if AL was not 1,6,7,8 or 10
315
316 procedure $STD_CON_INPUT_FLUSH,NEAR ;System call 12
317ASSUME DS:NOTHING,ES:NOTHING
318
319 PUSH AX
320 PUSH DX
321 XOR BX,BX
322 invoke GET_IO_SFT
323 JC BADJFNCON
324 MOV AH,4
325 invoke IOFUNC
326
327BADJFNCON:
328 POP DX
329 POP AX
330 MOV AH,AL
331 CMP AL,1
332 JZ REDISPJ
333 CMP AL,6
334 JZ REDISPJ
335 CMP AL,7
336 JZ REDISPJ
337 CMP AL,8
338 JZ REDISPJ
339 CMP AL,10
340 JZ REDISPJ
341 MOV AL,0
342 return
343
344REDISPJ:
345 IF DBCS ;AN000;
346 mov ds,[CurrentPDB] ;AN000;
347 ;AN000; set DS same as one from COMMAND entry
348 ENDIF
349 CLI
350 transfer REDISP
351EndProc $STD_CON_INPUT_FLUSH
352
353CODE ENDS
354 END
diff --git a/v4.0/src/DOS/CREATE.ASM b/v4.0/src/DOS/CREATE.ASM
new file mode 100644
index 0000000..6983e29
--- /dev/null
+++ b/v4.0/src/DOS/CREATE.ASM
@@ -0,0 +1,380 @@
1; SCCSID = @(#)create.asm 1.6 85/08/19
2TITLE DOS_CREATE/DOS_CREATE_NEW - Internal CREATE calls for MS-DOS
3NAME DOS_CREATE
4; Internal Create and Create new to create a local or NET file and SFT.
5;
6; DOS_CREATE
7; DOS_CREATE_NEW
8; SET_MKND_ERR
9; SET_Media_ID
10; SET_EXT_Mode
11;
12; Revision history:
13;
14; A000 version 4.00 Jan. 1988
15; A001 D490 -- Change IOCTL subfunctios from 63h,43h to 66h, 46h
16
17;
18; get the appropriate segment definitions
19;
20.xlist
21include dosseg.asm
22
23CODE SEGMENT BYTE PUBLIC 'CODE'
24 ASSUME SS:DOSGROUP,CS:DOSGROUP
25
26.xcref
27INCLUDE DOSSYM.INC
28INCLUDE DEVSYM.INC
29include version.inc
30.cref
31.list
32
33Installed = TRUE
34
35 i_need NoSetDir,BYTE
36 i_need THISSFT,DWORD
37 i_need THISCDS,DWORD
38 I_need EXTERR,WORD
39 I_Need ExtErr_locus,BYTE
40 I_need JShare,DWORD
41 I_need VOLCHNG_FLAG,BYTE
42 I_need SATTRIB,BYTE
43 I_need CALLVIDM,DWORD
44 I_need OpenBuf,128
45 I_need EXTOPEN_ON,BYTE ;AN000; extended open
46 I_need NAME1,BYTE ;AN000;
47 I_need NO_NAME_ID,BYTE ;AN000;
48 I_need Packet_Temp,WORD ;AN000;
49 I_need DOS34_FLAG,WORD ;AN000;
50 I_need SAVE_BX,WORD ;AN000;
51
52; Inputs:
53; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
54; terminated)
55; [CURR_DIR_END] Points to end of Current dir part of string
56; ( = -1 if current dir not involved, else
57; Points to first char after last "/" of current dir part)
58; [THISCDS] Points to CDS being used
59; (Low word = -1 if NUL CDS (Net direct request))
60; [THISSFT] Points to SFT to fill in if file created
61; (sf_mode field set so that FCB may be detected)
62; [SATTRIB] Is attribute of search, determines what files can be found
63; AX is Attribute to create
64; Function:
65; Try to create the specified file truncating an old one that exists
66; Outputs:
67; sf_ref_count is NOT altered
68; CARRY CLEAR
69; THISSFT filled in.
70; sf_mode = unchanged for FCB, sharing_compat + open_for_both
71; CARRY SET
72; AX is error code
73; error_path_not_found
74; Bad path (not in curr dir part if present)
75; error_bad_curr_dir
76; Bad path in current directory part of path
77; error_access_denied
78; Attempt to re-create read only file , or
79; create a second volume id or create a dir
80; error_sharing_violation
81; The sharing mode was correct but not allowed
82; generates an INT 24
83; DS preserved, others destroyed
84
85 procedure DOS_Create,NEAR
86 DOSAssume CS,<DS>,"DOS_Create"
87 ASSUME ES:NOTHING
88
89 XOR AH,AH ; Truncate is OK
90Create_inter:
91 TEST AL,NOT (attr_all + attr_ignore + attr_volume_id)
92 ; Mask out any meaningless bits
93 JNZ AttErr
94 TEST AL,attr_volume_id
95 JZ NoReset
96 OR [DOS34_FLAG],DBCS_VOLID ;AN000;FOR dbcs volid
97 MOV AL,attr_volume_id
98NoReset:
99 OR AL,attr_archive ; File changed
100 TEST AL,attr_directory + attr_device
101 JZ ATT_OK
102AttErr:
103 MOV AX,5 ; Attribute problem
104 MOV Exterr_Locus,errLOC_Unk
105 JMP SHORT SET_MKND_ERR ; Gotta use MKDIR to make dirs, NEVER allow
106 ; attr_device to be set.
107ATT_OK:
108 LES DI,[THISSFT]
109 PUSH ES
110 LES SI,[THISCDS]
111 CMP SI,-1
112 JNZ TEST_RE_NET
113 POP ES
114
115;Extended open hooks
116 TEST [EXTOPEN_ON],ext_open_on ;AN000;EO. from extnded open
117 JZ NOEXTOP ;AN000;EO. no, do normal
118IFS_extopen: ;AN000;EO.
119 PUSH AX ;AN000;EO. pass create attr
120 MOV AX,(multNET SHL 8) OR 46 ;AN000;EO. issue extended open verb
121 INT 2FH ;AN000;EO.
122 POP BX ;AN000;EO. trash bx
123 MOV [EXTOPEN_ON],0 ;AN000;EO.
124 return ;AN000;EO.
125NOEXTOP: ;AN000;
126;Extended open hooks
127
128IF NOT Installed
129 transfer NET_SEQ_CREATE
130ELSE
131 PUSH AX
132 MOV AX,(multNET SHL 8) OR 24
133 INT 2FH
134 POP BX ; BX is trashed anyway
135 return
136ENDIF
137
138TEST_RE_NET:
139 TEST ES:[SI.curdir_flags],curdir_isnet
140 POP ES
141 JZ LOCAL_CREATE
142
143 CALL Set_EXT_mode ;AN000;EO.
144 JC SHORT dochk ;AN000;EO.
145 OR ES:[DI.sf_mode],sharing_compat + open_for_both ;IFS.
146dochk:
147 ; invoke IFS_SHARE_CHECK ;AN000;IFS. check share
148 ; JC nomore ;AN000;IFS. share violation
149
150;Extended open hooks
151 TEST [EXTOPEN_ON],ext_open_on ;AN000;EO. from extnded open
152 JNZ IFS_extopen ;AN000;EO. yes, issue extended open
153;Extended open hooks
154
155IF NOT Installed
156 transfer NET_CREATE
157ELSE
158 PUSH AX
159 MOV AX,(multNET SHL 8) OR 23
160 INT 2FH
161 POP BX ; BX is trashed anyway
162nomore:
163 return
164ENDIF
165
166LOCAL_CREATE:
167 CALL Set_EXT_mode ;AN000;EO. set mode if from extended open
168 JC setdone ;AN000;EO.
169 OR ES:[DI].sf_mode,sharing_compat+open_for_both
170setdone:
171 EnterCrit critDisk
172 invoke MakeNode
173 JNC Create_ok
174 mov [VOLCHNG_FLAG],-1 ; indicate no change in volume label
175 LeaveCrit critDisk
176
177 entry SET_MKND_ERR
178 DOSAssume CS,<DS>,"Set_MkNd_Err"
179 ASSUME ES:NOTHING
180; Looks up MakeNode errors and converts them. AL is MakeNode
181; error, SI is GetPath bad spot return if path_not_found error.
182
183 MOV BX,OFFSET DOSGROUP:CRTERRTAB
184 XLAT
185CreatBadRet:
186 STC
187 return
188
189TABLE SEGMENT
190Public CREAT001S,CREAT001E
191CREAT001S label byte
192CRTERRTAB LABEL BYTE ; Lookup table for MakeNode returns
193 DB ? ; none
194 DB error_access_denied ; MakeNode error 1
195 DB error_cannot_make ; MakeNode error 2
196 DB error_file_exists ; MakeNode error 3
197 DB error_path_not_found ; MakeNode error 4
198 DB error_access_denied ; MakeNode error 5
199 DB error_sharing_violation ; MakeNode error 6
200 DB error_file_not_found ; MakeNode error 7
201CREAT001E label byte
202TABLE ENDS
203
204;
205; We have just created a new file. This results in the truncation of old
206; files. We must inform the sharer to slash all the open SFT's for this
207; file to the current size.
208;
209Create_ok:
210; If we created a volume id on the diskette, set the VOLCHNG_FLAG to logical
211; drive number to force a Build BPB after Media Check.
212
213;;; FASTOPEN 8/29/86
214 invoke FastOpen_Delete
215;;; FASTOPEN 8/29/86
216 mov al,[SATTRIB]
217 test al,attr_volume_id
218 jz NoVolLabel
219 LES DI,[THISCDS]
220 mov ah,byte ptr ES:[DI] ; get drive letter
221 sub ah,'A' ; convert to drive letter
222 mov [VOLCHNG_FLAG],ah ;Set flag to indicate volid change
223 MOV BH,1 ;AN000;>32mb set volume id to boot record
224 CALL Set_Media_ID ;AN000;>32mb
225
226 EnterCrit CritDisk
227 invoke FatRead_CDS ; force a media check
228 LeaveCrit CritDisk
229NoVolLabel:
230 MOV ax,2
231 LES DI,ThisSFT
232if installed
233 call JShare + 14 * 4
234else
235 Call ShSU
236endif
237 LeaveCrit critDisk
238 transfer SET_SFT_MODE
239
240EndProc DOS_Create
241
242; Inputs:
243; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
244; terminated)
245; [CURR_DIR_END] Points to end of Current dir part of string
246; ( = -1 if current dir not involved, else
247; Points to first char after last "/" of current dir part)
248; [THISCDS] Points to CDS being used
249; (Low word = -1 if NUL CDS (Net direct request))
250; [THISSFT] Points to SFT to fill in if file created
251; (sf_mode field set so that FCB may be detected)
252; [SATTRIB] Is attribute of search, determines what files can be found
253; AX is Attribute to create
254; Function:
255; Try to create the specified file truncating an old one that exists
256; Outputs:
257; sf_ref_count is NOT altered
258; CARRY CLEAR
259; THISSFT filled in.
260; sf_mode = sharing_compat + open_for_both for Non-FCB SFT
261; CARRY SET
262; AX is error code
263; error_path_not_found
264; Bad path (not in curr dir part if present)
265; error_bad_curr_dir
266; Bad path in current directory part of path
267; error_access_denied
268; Create a second volume id or create a dir
269; error_file_exists
270; Already a file by this name
271; DS preserved, others destroyed
272
273 procedure DOS_Create_New,NEAR
274 DOSAssume CS,<DS>,"DOS_Create_New"
275 ASSUME ES:NOTHING
276
277 MOV AH,1 ; Truncate is NOT OK
278 JMP Create_inter
279
280EndProc DOS_Create_New
281
282
283; Inputs:
284; NAME1= Volume ID
285; BH= 0, delete volume id
286; 1, set new volume id
287; DS= DOSGROUP
288; Function:
289; Set Volume ID to DOS 4.00 Boot record.
290; Outputs:
291; CARRY CLEAR
292; volume id set
293; CARRY SET
294; AX is error code
295
296 procedure Set_Media_ID,NEAR ;AN000;
297 DOSAssume CS,<DS>,"DOS_Create_New" ;AN000;
298 ASSUME ES:NOTHING ;AN000;
299
300 PUSH AX ;AN000;;>32mb
301 PUSH ES ;AN000;;>32mb
302 PUSH DI ;AN000;;>32mb
303
304 INC AH ;AN000;;>32mb bl=drive #
305 MOV BL,AH ;AN000;;>32mb bl=drive # (A=1,B=2,,,)
306 MOV AL,0DH ;AN000;;>32mb generic IOCTL
307 MOV CX,0866H ;AN001;;>32mb get media id
308 MOV DX,OFFSET DOSGROUP:PACKET_TEMP ;AN000;>32mb
309
310 PUSH BX ;AN000;;>32mb
311 PUSH DX ;AN000;;>32mb
312 XOR BH,BH ;AN000;;>32mb
313
314 invoke $IOCTL ;AN000;;>32mb
315 POP DX ;AN000;;>32mb
316 POP BX ;AN000;;>32mb
317 JC geterr ;AN000;;>32mb
318
319 OR BH,BH ;AN000;;>32mb delete volume id
320 JZ NoName ;AN000;>32mb yes
321 MOV SI,OFFSET DOSGROUP:NAME1 ;AN000;>32mb
322 JMP SHORT doset ;AN000;>32mb yes
323Noname: ;AN000;
324 MOV SI,OFFSET DOSGROUP:NO_NAME_ID ;AN000;>32mb
325doset: ;AN000;
326 MOV DI,DX ;AN000;;>32mb
327 ADD DI,MEDIA_LABEL ;AN000;;>32mb
328 PUSH CS ;AN000;;>32mb move new volume id to packet
329 POP DS ;AN000;;>32mb
330 PUSH CS ;AN000;;>32mb
331 POP ES ;AN000;;>32mb
332 MOV CX,11 ;AN000;;>32mb
333 REP MOVSB ;AN000;;>32mb
334 MOV CX,0846H ;AN001;;>32mb
335 MOV AL,0DH ;AN000;;>32mb
336 XOR BH,BH ;AN000;;>32mb
337 invoke $IOCTL ;AN000;;>32mb set volume id
338geterr: ;AN000;
339 PUSH CS ;AN000;>32mb
340 POP DS ;AN000;>32mb ds= dosgroup
341
342 POP DI ;AN000;;>32mb
343 POP ES ;AN000;;>32mb
344 POP AX ;AN000;;>32mb
345 return ;AN000;>32mb
346
347EndProc Set_Media_ID ;AN000;
348
349
350; Inputs:
351; [EXTOPEN_ON]= flag for extende open
352; SAVE_BX= mode specified in Extended Open
353; Function:
354; Set mode in ThisSFT
355; Outputs:
356; carry set,mode is set if from Extended Open
357; carry clear, mode not set yet
358
359IF NOT IBMCOPYRIGHT
360 public Set_EXT_mode
361ENDIF
362
363 procedure Set_EXT_mode,NEAR ;AN000;
364 ASSUME ES:NOTHING,DS:NOTHING ;AN000;
365
366 TEST [EXTOPEN_ON],ext_open_on ;AN000;EO. from extnded open
367 JZ NOTEX ;AN000;EO. no, do normal
368 PUSH AX ;AN000;EO.
369 MOV AX,[SAVE_BX] ;AN000;EO.
370 OR ES:[DI.sf_mode],AX ;AN000;EO.
371 POP AX ;AN000;EO.
372 STC ;AN000;EO.
373NOTEX: ;AN000;
374 return ;AN000;EO.
375
376EndProc Set_EXT_mode ;AN000;
377
378CODE ENDS
379 END
380 \ No newline at end of file
diff --git a/v4.0/src/DOS/CRIT.ASM b/v4.0/src/DOS/CRIT.ASM
new file mode 100644
index 0000000..dfb1ccd
--- /dev/null
+++ b/v4.0/src/DOS/CRIT.ASM
@@ -0,0 +1,92 @@
1; SCCSID = @(#)crit.asm 1.1 85/04/10
2TITLE CRIT - Critical Section Routines
3NAME CRIT
4;
5; Critical Section Routines
6;
7; Critical section handlers
8;
9; Modification history:
10;
11; Created: ARR 30 March 1983
12;
13
14.xlist
15;
16; get the appropriate segment definitions
17;
18include dosseg.asm
19
20CODE SEGMENT BYTE PUBLIC 'CODE'
21 ASSUME SS:NOTHING,CS:DOSGROUP
22
23.xcref
24INCLUDE DOSSYM.INC
25.cref
26.list
27
28 I_need User_In_AX,WORD
29 i_need CurrentPDB,WORD
30if debug
31 I_need BugLev,WORD
32 I_need BugTyp,WORD
33include bugtyp.asm
34endif
35
36Break <Critical section handlers>
37
38;
39; Each handler must leave everything untouched; including flags!
40;
41; Sleaze for time savings: first instruction is a return. This is patched
42; by the sharer to be a PUSH AX to complete the correct routines.
43;
44Procedure EcritDisk,NEAR
45 public EcritMem
46 public EcritSFT
47ECritMEM LABEL NEAR
48ECritSFT LABEL NEAR
49 RET
50; PUSH AX
51 fmt TypSect,LevReq,<"PDB $x entering $x">,<CurrentPDB,sect>
52 MOV AX,8000h+critDisk
53 INT int_ibm
54 POP AX
55 return
56EndProc EcritDisk
57
58Procedure LcritDisk,NEAR
59 public LcritMem
60 public LcritSFT
61LCritMEM LABEL NEAR
62LCritSFT LABEL NEAR
63 RET
64; PUSH AX
65 fmt TypSect,LevReq,<"PDB $x entering $x">,<CurrentPDB,sect>
66 MOV AX,8100h+critDisk
67 INT int_ibm
68 POP AX
69 return
70EndProc LcritDisk
71
72Procedure EcritDevice,NEAR
73 RET
74; PUSH AX
75 fmt TypSect,LevReq,<"PDB $x entering $x">,<CurrentPDB,sect>
76 MOV AX,8000h+critDevice
77 INT int_ibm
78 POP AX
79 return
80EndProc EcritDevice
81
82Procedure LcritDevice,NEAR
83 RET
84; PUSH AX
85 MOV AX,8100h+critDevice
86 INT int_ibm
87 POP AX
88 return
89EndProc LcritDevice
90
91CODE ENDS
92 END
diff --git a/v4.0/src/DOS/CTRLC.ASM b/v4.0/src/DOS/CTRLC.ASM
new file mode 100644
index 0000000..5a79e04
--- /dev/null
+++ b/v4.0/src/DOS/CTRLC.ASM
@@ -0,0 +1,771 @@
1; SCCSID = @(#)ctrlc.asm 1.4 85/08/16
2; Low level routines for detecting special characters on CON input,
3; the ^C exit/int code, the Hard error INT 24 code, the
4; process termination code, and the INT 0 divide overflow handler.
5;
6; FATAL
7; FATAL1
8; reset_environment
9; DSKSTATCHK
10; SPOOLINT
11; STATCHK
12; CNTCHAND
13; DIVOV
14; CHARHARD
15; HardErr
16;
17; Revision history:
18;
19; AN000 version 4.0 Jan 1988
20; A002 PTM -- dir >lpt3 hangs
21; A003 PTM 3957- fake version for IBMCAHE.COM
22
23;
24; get the appropriate segment definitions
25;
26.xlist
27include dosseg.asm
28
29CODE SEGMENT BYTE PUBLIC 'CODE'
30 ASSUME SS:DOSGROUP,CS:DOSGROUP
31
32.xcref
33INCLUDE DOSSYM.INC
34INCLUDE DEVSYM.INC
35include version.inc
36.cref
37.list
38
39 I_need SFN,WORD
40 I_NEED pJFN,DWORD
41 i_need DevIOBuf,BYTE
42 i_need DidCTRLC,BYTE
43 i_need INDOS,BYTE
44 i_need DSKSTCOM,BYTE
45 i_need DSKSTCALL,BYTE
46 i_need DSKSTST,WORD
47 i_need BCON,DWORD
48 i_need DSKCHRET,BYTE
49 i_need DSKSTCNT,WORD
50 i_need IDLEINT,BYTE
51 i_need CONSWAP,BYTE
52 i_need user_SS,WORD
53 i_need user_SP,WORD
54 i_need User_In_AX,WORD
55 i_need ERRORMODE,BYTE
56 i_need ConC_spsave,WORD
57 i_need Exit_type,BYTE
58 i_need PFLAG,BYTE
59 i_need ExitHold,DWORD
60 i_need WPErr,BYTE
61 i_need ReadOp,BYTE
62 i_need CONTSTK,WORD
63 i_need Exit_Code,WORD
64 i_need CurrentPDB,WORD
65 i_need DIVMES,BYTE
66 i_need DivMesLen,WORD
67 i_need ALLOWED,BYTE
68 i_need FAILERR,BYTE
69 i_need EXTERR,WORD
70 i_need ERR_TABLE_24,BYTE
71 I_need ErrMap24,BYTE
72 I_need ErrMap24End,BYTE
73 I_need fAborting,BYTE
74 I_need AUXStack,BYTE
75 I_need SCAN_FLAG,BYTE
76 I_need EXTOPEN_ON,BYTE ;AN000; DOS 4.0
77 I_need InterCon,BYTE ;AN000; DOS 4.0
78 I_need DOS34_FLAG,WORD ;AN000; DOS 4.0
79 I_need ACT_PAGE,WORD ;AN000; DOS 4.0
80 I_need Special_Version,WORD ;AN007; DOS 4.0
81if debug
82 I_need BugLev,WORD
83 I_need BugTyp,WORD
84include bugtyp.asm
85endif
86IF BUFFERFLAG
87 extrn restore_user_map:near
88ENDIF
89
90Break <Checks for ^C in CON I/O>
91
92ASSUME DS:NOTHING,ES:NOTHING
93
94 procedure DSKSTATCHK,NEAR ; Check for ^C if only one level in
95 CMP BYTE PTR [INDOS],1
96 retnz ; Do NOTHING
97 PUSH CX
98 PUSH ES
99 PUSH BX
100 PUSH DS
101 PUSH SI
102 PUSH CS
103 POP ES
104 Context DS
105 DOSAssume CS,<DS>,"DskStatChk"
106 MOV BYTE PTR [DSKSTCOM],DEVRDND
107 MOV BYTE PTR [DSKSTCALL],DRDNDHL
108 MOV [DSKSTST],0
109 IF DBCS ;AN000;
110 MOV AL, [InterCon] ;AN000;get type of status read 2/13/KK
111 MOV BYTE PTR [DSKCHRET],AL ;AN000; load interim flag into packet
112 ENDIF ;AN000;
113 MOV BX,OFFSET DOSGROUP:DSKSTCALL
114 LDS SI,[BCON]
115ASSUME DS:NOTHING
116 invoke DEVIOCALL2
117 TEST [DSKSTST],STBUI
118 JZ GotCh ; No characters available
119 XOR AL,AL ; Set zero
120RET36:
121 POP SI
122 POP DS
123 POP BX
124 POP ES
125 POP CX
126 return
127
128GotCh:
129 MOV AL,BYTE PTR [DSKCHRET]
130DSK1:
131 CMP AL,"C"-"@"
132 JNZ RET36
133 MOV BYTE PTR [DSKSTCOM],DEVRD
134 MOV BYTE PTR [DSKSTCALL],DRDWRHL
135 MOV BYTE PTR [DSKCHRET],CL
136 MOV [DSKSTST],0
137 MOV [DSKSTCNT],1
138 invoke DEVIOCALL2 ; Eat the ^C
139 POP SI
140 POP DS
141 POP BX ; Clean stack
142 POP ES
143 POP CX
144 JMP CNTCHAND
145
146NOSTOP:
147 CMP AL,"P"-"@"
148 JNZ check_next
149 CMP BYTE PTR [SCAN_FLAG],0 ; ALT_Q ?
150 JZ INCHKJ ; no
151 return
152check_next:
153 IF NOT TOGLPRN
154 CMP AL,"N"-"@"
155 JZ INCHKJ
156 ENDIF
157
158 CMP AL,"C"-"@"
159 JZ INCHKJ
160check_end:
161 return
162
163INCHKJ:
164 JMP INCHK
165
166EndProc DSKSTATCHK
167
168;
169; SpoolInt - signal processes that the DOS is truly idle. We are allowed to
170; do this ONLY if we are working on a 1-12 system call AND if we are not in
171; the middle of an INT 24.
172;
173procedure SPOOLINT,NEAR
174 PUSHF
175 test IdleInt,-1
176 jz POPFRet
177 test ErrorMode,-1
178 jnz POPFRet
179;
180; Note that we are going to allow an external program to issue system calls
181; at this time. We MUST preserve IdleInt across this.
182;
183 PUSH WORD PTR IdleInt
184 INT int_spooler
185 POP WORD PTR IdleInt
186POPFRET:
187 POPF
188 return
189EndProc SPOOLINT
190
191 procedure STATCHK,NEAR
192
193 invoke DSKSTATCHK ; Allows ^C to be detected under
194 ; input redirection
195 PUSH BX
196 XOR BX,BX
197 invoke GET_IO_SFT
198 POP BX
199 retc
200 MOV AH,1
201 invoke IOFUNC
202 JZ SPOOLINT
203 CMP AL,"S"-"@"
204 JNZ NOSTOP
205
206 CMP BYTE PTR [SCAN_FLAG],0 ;AN000; ALT_R ?
207 JNZ check_end ;AN000; yes
208 XOR AH,AH
209 invoke IOFUNC ; Eat Cntrl-S
210 JMP SHORT PAUSOSTRT
211PRINTOFF:
212PRINTON:
213 NOT BYTE PTR [PFLAG]
214 PUSH BX
215 MOV BX,4
216 invoke GET_IO_SFT
217 POP BX
218 retc
219 PUSH ES
220 PUSH DI
221 PUSH DS
222 POP ES
223 MOV DI,SI ; ES:DI -> SFT
224 TEST ES:[DI.sf_flags],sf_net_spool
225 JZ NORM_PR ; Not redirected, echo is OK
226 Callinstall NetSpoolEchoCheck,MultNet,38,<AX>,<AX> ; See if allowed
227 JNC NORM_PR ; Echo is OK
228 MOV BYTE PTR [PFLAG],0 ; If not allowed, disable echo
229 Callinstall NetSpoolClose,MultNet,36,<AX>,<AX> ; and close
230 JMP SHORT RETP6
231
232NORM_PR:
233 CMP BYTE PTR [PFLAG],0
234 JNZ PRNOPN
235 invoke DEV_CLOSE_SFT
236 JMP SHORT RETP6
237
238PRNOPN:
239 invoke DEV_OPEN_SFT
240RETP6:
241 POP DI
242 POP ES
243 return
244
245PAUSOLP:
246 CALL SPOOLINT
247PAUSOSTRT:
248 MOV AH,1
249 invoke IOFUNC
250 JZ PAUSOLP
251INCHK:
252 PUSH BX
253 XOR BX,BX
254 invoke GET_IO_SFT
255 POP BX
256 retc
257 XOR AH,AH
258 invoke IOFUNC
259 CMP AL,"P"-"@"
260;;;;; 7/14/86 ALT_Q key fix
261
262 JZ PRINTON ; no! must be CTRL_P
263
264NOPRINT:
265;;;;; 7/14/86 ALT_Q key fix
266 IF NOT TOGLPRN
267 CMP AL,"N"-"@"
268 JZ PRINTOFF
269 ENDIF
270 CMP AL,"C"-"@"
271 retnz
272EndProc STATCHK
273
274 procedure CNTCHAND,NEAR
275; Ctrl-C handler.
276; "^C" and CR/LF is printed. Then the user registers are restored and the
277; user CTRL-C handler is executed. At this point the top of the stack has 1)
278; the interrupt return address should the user CTRL-C handler wish to allow
279; processing to continue; 2) the original interrupt return address to the code
280; that performed the function call in the first place. If the user CTRL-C
281; handler wishes to continue, it must leave all registers unchanged and RET
282; (not IRET) with carry CLEAR. If carry is SET then an terminate system call
283; is simulated.
284 TEST [DOS34_FLAG],CTRL_BREAK_FLAG ;AN002; from RAWOUT
285 JNZ around_deadlock ;AN002;
286 MOV AL,3 ; Display "^C"
287 invoke BUFOUT
288 invoke CRLF
289around_deadlock: ;AN002;
290 Context DS
291 CMP BYTE PTR [CONSWAP],0
292 JZ NOSWAP
293 invoke SWAPBACK
294NOSWAP:
295 CLI ; Prepare to play with stack
296 MOV SS,[user_SS] ; User stack now restored
297ASSUME SS:NOTHING
298 MOV SP,[user_SP]
299 invoke restore_world ; User registers now restored
300ASSUME DS:NOTHING
301 MOV BYTE PTR [INDOS],0 ; Go to known state
302 MOV BYTE PTR [ERRORMODE],0
303 MOV [ConC_spsave],SP ; save his SP
304 CLC
305 INT int_ctrl_c ; Execute user Ctrl-C handler
306;
307; The user has returned to us. The circumstances we allow are:
308;
309; IRET We retry the operation by redispatching the system call
310; CLC/RETF POP the stack and retry
311; ... Exit the current process with ^C exit
312;
313; User's may RETURN to us and leave interrupts on. Turn 'em off just to be
314; sure
315;
316 CLI
317 MOV [user_IN_AX],ax ; save the AX
318 PUSHF ; and the flags (maybe new call)
319 POP AX
320;
321; See if the input stack is identical to the output stack
322;
323 CMP SP,[ConC_spsave]
324 JNZ ctrlc_try_new ; current SP not the same as saved SP
325;
326; Repeat the operation by redispatching the system call.
327;
328ctrlc_repeat:
329 MOV AX,User_In_AX
330 transfer COMMAND
331;
332; The current SP is NOT the same as the input SP. Presume that he RETF'd
333; leaving some flags on the stack and examine the input
334;
335ctrlc_try_new:
336 ADD SP,2 ; pop those flags
337 TEST AX,f_carry ; did he return with carry?
338 JZ Ctrlc_Repeat ; no carry set, just retry
339;
340; Well... time to abort the user. Signal a ^C exit and use the EXIT system
341; call..
342;
343ctrlc_abort:
344 MOV AX,(EXIT SHL 8) + 0
345 MOV DidCTRLC,-1
346 transfer COMMAND ; give up by faking $EXIT
347
348EndProc CNTCHAND
349
350Break <DIVISION OVERFLOW INTERRUPT>
351
352; Default handler for division overflow trap
353 procedure DIVOV,NEAR
354ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
355 MOV SI,OFFSET DOSGROUP:DIVMES
356 MOV BX,DivMesLen
357 MOV AX,CS
358 MOV SS,AX
359 MOV SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts
360 CALL OutMes
361 JMP ctrlc_abort ; Use Ctrl-C abort on divide overflow
362EndProc DIVOV
363
364;
365; OutMes: perform message output
366; Inputs: SS:SI points to message
367; BX has message length
368; Outputs: message to BCON
369;
370procedure OutMes,NEAR
371
372 Context ES ; get ES addressability
373 Context DS ; get DS addressability
374
375 MOV BYTE PTR [DskStCom],DevWrt
376 MOV BYTE PTR [DskStCall],DRdWrHL
377 MOV [DskSTST],0
378 MOV [DskStCnt],BX
379 MOV BX,OFFSET DOSGROUP:DskStCall
380 MOV WORD PTR [DskChRet+1],SI ; transfer address (need an EQU)
381 LDS SI,[BCON]
382ASSUME DS:NOTHING
383 invoke DEVIOCALL2
384 MOV WORD PTR [DskChRet+1],OFFSET DOSGROUP:DevIOBuf
385 MOV [DskStCnt],1
386 return
387EndProc OutMes
388
389Break <CHARHRD,HARDERR,ERROR -- HANDLE DISK ERRORS AND RETURN TO USER>
390
391 procedure CHARHARD,NEAR
392ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
393
394; Character device error handler
395; Same function as HARDERR
396
397 OR AH,allowed_FAIL + allowed_IGNORE + allowed_RETRY
398 MOV Allowed,AH
399 MOV WORD PTR [EXITHOLD+2],ES
400 MOV WORD PTR [EXITHOLD],BP
401 PUSH SI
402 AND DI,STECODE
403 MOV BP,DS ; Device pointer is BP:SI
404 CALL FATALC
405 POP SI
406 return
407EndProc CHARHARD
408
409; Hard disk error handler. Entry conditions:
410; DS:BX = Original disk transfer address
411; DX = Original logical sector number
412; CX = Number of sectors to go (first one gave the error)
413; AX = Hardware error code
414; DI = Original sector transfer count
415; ES:BP = Base of drive parameters
416; [READOP] = 0 for read, 1 for write
417; [ALLOWED] Set with allowed responses to this error (other bits MUST BE 0)
418; Output:
419; [FAILERR] will be set if user responded FAIL
420
421 procedure HardErr,NEAR
422 ASSUME DS:NOTHING,ES:NOTHING
423
424 XCHG AX,DI ; Error code in DI, count in AX
425 AND DI,STECODE ; And off status bits
426 CMP DI,error_I24_write_protect ; Write Protect Error?
427 JNZ NOSETWRPERR
428 PUSH AX
429 MOV AL,ES:[BP.dpb_drive]
430 MOV BYTE PTR [WPERR],AL ; Flag drive with WP error
431 POP AX
432NOSETWRPERR:
433 SUB AX,CX ; Number of sectors successfully transferred
434 ADD DX,AX ; First sector number to retry
435 PUSH DX
436 MUL ES:[BP.dpb_sector_size] ; Number of bytes transferred
437 POP DX
438 ADD BX,AX ; First address for retry
439 XOR AH,AH ; Flag disk section in error
440 CMP DX,ES:[BP.dpb_first_FAT] ; In reserved area?
441 JB ERRINT
442 INC AH ; Flag for FAT
443 CMP DX,ES:[BP.dpb_dir_sector] ; In FAT?
444 JAE TESTDIR ; No
445 MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace
446 JMP SHORT ERRINT
447
448TESTDIR:
449 INC AH
450 CMP DX,ES:[BP.dpb_first_sector] ; In directory?
451 JB ERRINT
452 INC AH ; Must be in data area
453ERRINT:
454 SHL AH,1 ; Make room for read/write bit
455 OR AH,BYTE PTR [READOP] ; Set bit 0
456; If we have a write protect error when writing on a critical area on disk,
457; do not allow a retry as this may write out garbage on any subsequent disk.
458 ;test ah,1
459 ;jz Not_Crit
460 ;cmp ah,5
461 ;ja Not_Crit
462 ;and [ALLOWED],NOT Allowed_RETRY
463Not_Crit:
464 OR AH,[ALLOWED] ; Set the allowed_ bits
465 entry FATAL
466 MOV AL,ES:[BP.dpb_drive] ; Get drive number
467 entry FATAL1
468 MOV WORD PTR [EXITHOLD+2],ES
469 MOV WORD PTR [EXITHOLD],BP ; The only things we preserve
470 LES SI,ES:[BP.dpb_driver_addr]
471 MOV BP,ES ; BP:SI points to the device involved
472;
473; DI has the INT-24-style extended error. We now map the error code for this
474; into the normalized get extended error set by using the ErrMap24 table as an
475; translate table. Note that we translate ONLY the device returned codes and
476; leave all others beyond the look up table alone.
477;
478FATALC:
479 call SET_I24_EXTENDED_ERROR
480 CMP DI,error_I24_gen_failure
481 JBE GOT_RIGHT_CODE ; Error codes above gen_failure get
482 MOV DI,error_I24_gen_failure ; mapped to gen_failure. Real codes
483 ; Only come via GetExtendedError
484
485 entry NET_I24_ENTRY
486; Entry point used by REDIRector on Network I 24 errors.
487;
488; ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
489;
490; ALL I 24 regs set up. ALL Extended error info SET. ALLOWED Set.
491; EXITHOLD set for restore of ES:BP.
492
493GOT_RIGHT_CODE:
494 CMP BYTE PTR [ERRORMODE],0 ; No INT 24s if already INT 24
495 JZ NoSetFail
496 MOV AL,3
497 JMP FailRet
498NoSetFail:
499IF BUFFERFLAG
500 invoke RESTORE_USER_MAP ;AN000;LB. restore user's EMS map
501ENDIF
502 MOV [CONTSTK],SP
503 Context ES
504 fmt TypINT24,LevLog,<"INT 24: AX = $x DI = $x\n">,<AX,DI>
505;
506; Wango!!! We may need to free some user state info... In particular, we
507; may have locked down a JFN for a user and he may NEVER return to us. Thus,
508; we need to free it here and then reallocate it when we come back.
509;
510 CMP SFN,-1
511 JZ NoFree
512 SaveReg <DS,SI>
513 LDS SI,pJFN
514 MOV BYTE PTR [SI],0FFH
515 RestoreReg <SI,DS>
516NoFree:
517 CLI ; Prepare to play with stack
518 INC BYTE PTR [ERRORMODE] ; Flag INT 24 in progress
519 DEC BYTE PTR [INDOS] ; INT 24 handler might not return
520;; Extneded Open hooks
521 TEST [DOS34_FLAG],Force_I24_Fail ;AN000;IFS. form IFS Call Back ;AN000;
522 JNZ faili24 ;AN000;IFS. ;AN000;
523 TEST [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;IFS.I24 error disabled ;AN000;
524 JZ i24yes ;AN000;IFS.no ;AN000;
525faili24: ;AN000;
526 MOV AL,3 ;AN000;IFS.fake fail ;AN000;
527 JMP passi24 ;AN000;IFS.exit ;AN000;
528i24yes: ;AN000;
529
530;; Extended Open hooks
531 MOV SS,[user_SS]
532ASSUME SS:NOTHING
533 MOV SP,ES:[user_SP] ; User stack pointer restored
534 INT int_fatal_abort ; Fatal error interrupt vector, must preserve ES
535 MOV ES:[user_SP],SP ; restore our stack
536 MOV ES:[user_SS],SS
537 MOV BP,ES
538 MOV SS,BP
539ASSUME SS:DOSGROUP
540passi24: ;AN000;
541 MOV SP,[CONTSTK]
542 INC BYTE PTR [INDOS] ; Back in the DOS
543 MOV BYTE PTR [ERRORMODE],0 ; Back from INT 24
544 STI
545;; MOV [ACT_PAGE],-1 ;LB. invalidate DOS active page ;AN000;
546;; invoke SAVE_MAP ;LB. save user's EMS map ;AN000;
547 fmt TypINT24,LevLog,<"INT 24: User reply = $x\n">,<AX>
548FAILRET:
549 LES BP,[EXITHOLD]
550ASSUME ES:NOTHING
551;
552; Triage the user's reply.
553;
554 CMP AL,1
555 JB CheckIgnore ; 0 => ignore
556 JZ CheckRetry ; 1 => retry
557 CMP AL,3 ; 3 => fail
558 JNZ DoAbort ; 2, invalid => abort
559;
560; The reply was fail. See if we are allowed to fail.
561;
562 TEST [ALLOWED],allowed_FAIL ; Can we?
563 JZ DoAbort ; No, do abort
564DoFail:
565 MOV AL,3 ; just in case...
566 TEST [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO. I24 error disabled
567 JNZ cleanup ;AN000;EO. no
568 INC [FAILERR] ; Tell everybody
569CleanUp:
570 MOV WpErr,-1
571 CMP SFN,-1
572 retz
573 SaveReg <DS,SI,AX>
574 MOV AX,SFN
575 LDS SI,pJFN
576 MOV [SI],AL
577 RestoreReg <AX,SI,DS>
578 return
579;
580; The reply was IGNORE. See if we are allowed to ignore.
581;
582CheckIgnore:
583 TEST [ALLOWED],allowed_IGNORE ; Can we?
584 JZ DoFail ; No, do fail
585 JMP CleanUp
586;
587; The reply was RETRY. See if we are allowed to retry.
588;
589CheckRetry:
590 TEST [ALLOWED],allowed_RETRY ; Can we?
591 JZ DoFail ; No, do fail
592 JMP CleanUp
593;
594; The reply was ABORT.
595;
596DoAbort:
597 Context DS
598 CMP BYTE PTR [CONSWAP],0
599 JZ NOSWAP2
600 invoke SWAPBACK
601NOSWAP2:
602;
603; See if we are to truly abort. If we are in the process of aborting, turn
604; this abort into a fail.
605;
606 TEST fAborting,-1
607 JNZ DoFail
608;
609; Set return code
610;
611 MOV BYTE PTR [exit_Type],Exit_hard_error
612 XOR AL,AL
613;
614; we are truly aborting the process. Go restore information from the PDB as
615; necessary.
616;
617 Transfer exit_inner
618;
619; reset_environment checks the DS value against the CurrentPDB. If they are
620; different, then an old-style return is performed. If they are the same,
621; then we release jfns and restore to parent. We still use the PDB at DS:0 as
622; the source of the terminate addresses.
623;
624; Some subtlety: We are about to issue a bunch of calls that *may* generate
625; INT 24s. We *cannot* allow the user to restart the abort process; we may
626; end up aborting the wrong process or turn a terminate/stay/resident into a
627; normal abort and leave interrupt handlers around. What we do is to set a
628; flag that will indicate that if any abort code is seen, we just continue the
629; operation. In essence, we dis-allow the abort response.
630;
631; output: none.
632;
633 entry reset_environment
634 ASSUME DS:NOTHING,ES:NOTHING
635
636 invoke Reset_Version ;AN007;MS. reset version number
637 PUSH DS ; save PDB of process
638
639;
640; There are no critical sections in force. Although we may enter here with
641; critical sections locked down, they are no longer relevant. We may safely
642; free all allocated resources.
643;
644 MOV AH,82h
645 INT int_IBM
646
647 MOV fAborting,-1 ; signal abort in progress
648
649 CallInstall NetResetEnvironment, multNet, 34 ;DOS 4.00 doesn't need it
650 ; Allow REDIR to clear some stuff
651 ; On process exit.
652 MOV AL,int_Terminate
653 invoke $Get_interrupt_vector ; and who to go to
654
655 POP CX ; get ThisPDB
656 SaveReg <ES,BX> ; save return address
657
658 MOV BX,[CurrentPDB] ; get currentPDB
659 MOV DS,BX
660 MOV AX,DS:[PDB_Parent_PID] ; get parentPDB
661
662;
663; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB
664; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not
665; Exit_keep_process
666;
667 CMP AX,BX
668 JZ reset_return ; parentPDB = CurrentPDB
669 CMP BX,CX
670 JNZ reset_return ; CurrentPDB <> ThisPDB
671 PUSH AX ; save parent
672 CMP BYTE PTR [exit_type],Exit_keep_process
673 JZ reset_to_parent ; keeping this process
674;
675; We are truly removing a process. Free all allocation blocks belonging to
676; this PDB
677;
678 invoke arena_free_process
679;
680; Kill off remainder of this process. Close file handles and signal to
681; relevant network folks that this process is dead. Remember that CurrentPDB
682; is STILL the current process!
683;
684 invoke DOS_ABORT
685
686reset_to_parent:
687 POP [CurrentPDB] ; set up process as parent
688
689reset_return: ; come here for normal return
690 PUSH CS
691 POP DS
692 ASSUME DS:DOSGROUP
693 MOV AL,-1
694;
695; make sure that everything is clean In this case ignore any errors, we cannot
696; "FAIL" the abort, the program being aborted is dead.
697;
698 EnterCrit critDisk
699 invoke FLUSHBUF
700 LeaveCrit critDisk
701;
702; Decrement open ref. count if we had done a virtual open earlier.
703;
704 invoke CHECK_VIRT_OPEN
705IF BUFFERFLAG
706 invoke RESTORE_USER_MAP ;AN000;LB. restore user's EMS map
707ENDIF
708 CLI
709 MOV BYTE PTR [INDOS],0 ; Go to known state
710 MOV BYTE PTR [WPERR],-1 ; Forget about WP error
711 MOV fAborting,0 ; let aborts occur
712 POP WORD PTR ExitHold
713 POP WORD PTR ExitHold+2
714;
715; Snake into multitasking... Get stack from CurrentPDB person
716;
717 MOV DS,[CurrentPDB]
718 ASSUME DS:NOTHING
719 MOV SS,WORD PTR DS:[PDB_user_stack+2]
720 MOV SP,WORD PTR DS:[PDB_user_stack]
721
722 ASSUME SS:NOTHING
723 invoke restore_world
724 ASSUME ES:NOTHING
725 MOV User_SP,AX
726 POP AX ; suck off CS:IP of interrupt...
727 POP AX
728 POP AX
729 MOV AX,0F202h ; STI
730 PUSH AX
731 PUSH WORD PTR [EXITHOLD+2]
732 PUSH WORD PTR [EXITHOLD]
733 MOV AX,User_SP
734 IRET ; Long return back to user terminate address
735EndProc HardErr
736
737;
738; This routine handles extended error codes.
739; Input : DI = error code from device
740; Output: All EXTERR fields are set
741;
742Procedure SET_I24_EXTENDED_ERROR,NEAR
743 PUSH AX
744 MOV AX,OFFSET DOSGroup:ErrMap24End
745 SUB AX,OFFSET DOSGroup:ErrMap24
746;
747; AX is the index of the first unavailable error. Do not translate if
748; greater or equal to AX.
749;
750 CMP DI,AX
751 MOV AX,DI
752 JAE NoTrans
753 MOV AL,ErrMap24[DI]
754 XOR AH,AH
755NoTrans:
756 MOV [EXTERR],AX
757 POP AX
758;
759; Now Extended error is set correctly. Translate it to get correct error
760; locus class and recommended action.
761;
762 PUSH SI
763 MOV SI,OFFSET DOSGROUP:ERR_TABLE_24
764 invoke CAL_LK ; Set other extended error fields
765 POP SI
766 ret
767EndProc SET_I24_EXTENDED_ERROR
768
769CODE ENDS
770 END
771 \ No newline at end of file
diff --git a/v4.0/src/DOS/DELETE.ASM b/v4.0/src/DOS/DELETE.ASM
new file mode 100644
index 0000000..c5473c0
--- /dev/null
+++ b/v4.0/src/DOS/DELETE.ASM
@@ -0,0 +1,777 @@
1; SCCSID = @(#)delete.asm 1.3 85/10/18
2; SCCSID = @(#)delete.asm 1.3 85/10/18
3TITLE DOS_DELETE - Internal DELETE call for MS-DOS
4NAME DOS_DELETE
5; Low level routine for deleting files
6;
7; DOS_DELETE
8; REN_DEL_Check
9; FastOpen_Delete ; DOS 3.3
10; FastOpen_Update ; DOS 3.3
11; FastSeek_Open ; DOS 4.00
12; FSeek_dispatch ; DOS 4.00
13; FastSeek_Close ; DOS 4.00
14; FastSeek_Delete ; DOS 4.00
15; Delete_FSeek ; DOS 4.00
16; FastSeek_Lookup ; DOS 4.00
17; FastSeek_Insert ; DOS 4.00
18; FastSeek_Truncate ; DOS 4.00
19; FS_doit ; DOS 4.00
20;
21; Revision history:
22;
23; A000 version 4.00 Jan. 1988
24;
25
26;
27; get the appropriate segment definitions
28;
29.xlist
30include dosseg.asm
31
32CODE SEGMENT BYTE PUBLIC 'CODE'
33 ASSUME SS:DOSGROUP,CS:DOSGROUP
34
35.xcref
36INCLUDE DOSSYM.INC
37INCLUDE DEVSYM.INC
38INCLUDE FASTOPEN.INC
39INCLUDE fastseek.inc
40INCLUDE fastxxxx.inc
41.cref
42.list
43
44Installed = TRUE
45
46 i_need NoSetDir,BYTE
47 i_need Creating,BYTE
48 i_need DELALL,BYTE
49 i_need THISDPB,DWORD
50 i_need THISSFT,DWORD
51 i_need THISCDS,DWORD
52 i_need CURBUF,DWORD
53 i_need ATTRIB,BYTE
54 i_need SATTRIB,BYTE
55 i_need WFP_START,WORD
56 i_need FoundDel,BYTE
57 i_need AUXSTACK,BYTE
58 i_need VOLCHNG_FLAG,BYTE
59 i_need JShare,DWORD
60 i_need FastOpenTable,BYTE ; DOS 3.3
61 i_need FastTable,BYTE ; DOS 4.00
62 i_need FSeek_drive,BYTE ; DOS 4.00
63 i_need FSeek_firclus,WORD ; DOS 4.00
64 i_need FSeek_logclus,WORD ; DOS 4.00
65 i_need FSeek_logsave,WORD ; DOS 4.00
66 i_need FastSeekflg,BYTE ; DOS 4.00
67 i_need Del_ExtCluster,WORD ; DOS 4.00
68 i_need SAVE_BX,WORD ; DOS 4.00
69 i_need DMAADD,DWORD
70 i_need RENAMEDMA,BYTE
71
72; Inputs:
73; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
74; terminated)
75; [CURR_DIR_END] Points to end of Current dir part of string
76; ( = -1 if current dir not involved, else
77; Points to first char after last "/" of current dir part)
78; [THISCDS] Points to CDS being used
79; (Low word = -1 if NUL CDS (Net direct request))
80; [SATTRIB] Is attribute of search, determines what files can be found
81; Function:
82; Delete the specified file(s)
83; Outputs:
84; CARRY CLEAR
85; OK
86; CARRY SET
87; AX is error code
88; error_file_not_found
89; Last element of path not found
90; error_path_not_found
91; Bad path (not in curr dir part if present)
92; error_bad_curr_dir
93; Bad path in current directory part of path
94; error_access_denied
95; Attempt to delete device or directory
96; ***error_sharing_violation***
97; Deny both access required, generates an INT 24.
98; This error is NOT returned. The INT 24H is generated,
99; and the file is ignored (not deleted). Delete will
100; simply continue on looking for more files.
101; Carry will NOT be set in this case.
102; DS preserved, others destroyed
103
104fileFound = 01h
105fileDeleted = 10h
106
107 procedure DOS_DELETE,NEAR
108 DOSAssume CS,<DS>,"DOS_Delete"
109 ASSUME ES:NOTHING
110
111 Invoke TestNet
112 JNC LOCAL_DELETE
113; invoke OWN_SHARE2 ;IFS. IFS owns share ? ;AN000;
114; JZ ifsshare ;IFS. yes ;AN000;
115; PUSH WORD PTR [DMAADD+2] ;IFS. save DMAADD ;AN000;
116; PUSH WORD PTR [DMAADD] ;IFS. ;AN000;
117; CALL IFS_SEARCH_FIRST ;IFS. do search first ;AN000;
118; JC nofiles ;IFS. file not existing ;AN000;
119delete_next_file: ;IFS. ;AN000;
120; CALL IFS_REN_DEL_CHECK ;IFS. do REN_DEL_CHECK ;AN000;
121; JNC share_okok ;IFS. share ok ;AN000;
122; MOV AX,error_sharing_violation ;IFS. share violation ;AN000;
123; JMP SHORT nofiles ;IFS. ;AN000;
124share_okok:
125; MOV AX,(multNET SHL 8) OR 19 ;IFS. delete it now ;AN000;
126;; INT 2FH ;IFS. ;AN000;
127; JC nofiles ;IFS. error ;AN000;
128; invoke DOS_SEARCH_NEXT ;IFS. get next entry ;AN000;
129; JNC delete_next_file ;IFS. ;AN000;
130; CLC ;IFS. no more files ;AN000;
131nofiles:
132; POP WORD PTR [DMAADD] ;IFS. retor DMAADD ;AN000;
133; POP WORD PTR [DMAADD+2] ;IFS. ;AN000;
134; ret ;IFS. return
135ifsshare:
136
137
138IF NOT Installed
139 transfer NET_DELETE
140ELSE
141 MOV AX,(multNET SHL 8) OR 19
142 INT 2FH
143 return
144ENDIF
145
146LOCAL_DELETE:
147 MOV [FoundDel],00 ; No files found and no files deleted
148 EnterCrit critDisk
149 MOV WORD PTR [CREATING],0E500H ; Assume not del *.*
150 MOV SI,[WFP_START]
151SKPNUL:
152 LODSB
153 OR AL,AL
154 JNZ SKPNUL ; go to end
155 SUB SI,4 ; Back over possible "*.*"
156 CMP WORD PTR [SI],("." SHL 8 OR "*")
157 JNZ TEST_QUEST
158 CMP BYTE PTR [SI+2],"*"
159 JZ CHECK_ATTS
160TEST_QUEST:
161 SUB SI,9 ; Back over possible "????????.???"
162 XCHG DI,SI
163 context ES
164 MOV AX,"??"
165 MOV CX,4 ; four sets of "??"
166 REPE SCASW
167 JNZ NOT_ALL
168 XCHG DI,SI
169 LODSW
170 CMP AX,("?" SHL 8) OR "."
171 JNZ NOT_ALL
172 LODSW
173 CMP AX,"??"
174 JNZ NOT_ALL
175CHECK_ATTS:
176 MOV AL,BYTE PTR [SATTRIB]
177 AND AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only
178 ; Look only at hidden bits
179 CMP AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only
180 ; All must be set
181 JNZ NOT_ALL
182
183; NOTE WARNING DANGER-----
184; This DELALL stuff is not safe. It allows directories to be deleted.
185; It should ONLY be used by FORMAT in the ROOT directory.
186;
187
188 MOV [DELALL],0 ; DEL *.* - flag deleting all
189NOT_ALL:
190 MOV [NoSetDir],1
191 invoke GetPathNoSet
192 ASSUME ES:NOTHING
193 JNC Del_found
194 JNZ bad_path
195 OR CL,CL
196 JZ bad_path
197No_file:
198 MOV AX,error_file_not_found
199ErrorReturn:
200 STC
201 LeaveCrit critDisk
202 return
203
204bad_path:
205 MOV AX,error_path_not_found
206 JMP ErrorReturn
207
208Del_found:
209 JNZ NOT_DIR ; Check for dir specified
210 CMP DelAll,0 ; DelAll = 0 allows delete of dir.
211 JZ Not_Dir
212Del_access_err:
213 MOV AX,error_access_denied
214 JMP ErrorReturn
215
216NOT_DIR:
217 OR AH,AH ; Check if device name
218 JS Del_access_err ; Can't delete I/O devices
219;
220; Main delete loop. CURBUF+2:BX points to a matching directory entry.
221;
222DELFILE:
223 OR [FoundDel],fileFound ; file found, not deleted yet
224;
225; If we are deleting the Volume ID, then we set VOLUME_CHNG flag to make
226; DOS issue a build BPB call the next time this drive is accessed.
227;
228 PUSH DS
229 MOV AH,[DELALL]
230 LDS DI,[CURBUF]
231ASSUME DS:NOTHING
232;; Extended Attributes
233; PUSH AX ;FT. save cluster of XA ;AN000;
234; MOV AX,DS:[BX.dir_ExtCluster];FT. ;AN000;
235; MOV [Del_ExtCluster],AX ;FT. ;AN000;
236; POP AX ;FT, ;AN000;
237
238;; Extended Attributes
239 TEST [Attrib],attr_read_only ; are we deleting RO files too?
240 JNZ DoDelete ; yes
241 TEST DS:[BX.dir_attr],attr_read_only
242 JZ DoDelete ; not read only
243 POP DS
244 JMP SHORT DelNxt ; Skip it (Note ES:BP not set)
245
246DoDelete:
247 call REN_DEL_Check ; Sets ES:BP = [THISDPB]
248 JNC DEL_SHARE_OK
249 POP DS
250 JMP SHORT DelNxt ; Skip it
251
252DEL_SHARE_OK:
253 Assert ISBUF,<DS,DI>,"Del_Share_OK"
254 TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
255 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
256 invoke INC_DIRTY_COUNT ;LB. ;AN000;
257 OR [DI.buf_flags],buf_dirty
258yesdirty:
259 MOV [BX],AH ; Put in E5H or 0
260 MOV BX,[SI] ; Get firclus pointer
261 POP DS
262 DOSAssume CS,<DS>,"Del_Share_OK"
263 OR [FoundDel],fileDeleted ; Deleted file
264 CMP BX,2
265 JB DELEXT ; File has invalid FIRCLUS (too small)
266 CMP BX,ES:[BP.dpb_max_cluster]
267 JA DELEXT ; File has invalid FIRCLUS (too big)
268;; FastSeek 10/27/86
269 CALL Delete_FSeek ; delete the fastseek entry
270;; FastSeek 10/27/86
271
272 invoke RELEASE ; Free file data
273 JC No_fileJ
274; DOS 3.3 FastOpen
275
276 CALL FastOpen_Delete ; delete the dir info in fastopen
277
278
279; DOS 3.3 FastOpen
280;; Extended Attributes
281DELEXT:
282
283; MOV BX,[Del_ExtCluster] ;FT. delete XA cluster chain ;AN000;
284; CMP BX,2 ;FT. ;AN000;
285; JB DELNXT ;FT. XA has invalid cluster (too small) ;AN000;
286; CMP BX,ES:[BP.dpb_max_cluster];FT. ;AN000;
287; JA DELNXT ;FT. XA has invalid cluster (too big) ;AN000;
288; invoke RELEASE ;FT. Free extended attrs cluster ;AN000;
289; JC No_fileJ ;FT. ;AN000;
290
291;; Extended Attributes
292DELNXT:
293 LES BP,[THISDPB] ; Possible to get here without this set
294 invoke GETENTRY ; Registers need to be reset
295 JC No_fileJ
296 invoke NEXTENT
297if DEBUG
298 JC Flsh
299 JMP DelFile
300flsh:
301ELSE
302 JNC DELFILE
303ENDIF
304 LES BP,[THISDPB] ; NEXTENT sets ES=DOSGROUP
305 MOV AL,ES:[BP.dpb_drive]
306 invoke FLUSHBUF
307 JC No_fileJ
308;
309; Now we need to test FoundDel for our flags. The cases to consider are:
310;
311; not found not deleted file not found
312; not found deleted *** impossible ***
313; found not deleted access denied (read-only)
314; found deleted no error
315;
316 TEST FoundDel,fileDeleted ; did we delete a file?
317 JZ DelError ; no, figure out what's wrong.
318; We set VOLCHNG_FLAG to indicate that we have changed the volume label
319; and to force the DOS to issue a media check.
320 TEST [Attrib],attr_volume_id
321 jz No_Set_Flag
322 PUSH AX
323 PUSH ES
324 PUSH DI
325 LES DI,[THISCDS]
326ASSUME ES:NOTHING
327 MOV AH,BYTE PTR ES:[DI] ; Get drive
328 SUB AH,'A' ; Convert to 0-based
329 mov byte ptr [VOLCHNG_FLAG],AH
330 XOR BH,BH ;>32mb delte volume id from boot record ;AN000;
331 invoke Set_Media_ID ;>32mb set voulme id to boot record ;AN000;
332 invoke FATRead_CDS ; force media check
333 POP DI
334 POP ES
335 POP AX
336No_Set_Flag:
337 LeaveCrit critDisk ; carry is clear
338 return
339DelError:
340 TEST FoundDel,fileFound ; not deleted. Did we find file?
341 JNZ Del_access_errJ ; yes. Access denied
342No_fileJ:
343 JMP No_file ; Nope
344Del_Access_errJ:
345 JMP Del_access_err
346
347EndProc DOS_DELETE
348
349Break <REN_DEL_Check - check for access for rename and delete>
350
351; Inputs:
352; [THISDPB] set
353; [CURBUF+2]:BX points to entry
354; [CURBUF+2]:SI points to firclus field of entry
355; [WFP_Start] points to name
356; Function:
357; Check for Exclusive access on given file.
358; Used by RENAME, SET_FILE_INFO, and DELETE.
359; Outputs:
360; ES:BP = [THISDPB]
361; NOTE: The WFP string pointed to by [WFP_Start] Will be Modified. The
362; last element will be loaded from the directory entry. This is
363; so the name given to the sharer doesn't have any meta chars in
364; it.
365; Carry set if sharing violation, INT 24H generated
366; NOTE THAT AX IS NOT error_sharing_violation.
367; This is because input AX is preserved.
368; Caller must set the error if needed.
369; Carry clear
370; OK
371; AX,DS,BX,SI,DI preserved
372
373 procedure REN_DEL_Check,NEAR
374ASSUME DS:NOTHING,ES:NOTHING
375
376 PUSH DS
377 PUSH DI
378 PUSH AX
379 PUSH BX
380 PUSH SI ; Save CURBUF pointers
381 context ES
382ASSUME ES:DOSGROUP
383 MOV DI,[WFP_START] ; ES:DI -> WFP
384 MOV SI,BX
385 MOV DS,WORD PTR [CURBUF+2] ; DS:SI -> entry (FCB style name)
386 MOV BX,DI ; Set backup limit for skipback
387 ADD BX,2 ; Skip over d: to point to leading '\'
388 invoke StrLen ; CX is length of ES:DI including NUL
389 DEC CX ; Don't include nul in count
390 ADD DI,CX ; Point to NUL at end of string
391 invoke SkipBack ; Back up one element
392 INC DI ; Point to start of last element
393 MOV [SAVE_BX],DI ;IFS. save for DOS_RENAME ;AN000;
394 invoke PackName ; Transfer name from entry to ASCIZ tail.
395 POP SI ; Get back entry pointers
396 POP BX
397 PUSH BX
398 PUSH SI ; Back on stack
399 context DS
400ASSUME DS:DOSGROUP
401;
402; Close the file if possible by us.
403;
404if installed
405 Call JShare + 13 * 4
406else
407 Call ShCloseFile
408endif
409 MOV WORD PTR [THISSFT+2],DS
410 MOV WORD PTR [THISSFT],OFFSET DOSGROUP:AUXSTACK - (SIZE sf_entry)
411 ; Scratch space
412 XOR AH,AH ; Indicate file to DOOPEN (high bit off)
413 invoke DOOPEN ; Fill in SFT for share check
414 LES DI,[THISSFT]
415 MOV ES:[DI.sf_mode],sharing_deny_both ; requires exclusive access
416 MOV ES:[DI.sf_ref_count],1 ; Pretend open
417 invoke ShareEnter
418 jc CheckDone
419 LES DI,[THISSFT]
420 MOV ES:[DI.sf_ref_count],0 ; Pretend closed and free
421 invoke SHAREEND ; Tell sharer we're done with THISSFT
422 CLC
423CheckDone:
424 LES BP,[THISDPB]
425 POP SI
426 POP BX
427 POP AX
428 POP DI
429 POP DS
430 return
431
432EndProc REN_DEL_Check
433
434Break <FastOpen_Delete - delete dir info in fastopen>
435
436; Inputs:
437; None
438; Function:
439; Call FastOpen to delete the dir info.
440; Outputs:
441; None
442;
443;
444
445 procedure FastOpen_Delete,NEAR
446ASSUME DS:NOTHING,ES:NOTHING
447 PUSHF ; save flag
448 PUSH SI ; save registers
449 PUSH BX
450 PUSH AX
451
452 MOV SI,[WFP_Start] ; ds:si points to path name
453 MOV AL,FONC_delete ; al = 3
454fastinvoke:
455 MOV BX,OFFSET DOSGROUP:FastTable + 2
456 CALL DWORD PTR [BX] ; call fastopen
457
458 POP AX ; restore registers
459 POP BX
460 POP SI
461 POPF ; restore flag
462 return
463EndProc FastOpen_Delete
464
465
466Break <FastOpen_Update - update dir info in fastopen>
467
468; Inputs:
469; DL drive number (A=0,B=1,,,)
470; CX first cluster #
471; AH 0 updates dir entry
472; 1 updates CLUSNUM , BP = new CLUSNUM
473; ES:DI directory entry
474; Function:
475; Call FastOpen to update the dir info.
476; Outputs:
477; None
478;
479;
480
481 procedure FastOpen_Update,NEAR
482ASSUME DS:NOTHING,ES:NOTHING
483 PUSHF ; save flag
484 PUSH SI
485 PUSH BX ; save regs
486 PUSH AX
487
488 MOV AL,FONC_update ; al = 4
489 JMP fastinvoke
490
491EndProc FastOpen_Update
492
493Break <FastSeek_Open - create a file extent cache entry>
494
495; Inputs:
496; DL drive number (0=A,1=B,,,)
497; CX first cluster #
498; Function:
499; Create a file extent cache entry
500; Outputs:
501; None
502;
503;
504
505 procedure FastSeek_Open,NEAR ;AN000;
506ASSUME DS:NOTHING,ES:NOTHING ;AN000;
507 ;AN000;
508 TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000;
509 JZ fs_no11 ; no ;AN000;
510 PUSH SI ; save regs ;AN000;
511 PUSH AX ;AN000;
512 MOV AL,FSEC_open ; al = 11 ;AN000;
513fseek_disp: ;AN000;
514 CALL FSeek_dispatch ; call fastseek ;AN000;
515 POP AX ; restore regs ;AN000;
516 POP SI ;AN000;
517fs_no11: ;AN000;
518 return ; return ;AN000;
519EndProc FastSeek_Open ;AN000;
520
521; Inputs:
522; none
523; Function:
524; Call Fastseek
525; Outputs:
526; Output of Fastseek
527;
528
529 procedure FSeek_dispatch,NEAR
530ASSUME DS:NOTHING,ES:NOTHING ;AN000;
531 ;AN000;
532 MOV AH,FastSeek_ID ; fastseek ID = 1 ;AN000;
533 entry Fast_Dispatch ; future fastxxxx entry ;AN000;
534 PUSH AX ; save ax ;AN000;
535 MOV AL,AH ; al=fastseek ID ;AN000;
536 XOR AH,AH ; ;AN000;
537 DEC AX ; ;AN000;
538 SHL AX,1 ; times 4 to get entry offset ;AN000;
539 SHL AX,1 ;AN000;
540 ;AN000;
541 MOV SI,OFFSET DOSGROUP:FastTable + 2 ; index to the ;AN000;
542 ADD SI,AX ; fastxxxx entry ;AN000;
543 POP AX ; restore ax ;AN000;
544 CALL DWORD PTR CS:[SI] ; call fastseek ;AN000;
545 return
546EndProc FSeek_dispatch
547
548Break <FastSeek_Close - close a file extent entry>
549
550; Inputs:
551; DL drive number (0=A,1=B,,,)
552; CX first cluster #
553; Function:
554; Close a file extent entry
555; Outputs:
556; None
557;
558;
559
560 procedure FastSeek_Close,NEAR
561ASSUME DS:NOTHING,ES:NOTHING ;AN000;
562
563 TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000;
564 JZ fs_no2 ; no ;AN000;
565 PUSH SI ; save regs ;AN000;
566 PUSH AX ; ;AN000;
567 MOV AL,FSEC_close ; al = 12 ;AN000;
568 JMP fseek_disp ; call fastseek ;AN000;
569EndProc FastSeek_Close ;AN000;
570
571Break <FastSeek_Delete - delete a file extent entry>
572
573; Inputs:
574; DL drive number (0=A,1=B,,,)
575; CX first cluster #
576; Function:
577; Delete a file extent entry
578; Outputs:
579; None
580;
581;
582
583 procedure FastSeek_Delete,NEAR
584ASSUME DS:NOTHING,ES:NOTHING ;AN000;
585 ;AN000;
586 TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000;
587 JZ fs_no2 ; no ;AN000;
588 PUSH SI ; save regs ;AN000;
589 PUSH AX ;AN000;
590 MOV AL,FSEC_delete ; al=13 ;AN000;
591 JMP fseek_disp ; call fastseek ;AN000;
592EndProc FastSeek_Delete ;AN000;
593 ;AN000;
594; Inputs:
595; FastSeekflg= 0 , not installed
596; 1 , installed
597; BX= first cluster number
598; ES:BP = addr of DPB
599; Function:
600; Delete a file extent entry
601; Outputs:
602; None
603;
604
605 procedure Delete_FSeek,NEAR ;AN000;
606ASSUME DS:NOTHING,ES:NOTHING ;AN000;
607 TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000;
608 JZ fs_no2 ; no ;AN000;
609 PUSH CX ; save regs ;AN000;
610 PUSH DX ;AN000;
611 MOV CX,BX ; first cluster # ;AN000;
612 MOV DL,ES:[BP.dpb_drive] ; drive # ;AN000;
613 CALL FastSeek_Delete ; call fastseek to delete an entry ;AN000;
614 POP DX ; restore regs ;AN000;
615 POP CX ;AN000;
616fs_no2: ;AN000;
617 return ; exit ;AN000;
618EndProc Delete_FSeek ;AN000;
619
620Break <FastSeek_Lookup - look up a cluster number>
621
622; Inputs:
623; FSeek_drive : drive number (0=A,1=B,,,)
624; FSeek_firclus: first cluster #
625; FSeek_logclus: logical cluster #
626; Function:
627; Look up a physical cluster #
628; Outputs:
629; carry clear, DI = physical cluster #, FSeek_logsave=DI-1
630; carry set,
631; partially found, DI=last physical cluster #
632; FSeek_logsave=last logical cluster #
633
634 procedure FastSeek_Lookup,NEAR ;AN000;
635ASSUME DS:NOTHING,ES:NOTHING ;AN000;
636
637 PUSH AX ; save ax ;AN000;
638 MOV AL,FSEC_lookup ; al = 14 ;AN000;
639 PUSH BX ; save bx ;AN000;
640 CALL FS_doit ; call fastseek ;AN000;
641 MOV [FSeek_logsave],BX ; save returned BX ;AN000;
642 POP BX ; restore bx ;AN000;
643 POP AX ; restore ax ;AN000;
644 return ;AN000;
645EndProc FastSeek_Lookup ;AN000;
646 ;AN000;
647
648Break <FastSeek_Insert - insert a cluster number>
649
650; Inputs:
651; FSeek_drive : drive number (0=A,1=B,,,)
652; FSeek_firclus: first cluster #
653; FSeek_logclus: logical cluster #
654; DI: physical cluster # to be inserted
655; Function:
656; insert a physical cluster #
657; Outputs:
658; none
659;
660
661 procedure FastSeek_Insert,NEAR
662ASSUME DS:NOTHING,ES:NOTHING
663
664 TEST [FastSeekflg],FS_insert ; insert mode set ? ;AN000;
665 JZ no_insert ; no ;AN000;
666 ;AN000;
667 PUSH AX ; save regs ;AN000;
668 PUSH BX ;AN000;
669 MOV AL,FSEC_insert ; al = 15 ;AN000;
670FSentry: ;AN000;
671 CALL FS_doit ; call fastseek ;AN000;
672 POP BX ; restore regs ;AN000;
673 POP AX ;AN000;
674no_insert:
675 return
676EndProc FastSeek_insert
677
678Break <FastSeek_Truncate - truncate cluster numbers>
679
680; Inputs:
681; FSeek_drive : drive number (0=A,1=B,,,)
682; FSeek_firclus: first cluster #
683; FSeek_logclus: logical cluster #
684; Function:
685; truncate physical cluster #s starting from FSeek_logclus
686; Outputs:
687; none
688;
689
690 procedure FastSeek_Truncate,NEAR
691ASSUME DS:NOTHING,ES:NOTHING
692 ;AN000;
693 TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000;
694 JZ fs_no ; no ;AN000;
695 PUSH AX ; save regs ;AN000;
696 PUSH BX ;AN000;
697 MOV AL,FSEC_truncate ; al = 16 ;AN000;
698 JMP FSentry ; call fastseek ;AN000;
699fs_no: ;AN000;
700 return ;AN000;
701EndProc FastSeek_Truncate ;AN000;
702
703; Inputs:
704; FSeek_drive : drive number (0=A,1=B,,,)
705; FSeek_firclus: first cluster #
706; FSeek_logclus: logical cluster #
707; Function:
708; set up parameters and call fastseek
709; Outputs:
710; outputs of fastseek
711;
712 procedure FS_doit,NEAR
713ASSUME DS:NOTHING,ES:NOTHING
714 ;AN000;
715 PUSH CX ; save regs ;AN000;
716 PUSH DX ;AN000;
717 PUSH SI ;AN000;
718 MOV DL,[FSeek_drive] ; set drive # ;AN000;
719 MOV CX,[FSeek_firclus] ; set 1st cluster # ;AN000;
720 MOV BX,[FSeek_logclus] ; set logical cluster # ;AN000;
721 ;AN000;
722 CALL FSeek_dispatch ; call fastseek ;AN000;
723 ;AN000;
724 ; carry clear if found in DI ;AN000;
725 POP SI ; otherwise, carry set ;AN000;
726 ;AN000;
727 POP DX ; restore regs ;AN000;
728 POP CX ;AN000;
729 return ;AN000;
730EndProc FS_doit ;AN000;
731
732
733; Inputs:
734; same as DOS_SEARCH_FIRST
735; Function:
736; do a IFS search first
737; Outputs:
738; same as DOS_SEARCH_FIRST
739;
740 procedure IFS_SEARCH_FIRST,NEAR ;AN000;
741 DOSAssume CS,<DS>,"IFS_SEARCH_FIRST" ;AN000;
742 ASSUME ES:NOTHING ;AN000;
743
744; MOV WORD PTR [DMAADD+2],DS ;IFS. replace with scratch area ;AN000;;AN000;
745; MOV WORD PTR [DMAADD],OFFSET DOSGROUP:RENAMEDMA ;IFS. ;AN000;
746; invoke SET_THISDPB ;IFS. THISDPB set ;AN000;
747; invoke DOS_SEARCH_FIRST ;IFS. search first ;AN000;
748; return ;AN000;
749EndProc IFS_SEARCH_FIRST ;AN000;
750
751
752; Inputs:
753; THISDPB set
754; WFP_Start points to name
755; Function:
756; do a IFS REN_DEL_CHECK
757; Outputs:
758; same as REN_DEL_CHECK
759;
760 procedure IFS_REN_DEL_CHECK,NEAR ;AN000;
761 DOSAssume CS,<DS>,"IFS_REN_DEL_CHECK" ;AN000;
762 ASSUME ES:NOTHING ;AN000;
763
764; MOV AX,WORD PTR [DMAADD+2] ;IFS. set up ;AN000;;AN000;
765; MOV WORD PTR [CURBUF+2],AX ;IFS. curbuf+2 : bx -> dir entry ;AN000;
766; MOV BX,WORD PTR [DMAADD] ;IFS. ;AN000;
767; ADD BX,21 ;IFS. ;AN000;
768; MOV SI,BX ;IFS. curbuf+2:si -> dir_first ;AN000;
769; ADD SI,dir_first ;IFS. ;AN000;
770; EnterCrit critDisk ;IFS. enter critical section ;AN000;
771; CALL REN_DEL_Check ;IFS. share check ;AN000;
772; LeaveCrit critDisk ;IFS. leave critical section ;AN000;
773; return ;AN000;
774EndProc IFS_REN_DEL_CHECK ;AN000;
775
776CODE ENDS
777 END
diff --git a/v4.0/src/DOS/DEV.ASM b/v4.0/src/DOS/DEV.ASM
new file mode 100644
index 0000000..20c3f74
--- /dev/null
+++ b/v4.0/src/DOS/DEV.ASM
@@ -0,0 +1,841 @@
1; SCCSID = @(#)dev.asm 1.2 85/07/23
2; SCCSID = @(#)dev.asm 1.2 85/07/23
3TITLE DEV - Device call routines
4NAME Dev
5; Misc Routines to do 1-12 low level I/O and call devices
6;
7; IOFUNC
8; DEVIOCALL
9; SETREAD
10; SETWRITE
11; DEVIOCALL2
12; DEV_OPEN_SFT
13; DEV_CLOSE_SFT
14; RW_SC
15; IN_SC
16; INVALIDATE_SC
17; VIRREAD
18; SC2BUF
19;
20; Revision history:
21;
22; A000 version 4.00 Jan. 1988
23; A010 disable change line for SHARE /NC
24
25;
26; get the appropriate segment definitions
27;
28.xlist
29include dosseg.asm
30
31CODE SEGMENT BYTE PUBLIC 'CODE'
32 ASSUME SS:DOSGROUP,CS:DOSGROUP
33
34.xcref
35INCLUDE DOSSYM.INC
36INCLUDE DEVSYM.INC
37include version.inc
38.cref
39.list
40
41 i_need IOXAD,DWORD
42 i_need IOSCNT,WORD
43 i_need DEVIOBUF,4
44 i_need IOCALL,BYTE
45 i_need IOMED,BYTE
46 i_need IORCHR,BYTE
47 i_need CALLSCNT,WORD
48 i_need DMAAdd,DWORD
49 i_need CallDevAd,DWORD
50 i_need CallXAD,DWORD
51 i_need DPBHead,DWORD
52 i_need ThisSFT,DWORD
53 i_need ThisDPB,DWORD
54 i_need DevCall,DWORD
55 i_need VerFlg,BYTE
56 i_need HIGH_SECTOR,WORD ;AN000;
57 i_need CALLSSEC,WORD ;AN000;
58 i_need CALLNEWSC,DWORD ;AN000;
59 i_need SC_CACHE_COUNT,WORD ;AN000;
60 i_need SC_CACHE_PTR,DWORD ;AN000;
61 i_need CURSC_SECTOR,WORD ;AN000;
62 i_need SEQ_SECTOR,DWORD ;AN000;
63 i_need SC_SECTOR_SIZE,WORD ;AN000;
64 i_need CURSC_DRIVE,BYTE ;AN000;
65 i_need SC_DRIVE,BYTE ;AN000;
66 i_need SC_STATUS,WORD ;AN000;
67 i_need SC_FLAG,BYTE ;AN000;
68 i_need TEMP_VAR,WORD ;AN000;
69 i_need TEMP_VAR2,WORD ;AN000;
70 i_need InterChar,BYTE ;AN000; interim character flag 2/13/KK
71 i_need InterCon,BYTE ;AN000; Console mode flag(1:interim mode) 2/13/KK
72 i_need SaveCurFlg,BYTE ;AN000; Console out mode(1:print & don't adv cursor) 2 /13/KK
73 i_need DDMOVE,BYTE ;AN000; flag for DWORD move
74 i_need DOS34_FLAG,WORD ;AN000;
75 i_need fshare,BYTE ;AN010; share flag
76
77Break <IOFUNC -- DO FUNCTION 1-12 I/O>
78
79; Inputs:
80; DS:SI Points to SFT
81; AH is function code
82; = 0 Input
83; = 1 Input Status
84; = 2 Output
85; = 3 Output Status
86; = 4 Flush
87; = 5 Input Status - System WAIT invoked for K09 if no char
88; present.
89; AL = character if output
90; Function:
91; Perform indicated I/O to device or file
92; Outputs:
93; AL is character if input
94; If a status call
95; zero set if not ready
96; zero reset if ready (character in AL for input status)
97; For regular files:
98; Input Status
99; Gets character but restores position
100; Zero set on EOF
101; Input
102; Gets character advances position
103; Returns ^Z on EOF
104; Output Status
105; Always ready
106; AX altered, all other registers preserved
107
108 procedure IOFUNC,NEAR
109ASSUME DS:NOTHING,ES:NOTHING
110
111 Assert ISSFT,<DS,SI>,"IOFUNC"
112 MOV WORD PTR [IOXAD+2],SS
113 MOV WORD PTR [IOXAD],OFFSET DOSGROUP:DEVIOBUF
114 MOV WORD PTR [IOSCNT],1
115 MOV WORD PTR [DEVIOBUF],AX
116 TEST [SI.sf_flags],sf_isnet
117 JZ IOTO22 ;AN000;
118 JMP IOTOFILE ;AN000;
119IOTO22:
120 TEST [SI.sf_flags],devid_device
121 JNZ IOTo33 ;AN000;
122 JMP IOTOFILE ;AN000;
123IOTO33:
124 invoke save_world
125 MOV DX,DS
126 MOV BX,SS
127 MOV DS,BX
128 MOV ES,BX
129 ASSUME DS:DOSGroup
130 XOR BX,BX
131 cmp ah,5 ; system wait enabled?
132 jnz no_sys_wait
133 or bx,0400H ; Set bit 10 in status word for driver
134 ; It is up to device driver to carry out
135 ; appropriate action.
136no_sys_wait:
137 MOV [IOCALL.REQSTAT],BX
138 XOR BX,BX
139 MOV BYTE PTR [IOMED],BL
140
141Table Segment
142Public DEV001S, DEV001E ; Pathgen labels
143DEV001s:
144; length of packets
145LenTab DB DRDWRHL, DRDNDHL, DRDWRHL, DSTATHL, DFLSHL, DRDNDHL
146
147; Error Function
148
149CmdTab DB 86h, DEVRD ; 0 input
150 DB 86h, DEVRDND ; 1 input status
151 DB 87h, DEVWRT ; 2 output
152 DB 87h, DEVOST ; 3 output status
153 DB 86h, DEVIFL ; 4 input flush
154 DB 86H, DEVRDND ; 5 input status with system WAIT
155DEV001E:
156Table ENDS
157
158 MOV BL,AH ; get function
159 MOV AH,LenTab[BX]
160 SHL BX,1
161 MOV CX,WORD PTR CmdTab[BX]
162
163 MOV BX,OFFSET DOSGROUP:IOCALL
164
165 MOV [IOCALL.REQLEN],AH
166 MOV [IOCALL.REQFUNC],CH
167 IF DBCS ;AN000;
168;----------------------------- Start of DBCS 2/13/KK
169 PUSH CX ;AN000;
170 MOV CL, [InterCon] ;AN000;
171 CMP CH, DEVRD ;AN000; 0 input
172 JZ SETIN ;AN000;
173 CMP CH, DEVRDND ;AN000; 1(5) input status without(with) system WAIT
174 JZ SETIN ;AN000;
175 MOV CL, [SaveCurflg] ;AN000;
176 CMP CH, DEVWRT ;AN000; 2 output
177 JZ CHKERROUT ;AN000;
178 XOR CL,CL ;AN000; else, do normal
179SETIN: ;AN000;
180 MOV BYTE PTR [IoMed], CL ;AN000; set interim I/O indication
181 POP CX ;AN000;
182;----------------------------- End of DBCS 2/13/KK
183 ENDIF ;AN000;
184 MOV DS,DX
185ASSUME DS:NOTHING
186 CALL DEVIOCALL
187 MOV DI,[IOCALL.REQSTAT]
188 TEST DI,STERR
189 JNZ DevErr
190OkDevIO:
191 MOV AX,SS
192 MOV DS,AX
193 ASSUME DS:DOSGroup
194 IF DBCS ;AN000;
195 MOV [InterChar],0 ;AN000; reset interim character flag 2/13/KK
196 TEST DI,Ddkey ;AN000; is this a dead key (interim char)? 2/13/KK
197 JZ NotInterim ;AN000; no, flag already reset... 2/13/KK
198 INC [InterChar] ;AN000; yes, set flag for future 2/13/KK
199NotInterim: ;AN000; 2/13/KK
200 ENDIF ;AN000;
201 CMP CH,DEVRDND
202 JNZ DNODRD
203 MOV AL,BYTE PTR [IORCHR]
204 MOV [DEVIOBUF],AL
205
206DNODRD: MOV AH,BYTE PTR [IOCALL.REQSTAT+1]
207 NOT AH ; Zero = busy, not zero = ready
208 AND AH,STBUI SHR 8
209
210QuickReturn: ;AN000; 2/13/KK
211 invoke restore_world
212ASSUME DS:NOTHING
213 MOV AX,WORD PTR [DEVIOBUF]
214 return
215
216;IOTOFILEJ:
217; JMP SHORT IOTOFILE
218 IF DBCS ;AN000;
219;------------------------------ Start of DBCS 2/13/KK
220CHKERROUT: ;AN000;
221 MOV DS, DX ;AN000;
222 TEST [SI.sf_flags], devid_device_con_out ;AN000; output to console ?
223 JNZ GOOD ;AN000; yes
224 CMP CL, 01 ;AN000; write interim ?
225 JNZ GOOD ;AN000; no,
226 POP CX ;AN000;
227 JMP SHORT QuickReturn ;AN000; avoid writting interims to other than
228 ;AN000; console device
229GOOD: ;AN000;
230 PUSH SS ;AN000;
231 POP DS ;AN000;
232 JMP SETIN ;AN000;
233;------------------------------ End of DBCS 2/13/KK
234 ENDIF ;AN000;
235DevErr:
236 TEST CS:[DOS34_FLAG],X25_Special ;AN000; from disk.asm
237 JZ notx25 ;AN000; no
238 PUSH AX ;AN000; unknown command ?
239 MOV AX,DI ;AN000;
240 AND AX,error_I24_bad_command ;AN000;
241 CMP AL,error_I24_bad_command ;AN000;
242 POP AX ;AN000;
243 JNZ notx25 ;AN000; no, then error
244 JMP okDevIO ;AN000;
245notx25:
246 MOV AH,CL
247 invoke CHARHARD
248 CMP AL,1
249 JNZ NO_RETRY
250 invoke restore_world
251 JMP IOFUNC
252
253NO_RETRY:
254; Know user must have wanted Ignore OR Fail. Make sure device shows ready
255; so that DOS doesn't get caught in a status loop when user simply wants
256; to ignore the error.
257 AND BYTE PTR [IOCALL.REQSTAT+1], NOT (STBUI SHR 8)
258 JMP OKDevIO
259
260IOTOFILE:
261ASSUME DS:NOTHING
262 OR AH,AH
263 JZ IOIN
264 DEC AH
265 JZ IOIST
266 DEC AH
267 JZ IOUT
268 return ; NON ZERO FLAG FOR OUTPUT STATUS
269
270IOIST:
271 PUSH WORD PTR [SI.sf_position] ; Save position
272 PUSH WORD PTR [SI.sf_position+2]
273 CALL IOIN
274 POP WORD PTR [SI.sf_position+2] ; Restore position
275 POP WORD PTR [SI.sf_position]
276 return
277
278IOUT:
279 CALL SETXADDR
280 invoke DOS_WRITE
281 CALL RESTXADDR ; If you change this into a jmp don't
282 return ; come crying to me when things don't
283 ; work ARR
284
285IOIN:
286 CALL SETXADDR
287 OR [DOS34_FLAG],Disable_EOF_I24 ;AN000;
288 invoke DOS_READ
289 AND [DOS34_FLAG],NO_Disable_EOF_I24 ;AN000;
290 OR CX,CX ; Check EOF
291 CALL RESTXADDR
292 MOV AL,[DEVIOBUF] ; Get byte from trans addr
293 retnz
294 MOV AL,1AH ; ^Z if no bytes
295 return
296
297SETXADDR:
298 POP WORD PTR [CALLSCNT] ; Return address
299 invoke save_world
300 PUSH WORD PTR [DMAADD] ; Save Disk trans addr
301 PUSH WORD PTR [DMAADD+2]
302 MOV WORD PTR [THISSFT+2],DS
303 Context DS
304 MOV WORD PTR [THISSFT],SI ; Finish setting SFT pointer
305 MOV CX,WORD PTR [IOXAD+2]
306 MOV WORD PTR [DMAADD+2],CX
307 MOV CX,WORD PTR [IOXAD]
308 MOV WORD PTR [DMAADD],CX ; Set byte trans addr
309 MOV CX,[IOSCNT] ; ioscnt specifies length of buffer
310 JMP SHORT RESTRET ; RETURN ADDRESS
311
312RESTXADDR:
313 DOSAssume CS,<DS>,"RestXAddr"
314 POP WORD PTR [CALLSCNT] ; Return address
315 POP WORD PTR [DMAADD+2] ; Restore Disk trans addr
316 POP WORD PTR [DMAADD]
317 invoke restore_world
318ASSUME DS:NOTHING
319RESTRET:JMP WORD PTR [CALLSCNT] ; Return address
320EndProc IOFUNC
321
322Break <DEV_OPEN_SFT, DEV_CLOSE_SFT - OPEN or CLOSE A DEVICE>
323
324; Inputs:
325; ES:DI Points to SFT
326; Function:
327; Issue an OPEN call to the correct device
328; Outputs:
329; None
330; ALL preserved
331
332 procedure DEV_OPEN_SFT,NEAR
333ASSUME DS:NOTHING,ES:NOTHING
334
335 Assert ISSFT,<ES,DI>,"Dev_Open_SFT"
336 invoke Save_World
337 MOV AL,DEVOPN
338 JMP SHORT DO_OPCLS
339
340EndProc DEV_OPEN_SFT
341
342; Inputs:
343; ES:DI Points to SFT
344; Function:
345; Issue a CLOSE call to the correct device
346; Outputs:
347; None
348; ALL preserved
349
350 procedure DEV_CLOSE_SFT,NEAR
351ASSUME DS:NOTHING,ES:NOTHING
352
353 Assert ISSFT,<ES,DI>,"Dev_Close_SFT"
354 invoke Save_World
355 MOV AL,DEVCLS
356
357;
358; Main entry for device open and close. AL contains the function requested.
359; Subtlety: if Sharing is NOT loaded then we do NOT issue open/close to block
360; devices. This allows networks to function but does NOT hang up with bogus
361; change-line code.
362;
363 entry DO_OPCLS
364;
365; Is the SFT for the net? If so, no action necessary.
366;
367 invoke Test_IFS_Remote ;AC000;
368 JNZ OPCLS_DONE ; NOP on net SFTs
369 XOR AH,AH ; Unit
370 TEST ES:[DI.sf_flags],devid_device
371 LES DI,ES:[DI.sf_devptr] ; Get DPB or device
372 JNZ Got_Dev_Addr
373;
374; We are about to call device open/close on a block driver. If no sharing
375; then just short circuit to done.
376;
377;;;;; invoke CheckShare
378 CMP fshare,1 ;AN010; /NC or no SHARE
379 JBE opCLs_Done ;AN010; yes
380 MOV AH,ES:[DI.dpb_UNIT]
381 MOV CL,ES:[DI.dpb_drive]
382 LES DI,ES:[DI.dpb_driver_addr] ; Get device
383GOT_DEV_ADDR: ; ES:DI -> device
384 TEST ES:[DI.SDEVATT],DEVOPCL
385 JZ OPCLS_DONE ; Device can't
386 PUSH ES
387 POP DS
388 MOV SI,DI ; DS:SI -> device
389OPCLS_RETRY:
390 Context ES
391 MOV DI,OFFSET DOSGROUP:DEVCALL
392 MOV BX,DI
393 PUSH AX
394 MOV AL,DOPCLHL
395 STOSB ; Length
396 POP AX
397 XCHG AH,AL
398 STOSB ; Unit
399 XCHG AH,AL
400 STOSB ; Command
401 MOV WORD PTR ES:[DI],0 ; Status
402 PUSH AX ; Save Unit,Command
403 invoke DEVIOCALL2
404 MOV DI,ES:[BX.REQSTAT]
405 TEST DI,STERR
406 JZ OPCLS_DONEP ; No error
407 TEST [SI.SDEVATT],DEVTYP
408 JZ BLKDEV
409 MOV AH,86H ; Read error in data, Char dev
410 JMP SHORT HRDERR
411
412BLKDEV:
413 MOV AL,CL ; Drive # in AL
414 MOV AH,6 ; Read error in data, Blk dev
415HRDERR:
416 invoke CHARHARD
417 CMP AL,1
418 JNZ OPCLS_DONEP ; IGNORE or FAIL
419 ; Note that FAIL is essentually IGNORED
420 POP AX ; Get back Unit, Command
421 JMP OPCLS_RETRY
422
423OPCLS_DONEP:
424 POP AX ; Clean stack
425OPCLS_DONE:
426 invoke Restore_World
427 return
428
429EndProc DEV_CLOSE_SFT
430
431Break <DEVIOCALL, DEVIOCALL2 - CALL A DEVICE>
432
433; Inputs:
434; DS:SI Points to device SFT
435; ES:BX Points to request data
436; Function:
437; Call the device
438; Outputs:
439; DS:SI -> Device driver
440; DS:SI,AX destroyed, others preserved
441
442 procedure DEVIOCALL,NEAR
443ASSUME DS:NOTHING,ES:NOTHING
444
445 Assert ISSFT,<DS,SI>,"DevIOCall"
446 LDS SI,[SI.sf_devptr]
447
448 entry DEVIOCALL2
449
450 EnterCrit critDevice
451
452 TEST [SI.SDEVATT],DevTyp ;AN000; >32mb block device ?
453 JNZ chardev2 ;AN000; >32mb no
454 CMP ES:[BX.REQFUNC],DEVRD ;AN000; >32mb read ?
455 JZ chkext ;AN000; >32mb yes
456 CMP ES:[BX.REQFUNC],DEVWRT ;AN000; >32mb write ?
457 JZ chkext ;AN000; >32mb yes
458 CMP ES:[BX.REQFUNC],DEVWRTV;AN000; >32mb write/verify ?
459 JNZ chardev2 ;AN000; >32mb no
460chkext:
461 CALL RW_SC ;AN000;LB. use secondary cache if there
462 JC dev_exit ;AN000;LB. done
463
464 TEST [SI.SDEVATT],EXTDRVR ;AN000;>32mb extended driver?
465 JZ chksector ;AN000;>32mb no
466 ADD BYTE PTR ES:[BX],8 ;AN000;>32mb make length to 30
467 MOV AX,[CALLSSEC] ;AN000;>32mb
468 MOV [CALLSSEC],-1 ;AN000;>32mb old sector =-1
469 MOV WORD PTR [CALLNEWSC],AX ;AN000;>32mb new sector =
470 MOV AX,[HIGH_SECTOR] ;AN000; >32mb low sector,high sector
471 MOV WORD PTR [CALLNEWSC+2],AX ;AN000; >32mb
472 JMP chardev2 ;AN000; >32mb
473chksector: ;AN000; >32mb
474 CMP [HIGH_SECTOR],0 ;AN000; >32mb if >32mb
475 JZ chardev2 ;AN000; >32mb then fake error
476 MOV ES:[BX.REQSTAT],STERR+STDON+ERROR_I24_NOT_DOS_DISK ;AN000; >32mb
477 JMP SHORT dev_exit ;AN000; >32mb
478
479chardev2: ;AN000;
480; As above only DS:SI points to device header on entry, and DS:SI is preserved
481 MOV AX,[SI.SDEVSTRAT]
482 MOV WORD PTR [CALLDEVAD],AX
483 MOV WORD PTR [CALLDEVAD+2],DS
484 CALL DWORD PTR [CALLDEVAD]
485 MOV AX,[SI.SDEVINT]
486 MOV WORD PTR [CALLDEVAD],AX
487 CALL DWORD PTR [CALLDEVAD]
488 CALL VIRREAD ;AN000;LB. move data from SC to buffer
489 JC chardev2 ;AN000;LB. bad sector or exceeds max sec
490dev_exit:
491 LeaveCrit critDevice
492 return
493EndProc DEVIOCALL
494
495Break <SETREAD, SETWRITE -- SET UP HEADER BLOCK>
496
497; Inputs:
498; DS:BX = Transfer Address
499; CX = Record Count
500; DX = Starting Record
501; AH = Media Byte
502; AL = Unit Code
503; Function:
504; Set up the device call header at DEVCALL
505; Output:
506; ES:BX Points to DEVCALL
507; No other registers effected
508
509 procedure SETREAD,NEAR
510ASSUME DS:NOTHING,ES:NOTHING
511
512 PUSH DI
513 PUSH CX
514 PUSH AX
515 MOV CL,DEVRD
516SETCALLHEAD:
517 MOV AL,DRDWRHL
518 PUSH SS
519 POP ES
520 MOV DI,OFFSET DOSGROUP:DEVCALL
521 STOSB ; length
522 POP AX
523 STOSB ; Unit
524 PUSH AX
525 MOV AL,CL
526 STOSB ; Command code
527 XOR AX,AX
528 STOSW ; Status
529 ADD DI,8 ; Skip link fields
530 POP AX
531 XCHG AH,AL
532 STOSB ; Media byte
533 XCHG AL,AH
534 PUSH AX
535 MOV AX,BX
536 STOSW
537 MOV AX,DS
538 STOSW ; Transfer addr
539 POP CX ; Real AX
540 POP AX ; Real CX
541 STOSW ; Count
542 XCHG AX,DX ; AX=Real DX, DX=real CX, CX=real AX
543 STOSW ; Start
544 XCHG AX,CX
545 XCHG DX,CX
546 POP DI
547 MOV BX,OFFSET DOSGROUP:DEVCALL
548 return
549
550 entry SETWRITE
551ASSUME DS:NOTHING,ES:NOTHING
552
553; Inputs:
554; DS:BX = Transfer Address
555; CX = Record Count
556; DX = Starting Record
557; AH = Media Byte
558; AL = Unit Code
559; Function:
560; Set up the device call header at DEVCALL
561; Output:
562; ES:BX Points to DEVCALL
563; No other registers effected
564
565 PUSH DI
566 PUSH CX
567 PUSH AX
568 MOV CL,DEVWRT
569 ADD CL,[VERFLG]
570 JMP SHORT SETCALLHEAD
571EndProc SETREAD
572
573
574Break <RW_SC -- Read Write Secondary Cache>
575
576; Inputs:
577; [SC_CACHE_COUNT]= secondary cache count
578; [SC_STATUS]= SC validity status
579; [SEQ_SECTOR]= last sector read
580; Function:
581; Read from or write through secondary cache
582; Output:
583; ES:BX Points to DEVCALL
584; carry clear, I/O is not done
585; [SC_FLAG]=1 if continuos sectors will be read
586; carry set, I/O is done
587
588
589 procedure RW_SC,NEAR ;AN000;
590ASSUME DS:NOTHING,ES:NOTHING ;AN000;
591
592 CMP [SC_CACHE_COUNT],0 ;AN000;LB. secondary cache exists?
593 JZ scexit4 ;AN000;LB. no, do nothing
594 CMP [CALLSCNT],1 ;AN000;LB. sector count = 1 (buffer I/O)
595 JNZ scexit4 ;AN000;LB. no, do nothing
596 PUSH CX ;AN000;;LB.
597 PUSH DX ;AN000;;LB. yes
598 PUSH DS ;AN000;;LB. save registers
599 PUSH SI ;AN000;;LB.
600 PUSH ES ;AN000;;LB.
601 PUSH DI ;AN000;;LB.
602 MOV DX,WORD PTR [CALLSSEC] ;AN000;;LB. starting sector
603 CMP BYTE PTR [DEVCALL.REQFUNC],DEVRD ;AN000;LB. read ? ;AN000;
604 JZ doread ;AN000;LB. yes ;AN000;
605 CALL INVALIDATE_SC ;AN000;LB. invalidate SC ;AN000;
606 JMP scexit2 ;AN000;LB. back to normal ;AN000;
607scexit4: ;AN000; ;AN000;
608 CLC ;AN000;LB. I/O not done yet ;AN000;
609 return ;AN000;LB. ;AN000;
610doread: ;AN000; ;AN000;
611 CALL SC2BUF ;AN000;LB. check if in SC ;AN000;
612 JC readSC ;AN000;LB. ;AN000;
613 MOV [DEVCALL.REQSTAT],STDON ;AN000;LB. fake done and ok ;AN000;
614 STC ;AN000;LB. set carry ;AN000;
615 JMP saveseq ;AN000;LB. save seq. sector # ;AN000;
616readSC: ;AN000;
617 MOV AX,WORD PTR [HIGH_SECTOR] ;AN000;;LB. subtract sector num from
618 MOV CX,WORD PTR [CALLSSEC] ;AN000;;LB. saved sequential sector
619 SUB CX,WORD PTR [SEQ_SECTOR] ;AN000;;LB. number
620 SBB AX,WORD PTR [SEQ_SECTOR+2] ;AN000;;LB.
621 CMP AX,0 ;AN000;;LB. greater than 64K
622 JNZ saveseq2 ;AN000;;LB. yes,save seq. sector #
623chklow: ;AN000;
624 CMP CX,1 ;AN000;;LB. <= 1
625 JA saveseq2 ;AN000;;LB. no, not sequential
626 MOV [SC_STATUS],-1 ;AN000;;LB. prsume all SC valid
627 MOV AX,[SC_CACHE_COUNT] ;AN000;;LB. yes, sequential
628 MOV [CALLSCNT],AX ;AN000;;LB. read continuous sectors
629readsr:
630 MOV AX,WORD PTR [CALLXAD+2] ;AN000;;LB. save buffer addr
631 MOV [TEMP_VAR2],AX ;AN000;;LB. in temp vars
632 MOV AX,WORD PTR [CALLXAD] ;AN000;;LB.
633 MOV [TEMP_VAR],AX ;AN000;;LB.
634 ;AN000;
635 MOV AX,WORD PTR [SC_CACHE_PTR] ;AN000;LB. use SC cache addr as ;AN000;
636 MOV WORD PTR [CALLXAD],AX ;AN000;LB. transfer addr ;AN000;
637 MOV AX,WORD PTR [SC_CACHE_PTR+2] ;AN000;LB. ;AN000;
638 MOV WORD PTR [CALLXAD+2],AX ;AN000;LB. ;AN000;
639 MOV [SC_FLAG],1 ;AN000;LB. flag it for later ;AN000;
640 MOV AL,[SC_DRIVE] ;AN000;;LB. current drive
641 MOV [CURSC_DRIVE],AL ;AN000;;LB. set current drive
642 MOV AX,WORD PTR [CALLSSEC] ;AN000;;LB. current sector
643 MOV [CURSC_SECTOR],AX ;AN000;;LB. set current sector
644 MOV AX,WORD PTR [CALLSSEC+2] ;AN000;;LB.
645 MOV [CURSC_SECTOR+2],AX ;AN000;;LB.
646saveseq2: ;AN000;
647 CLC ;AN000;LB. clear carry ;AN000;
648saveseq: ;AN000; ;AN000;
649 MOV AX,[HIGH_SECTOR] ;AN000;LB. save current sector # ;AN000;
650 MOV WORD PTR [SEQ_SECTOR+2],AX ;AN000;LB. for access mode ref. ;AN000;
651 MOV AX,[CALLSSEC] ;AN000;LB. ;AN000;
652 MOV WORD PTR [SEQ_SECTOR],AX ;AN000;LB. ;AN000;
653 JMP scexit ;AN000;LB. ;AN000;
654 ;AN000;
655scexit2: ;AN000;LB. ;AN000;
656 CLC ;AN000;LB. clear carry ;AN000;
657scexit: ;AN000; ;AN000;
658 POP DI ;AN000;;LB.
659 POP ES ;AN000;;LB. restore registers
660 POP SI ;AN000;;LB.
661 POP DS ;AN000;;LB.
662 POP DX ;AN000;;LB.
663 POP CX ;AN000;;LB.
664 return ;AN000;;LB.
665 ;AN000;
666EndProc RW_SC ;AN000;
667
668Break <IN_SC -- check if in secondary cache>
669
670; Inputs: [SC_DRIVE]= requesting drive
671; [CURSC_DRIVE]= current SC drive
672; [CURSC_SECTOR] = starting scetor # of SC
673; [SC_CACHE_COUNT] = SC count
674; [HIGH_SECTOR]:DX= sector number
675; Function:
676; Check if the sector is in secondary cache
677; Output:
678; carry clear, in SC
679; CX= the index in the secondary cache
680; carry set, not in SC
681;
682
683 procedure IN_SC,NEAR ;AN000;
684ASSUME DS:NOTHING,ES:NOTHING ;AN000;
685
686 MOV AL,[SC_DRIVE] ;AN000;;LB. current drive
687 CMP AL,[CURSC_DRIVE] ;AN000;;LB. same as SC drive
688 JNZ outrange2 ;AN000;;LB. no
689 MOV AX,WORD PTR [HIGH_SECTOR] ;AN000;;LB. subtract sector num from
690 MOV CX,DX ;AN000;;LB. secondary starting sector
691 SUB CX,WORD PTR [CURSC_SECTOR] ;AN000;;LB. number
692 SBB AX,WORD PTR [CURSC_SECTOR+2] ;AN000;;LB.
693 CMP AX,0 ;AN000;;LB. greater than 64K
694 JNZ outrange2 ;AN000;;LB. yes
695 CMP CX,[SC_CACHE_COUNT] ;AN000;;LB. greater than SC count
696 JAE outrange2 ;AN000;;LB. yes
697 CLC ;AN000;;LB. clear carry
698 JMP short inexit ;AN000;;LB. in SC
699outrange2: ;AN000;;LB. set carry
700 STC ;AN000;;LB.
701inexit: ;AN000;;LB.
702 return ;AN000;;LB.
703
704EndProc IN_SC ;AN000;
705
706Break <INVALIDATE_SC - invalide secondary cache>
707
708; Inputs: [SC_DRIVE]= requesting drive
709; [CURSC_DRIVE]= current SC drive
710; [CURSC_SECTOR] = starting scetor # of SC
711; [SC_CACHE_COUNT] = SC count
712; [SC_STAUS] = SC status word
713; [HIGH_SECTOR]:DX= sceotor number
714;
715; Function:
716; invalidate secondary cache if in there
717; Output:
718; [SC_STATUS] is updated
719;
720
721 procedure INVALIDATE_SC,NEAR ;AN000;
722ASSUME DS:NOTHING,ES:NOTHING ;AN000;
723
724 CALL IN_SC ;AN000;;LB. in secondary cache
725 JC outrange ;AN000;;LB. no
726 MOV AX,1 ;AN000;;LB. invalidate the sector
727 SHL AX,CL ;AN000;;LB. in the secondary cache
728 NOT AX ;AN000;;LB.
729 AND [SC_STATUS],AX ;AN000;;LB. save the status
730outrange: ;AN000;;LB.
731 return ;AN000;;LB.
732
733EndProc INVALIDATE_SC ;AN000;
734
735
736Break <VIRREAD- virtually read data into buffer>
737
738; Inputs: SC_FLAG = 0 , no sectors were read into SC
739; 1, continous sectors were read into SC
740; Function:
741; Move data from SC to buffer
742; Output:
743; carry clear, data is moved to buffer
744; carry set, bad sector or exceeds maximum sector
745; SC_FLAG =0
746; CALLSCNT=1
747; SC_STATUS= -1 if succeeded
748; 0 if failed
749
750 procedure VIRREAD,NEAR ;AN000;
751ASSUME DS:NOTHING,ES:NOTHING ;AN000;
752
753 CMP [SC_FLAG],0 ;AN000;;LB. from SC fill
754 JZ sc2end ;AN000;;LB. no
755 MOV AX,[TEMP_VAR2] ;AN000;;LB. restore buffer addr
756 MOV WORD PTR [CALLXAD+2],AX ;AN000;;LB.
757 MOV AX,[TEMP_VAR] ;AN000;;LB.
758 MOV WORD PTR [CALLXAD],AX ;AN000;;LB.
759 MOV [SC_FLAG],0 ;AN000;;LB. reset sc_flag
760 MOV [CALLSCNT],1 ;AN000;;LB. one sector transferred
761
762 TEST [DEVCALL.REQSTAT],STERR ;AN000;;LB. error?
763 JNZ scerror ;AN000;;LB. yes
764 PUSH DS ;AN000;;LB.
765 PUSH SI ;AN000;;LB.
766 PUSH ES ;AN000;;LB.
767 PUSH DI ;AN000;;LB.
768 PUSH DX ;AN000;;LB.
769 PUSH CX ;AN000;;LB.
770 XOR CX,CX ;AN000;;LB. we want first sector in SC
771 CALL SC2BUF2 ;AN000;;LB. move data from SC to buffer
772 POP CX ;AN000;;LB.
773 POP DX ;AN000;;LB.
774 POP DI ;AN000;;LB.
775 POP ES ;AN000;;LB.
776 POP SI ;AN000;;LB.
777 POP DS ;AN000;;LB.
778 JMP SHORT sc2end ;AN000;;LB. return
779
780scerror: ;AN000;
781 MOV [CALLSCNT],1 ;AN000;;LB. reset sector count to 1
782 MOV [SC_STATUS],0 ;AN000;;LB. invalidate all SC sectors
783 MOV [CURSC_DRIVE],-1 ;AN000;;LB. invalidate drive
784 STC ;AN000;;LB. carry set
785 return ;AN000;;LB.
786
787sc2end: ;AN000;
788 CLC ;AN000;;LB. carry clear
789 return ;AN000;;LB.
790
791EndProc VIRREAD ;AN000;
792
793Break <SC2BUF- move data from SC to buffer>
794
795; Inputs: [SC_STATUS] = SC validity status
796; [SC_SECTOR_SIZE] = request sector size
797; [SC_CACHE_PTR] = pointer to SC
798; Function:
799; Move data from SC to buffer
800; Output:
801; carry clear, in SC and data is moved
802; carry set, not in SC and data is not moved
803
804 procedure SC2BUF,NEAR ;AN000;
805ASSUME DS:NOTHING,ES:NOTHING ;AN000;
806
807 CALL IN_SC ;AN000;;LB. in secondary cache
808 JC noSC ;AN000;;LB. no
809 MOV AX,1 ;AN000;;LB. check if valid sector
810 SHL AX,CL ;AN000;;LB. in the secondary cache
811 TEST [SC_STATUS],AX ;AN000;;LB.
812 JZ noSC ;AN000;;LB. invalid
813entry SC2BUF2 ;AN000;
814 MOV AX,CX ;AN000;;LB. times index with
815 MUL [SC_SECTOR_SIZE] ;AN000;;LB. sector size
816 ADD AX,WORD PTR [SC_CACHE_PTR] ;AN000;;LB. add SC starting addr
817 ADC DX,WORD PTR [SC_CACHE_PTR+2];AN000;;LB.
818 MOV DS,DX ;AN000; ;LB. DS:SI-> SC sector addr
819 MOV SI,AX ;AN000; ;LB.
820 MOV ES,WORD PTR [CALLXAD+2] ;AN000; ;LB. ES:DI-> buffer addr
821 MOV DI,WORD PTR [CALLXAD] ;AN000; ;LB.
822 MOV CX,[SC_SECTOR_SIZE] ;AN000; ;LB. count= sector size
823 SHR CX,1 ;AN000; ;LB. may use DWORD move for 386
824entry MOVWORDS ;AN000;
825 CMP [DDMOVE],0 ;AN000; ;LB. 386 ?
826 JZ nodd ;AN000; ;LB. no
827 SHR CX,1 ;AN000; ;LB. words/2
828 DB 66H ;AN000; ;LB. use double word move
829nodd:
830 REP MOVSW ;AN000; ;LB. move to buffer
831 CLC ;AN000; ;LB. clear carry
832 return ;AN000; ;LB. exit
833noSC: ;AN000;
834 STC ;AN000; ;LB. set carry
835sexit: ;AN000;
836 return ;AN000; ;LB.
837
838EndProc SC2BUF
839CODE ENDS
840 END
841 \ No newline at end of file
diff --git a/v4.0/src/DOS/DINFO.ASM b/v4.0/src/DOS/DINFO.ASM
new file mode 100644
index 0000000..10738b1
--- /dev/null
+++ b/v4.0/src/DOS/DINFO.ASM
@@ -0,0 +1,131 @@
1; SCCSID = @(#)dinfo.asm 1.1 85/04/10
2; SCCSID = @(#)dinfo.asm 1.1 85/04/10
3TITLE DISK_INFO - Internal Get Disk Info
4NAME DISK_INFO
5; Low level routine for returning disk drive information from a local
6; or NET device
7;
8; DISK_INFO
9;
10; Modification history:
11;
12; Created: ARR 30 March 1983
13;
14
15;
16; get the appropriate segment definitions
17;
18.xlist
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xcref
25INCLUDE DOSSYM.INC
26INCLUDE DEVSYM.INC
27.cref
28.list
29
30Installed = TRUE
31
32 i_need THISCDS,DWORD
33 i_need CURBUF,DWORD
34 i_need EXTERR_LOCUS,BYTE
35if debug
36 I_need BugLev,WORD
37 I_need BugTyp,WORD
38include bugtyp.asm
39endif
40
41Break <DISK_INFO -- Get Disk Drive Information>
42
43; Inputs:
44; [THISCDS] Points to the Macro List Structure of interest
45; (It MAY NOT be NUL, error not detected)
46; Function:
47; Get Interesting Drive Information
48; Returns:
49; DX = Number of free allocation units
50; BX = Total Number of allocation units on disk
51; CX = Sector size
52; AL = Sectors per allocation unit
53; AH = FAT ID BYTE
54; Carry set if error (currently user FAILed to I 24)
55; Segs except ES preserved, others destroyed
56
57 procedure DISK_INFO,NEAR
58 DOSAssume CS,<DS>,"Disk_Info"
59 ASSUME ES:NOTHING
60
61 Invoke TestNet
62 JNC LOCAL_INFO
63IF NOT Installed
64 transfer NET_DISK_INFO
65ELSE
66 MOV AX,(multNET SHL 8) OR 12
67 INT 2FH
68 return
69ENDIF
70
71LOCAL_INFO:
72 MOV [EXTERR_LOCUS],errLOC_Disk
73 EnterCrit critDisk
74 invoke FATREAD_CDS ; perform media check.
75 JC CRIT_LEAVE
76 MOV BX,2
77 invoke UNPACK ; Get first FAT sector into CURBUF
78 JC CRIT_LEAVE
79 LDS SI,[CURBUF]
80ASSUME DS:NOTHING
81 MOV AH,[SI].bufinsiz ; get FAT ID BYTE
82 context DS
83 MOV CX,ES:[BP.dpb_max_cluster]
84;
85; Examine the current free count. If it indicates that we have an invalid
86; count, do the expensive calculation.
87;
88 MOV DX,ES:[BP.dpb_free_cnt] ; get free count
89 CMP DX,-1 ; is it valid?
90 JZ DoScan
91;
92; Check to see if it is in a reasonalbe range. If so, trust it and return.
93; Otherwise, we need to blast out an internal error message and then recompute
94; the count.
95;
96 CMP DX,CX ; is it in a reasonable range?
97 JB GotVal ; yes, trust it.
98 fmt TypInt,LevLog,<"Internal error: MaxClus <= FreeClus\n">
99DoScan:
100 XOR DX,DX
101 DEC CX
102SCANFREE:
103 invoke UNPACK
104 JC Crit_Leave
105 JNZ NOTFREECLUS
106 INC DX ; A free one
107NOTFREECLUS:
108 INC BX ; Next cluster
109 LOOP SCANFREE
110 DEC BX ; BX was next cluster. Convert to
111ReturnVals:
112 DEC BX ; count
113 MOV AL,ES:[BP.dpb_cluster_mask]
114 INC AL ; Sectors/cluster
115 MOV CX,ES:[BP.dpb_sector_size] ; Bytes/sector
116 MOV ES:[BP.dpb_free_cnt],DX
117 CLC
118CRIT_LEAVE:
119 LeaveCrit critDisk
120 return
121;
122; We have correctly computed everything previously. Load up registers for
123; return.
124;
125GotVal: MOV BX,CX ; get cluster count
126 JMP ReturnVals
127
128EndProc DISK_INFO
129
130CODE ENDS
131 END
diff --git a/v4.0/src/DOS/DIR.ASM b/v4.0/src/DOS/DIR.ASM
new file mode 100644
index 0000000..2a86997
--- /dev/null
+++ b/v4.0/src/DOS/DIR.ASM
@@ -0,0 +1,445 @@
1; SCCSID = @(#)dir.asm 1.1 85/04/10
2; SCCSID = @(#)dir.asm 1.1 85/04/10
3TITLE DIR - Directory and path cracking
4NAME Dir
5; Main Path cracking routines, low level search routines
6;
7; FindEntry
8; SEARCH
9; Srch
10; NEXTENT
11; MetaCompare
12; NEXTENTRY
13; GETENTRY
14; GETENT
15; SETDIRSRCH
16; SETROOTSRCH
17;
18; Revision history:
19;
20; A000 version 4.00 Jan. 1988
21;
22
23;
24; get the appropriate segment definitions
25;
26.xlist
27include dosseg.asm
28include fastopen.inc
29
30CODE SEGMENT BYTE PUBLIC 'CODE'
31 ASSUME SS:DOSGROUP,CS:DOSGROUP
32
33.xcref
34include dossym.inc
35.cref
36.list
37
38asmvar Kanji
39
40 i_need EntFree,WORD
41 i_need DirStart,WORD
42 i_need LastEnt,WORD
43 i_need ClusNum,WORD
44 i_need CurBuf,DWORD
45 i_need Attrib,BYTE
46 i_need DelAll,BYTE
47 i_need VolID,BYTE
48 i_need Name1,BYTE
49 i_need ThisDPB,DWORD
50 i_need EntLast,WORD
51 i_need Creating,BYTE
52 i_need SecClusPos,BYTE
53 i_need ClusFac,BYTE
54 i_need NxtClusNum,WORD
55 i_need DirSec,DWORD ;AN000;
56 I_need FastOpenFlg,BYTE ;AN000;
57 I_need HIGH_SECTOR,WORD ;AN000;
58
59Break <FINDENTRY -- LOOK FOR AN ENTRY>
60
61; Inputs:
62; [THISDPB] set
63; [SECCLUSPOS] = 0
64; [DIRSEC] = Starting directory sector number
65; [CLUSNUM] = Next cluster of directory
66; [CLUSFAC] = Sectors/Cluster
67; [NAME1] = Name to look for
68; Function:
69; Find file name in disk directory.
70; "?" matches any character.
71; Outputs:
72; Carry set if name not found
73; ELSE
74; Zero set if attributes match (always except when creating)
75; AH = Device ID (bit 7 set if not disk)
76; [THISDPB] = Base of drive parameters
77; DS = DOSGROUP
78; ES = DOSGROUP
79; [CURBUF+2]:BX = Pointer into directory buffer
80; [CURBUF+2]:SI = Pointer to First Cluster field in directory entry
81; [CURBUF] has directory record with match
82; [NAME1] has file name
83; [LASTENT] is entry number of the entry
84; All other registers destroyed.
85
86 procedure SEARCH,near
87
88 entry FindEntry
89 DOSAssume CS,<DS>,"FindEntry"
90 ASSUME ES:NOTHING
91
92 invoke STARTSRCH
93 MOV AL,Attrib
94 AND AL,NOT attr_ignore ; Ignore useless bits
95 CMP AL,attr_volume_id ; Looking for vol ID only ?
96 JNZ NOTVOLSRCH ; No
97 CALL SETROOTSRCH ; Yes force search of root
98NOTVOLSRCH:
99 CALL GETENTRY
100 JNC Srch
101 JMP SETESRET
102
103 entry Srch
104
105 PUSH DS
106 MOV DS,WORD PTR [CURBUF+2]
107ASSUME DS:NOTHING
108 MOV AH,BYTE PTR [BX]
109 OR AH,AH ; End of directory?
110 JZ FREE
111 CMP AH,BYTE PTR [DELALL] ; Free entry?
112 JZ FREE
113 TEST BYTE PTR [BX+11],attr_volume_id
114 ; Volume ID file?
115 JZ CHKFNAM ; NO
116 INC BYTE PTR [VOLID]
117CHKFNAM:
118; Context ES
119 ASSUME ES:DOSGroup
120 MOV SI,SS
121 MOV ES,SI
122 MOV SI,BX
123 MOV DI,OFFSET DOSGROUP:NAME1
124;;;;; 7/29/86
125 CMP BYTE PTR [NAME1],0E5H ; special char check
126 JNZ NO_E5
127 MOV BYTE PTR [NAME1],05H
128NO_E5:
129;;;;; 7/29/86
130 CALL MetaCompare
131 JZ FOUND
132 POP DS
133
134 entry NEXTENT
135 DOSAssume CS,<DS>,"NextEnt"
136
137 Assert ISDPB,<<WORD PTR THISDPB+2>,<WORD PTR THISDPB>>,"NextEnt"
138 LES BP,[THISDPB]
139ASSUME ES:NOTHING
140 CALL NEXTENTRY
141 JNC SRCH
142 JMP SHORT SETESRET
143
144FREE:
145 POP DS
146 DOSAssume CS,<DS>,"DIR/Free"
147 MOV CX,[LASTENT]
148 CMP CX,[ENTFREE]
149 JAE TSTALL
150 MOV [ENTFREE],CX
151TSTALL:
152 CMP AH,BYTE PTR [DELALL] ; At end of directory?
153NextEntJ:
154 JZ NEXTENT ; No - continue search
155 MOV [ENTLAST],CX
156 STC
157 JMP SHORT SETESRET
158
159FOUND:
160;
161; We have a file with a matching name. We must now consider the attributes:
162; ATTRIB Action
163; ------ ------
164; Volume_ID Is Volume_ID in test?
165; Otherwise If no create then Is ATTRIB+extra superset of test?
166; If create then Is ATTRIB equal to test?
167;
168 MOV CH,[SI] ; Attributes of file
169 POP DS
170 DOSAssume CS,<DS>,"DIR/found"
171 MOV AH,Attrib ; Attributes of search
172 AND AH,NOT attr_ignore
173 LEA SI,[SI+Dir_First-Dir_Attr] ; point to firclus field
174 TEST CH,attr_volume_id ; Volume ID file?
175 JZ check_one_volume_id ; Nope check other attributes
176 TEST AH,attr_volume_id ; Can we find Volume ID?
177 JZ NEXTENTJ ; Nope, (not even $FCB_CREATE)
178 XOR AH,AH ; Set zero flag for $FCB_CREATE
179 JMP SHORT RETFF ; Found Volume ID
180check_one_volume_id:
181 CMP AH,attr_volume_id ; Looking only for Volume ID?
182 JZ NEXTENTJ ; Yes, continue search
183 invoke MatchAttributes
184 JZ RETFF
185 TEST BYTE PTR [CREATING],-1 ; Pass back mismatch if creating
186 JZ NEXTENTJ ; Otherwise continue searching
187RETFF:
188 LES BP,[THISDPB]
189 MOV AH,ES:[BP.dpb_drive]
190SETESRET:
191 PUSH SS
192 POP ES
193 return
194EndProc Search
195
196; Inputs:
197; DS:SI -> 11 character FCB style name NO '?'
198; Typically this is a directory entry. It MUST be in upper case
199; ES:DI -> 11 character FCB style name with possible '?'
200; Typically this is a FCB or SFT. It MUST be in upper case
201; Function:
202; Compare FCB style names allowing for ? match to any char
203; Outputs:
204; Zero if match else NZ
205; Destroys CX,SI,DI all others preserved
206
207 procedure MetaCompare,near
208ASSUME DS:NOTHING,ES:NOTHING
209 MOV CX,11
210 IF DBCS ;AN000;
211;-------------------- Start of DBCS ;AN000;
212 CMP BYTE PTR DS:[SI],05H ;AN000;; Special case for lead byte of 05h
213 JNE WILDCRD2 ;AN000;; Compare as normal if not an 05h
214 CMP BYTE PTR ES:[DI],0E5H ;AN000;; 05h and 0E5h equivalent for lead byte
215 JNE WILDCRD2 ;AN000;; Compare as normal if not an 05h
216 DEC CX ;AN000;; One less byte to compare
217 INC SI ;AN000;; Bypass lead byte in source and
218 INC DI ;AN000;; destination when 05h and 0E5h found.
219WILDCRD2: ;AN000;
220 PUSH AX ;AN000;;KK. save ax
221cagain: ;AN000;;KK.
222 CMP CX,0 ;AN000;;KK. end of compare ?
223 JLE metaend2 ;AN000;;KK. yes
224 MOV AL,[SI] ;AN000;;KK. is it a Kanji
225 invoke testkanj ;AN000;;KK.
226 JZ notdb ;AN000;;KK. no
227 MOV AX,'??' ;AN000;;KK.
228 CMP ES:[DI],AX ;AN000;;KK. is es:di pointing to '??'
229 JNZ metaend3 ;AN000;;KK. no
230 ADD SI,2 ;AN000;;KK.
231 ADD DI,2 ;AN000;;KK. update pointers and count
232subcx: ;AN000;
233 SUB CX,2 ;AN000;;KK.
234 JMP cagain ;AN000;;KK.
235metaend3: ;AN000;;KK.
236 CMPSW ;AN000;;KK.
237 JNZ metaend2 ;AN000;;KK.
238 JMP subcx ;AN000;;KK.
239notdb: ;AN000;
240 CMPSB ;AN000;;KK. same code ?
241 JZ sameco ;AN000;;KK. yes
242 CMP BYTE PTR ES:[DI-1],"?" ;AN000;;KK. ?
243 JNZ metaend2 ;AN000;;KK. no
244sameco: ;AN000;
245 DEC CX ;AN000;;KK. decrement count
246 JMP cagain ;AN000;;KK.
247
248metaend2: ;AN000;
249 POP AX ;AN000;;KK.
250;-------------------- End of DBCS ;AN000; KK.
251 ELSE ;AN000;
252WILDCRD:
253 REPE CMPSB
254 JZ MetaRet ; most of the time we will fail.
255CHECK_META:
256 CMP BYTE PTR ES:[DI-1],"?"
257 JZ WildCrd
258MetaRet:
259 ENDIF ;AN000;
260 return ; Zero set, Match
261EndProc MetaCompare
262
263Break <NEXTENTRY -- STEP THROUGH DIRECTORY>
264
265; Inputs:
266; Same as outputs of GETENTRY, above
267; Function:
268; Update BX, and [LASTENT] for next directory entry.
269; Carry set if no more.
270
271Procedure NextEntry
272 DOSAssume CS,<DS>,"NextEntry"
273 ASSUME ES:NOTHING
274
275 MOV AX,[LASTENT]
276 CMP AX,[ENTLAST]
277 JZ NONE
278 INC AX
279 LEA BX,[BX+32]
280 CMP BX,DX
281 JB HAVIT
282 MOV BL,BYTE PTR [SECCLUSPOS]
283 INC BL
284 CMP BL,BYTE PTR [CLUSFAC]
285 JB SAMECLUS
286 MOV BX,[NXTCLUSNUM]
287 Invoke IsEOF
288 JAE NONE
289 CMP BX,2
290 JB NONE
291 JMP GETENT
292
293NONE:
294 STC
295 return
296
297HAVIT:
298 MOV [LASTENT],AX
299 CLC
300 return
301
302SAMECLUS:
303 MOV BYTE PTR [SECCLUSPOS],BL
304 MOV [LASTENT],AX
305 PUSH DS
306 LDS DI,[CURBUF]
307ASSUME DS:NOTHING
308 MOV DX,WORD PTR [DI.buf_sector+2] ;AN000; >32mb
309 MOV [HIGH_SECTOR],DX ;AN000; >32mb
310 MOV DX,WORD PTR [DI.buf_sector] ;AN000; >32mb
311
312 ADD DX,1 ;AN000; >32mb
313 ADC [HIGH_SECTOR],0 ;AN000; >32mb
314 POP DS
315 DOSAssume CS,<DS>,"DIR/SameClus"
316 invoke FIRSTCLUSTER
317 XOR BX,BX
318 JMP SETENTRY
319EndProc NextEntry
320
321; Inputs:
322; [LASTENT] has directory entry
323; ES:BP points to drive parameters
324; [DIRSEC],[CLUSNUM],[CLUSFAC],[ENTLAST] set for DIR involved
325; Function:
326; Locates directory entry in preparation for search
327; GETENT provides entry for passing desired entry in AX
328; Outputs:
329; [CURBUF+2]:BX = Pointer to next directory entry in CURBUF
330; [CURBUF+2]:DX = Pointer to first byte after end of CURBUF
331; [LASTENT] = New directory entry number
332; [NXTCLUSNUM],[SECCLUSPOS] set via DIRREAD
333; Carry set if error (currently user FAILed to I 24)
334
335Procedure GETENTRY,NEAR
336 DOSAssume CS,<DS>,"GetEntry"
337 ASSUME ES:NOTHING
338
339 MOV AX,[LASTENT]
340
341 entry GETENT
342
343 Assert ISDPB,<ES,BP>,"GetEntry/GetEnt"
344 MOV [LASTENT],AX
345;
346; Convert the entry number in AX into a byte offset from the beginning of the
347; directory.
348;
349 mov cl,5 ; shift left by 5 = mult by 32
350 rol ax,cl ; keep hight order bits
351 mov dx,ax
352 and ax, NOT (32-1) ; mask off high order bits
353 and dx, 32-1 ; mask off low order bits
354;
355; DX:AX contain the byte offset of the required directory entry from the
356; beginning of the directory. Convert this to a sector number. Round the
357; sector size down to a multiple of 32.
358;
359 MOV BX,ES:[BP.dpb_sector_size]
360 AND BL,255-31 ; Must be multiple of 32
361 DIV BX
362 MOV BX,DX ; Position within sector
363 PUSH BX
364 invoke DIRREAD
365 POP BX
366 retc
367SETENTRY:
368 MOV DX,WORD PTR [CURBUF]
369 ADD DX,BUFINSIZ
370 ADD BX,DX
371 ADD DX,ES:[BP.dpb_sector_size] ; Always clears carry
372 return
373EndProc GetEntry
374
375Break <SETDIRSRCH SETROOTSRCH -- Set Search environments>
376
377; Inputs:
378; BX cluster number of start of directory
379; ES:BP Points to DPB
380; DI next cluster number from fastopen extended info. DOS 3.3 only
381; Function:
382; Set up a directory search
383; Outputs:
384; [DIRSTART] = BX
385; [CLUSFAC],[CLUSNUM],[SECCLUSPOS],[DIRSEC] set
386; Carry set if error (currently user FAILed to I 24)
387; destroys AX,DX,BX
388
389 procedure SETDIRSRCH
390 DOSAssume CS,<DS>,"SetDirSrch"
391 ASSUME ES:NOTHING
392
393 Assert ISDPB,<ES,BP>,"SetDirSrch"
394 OR BX,BX
395 JZ SETROOTSRCH
396 MOV [DIRSTART],BX
397 MOV AL,ES:[BP.dpb_cluster_mask]
398 INC AL
399 MOV BYTE PTR [CLUSFAC],AL
400; DOS 3.3 for FastOPen F.C. 6/12/86
401 SaveReg <SI>
402 TEST [FastOpenFlg],Lookup_Success
403 JNZ UNP_OK
404
405; DOS 3.3 for FastOPen F.C. 6/12/86
406 invoke UNPACK
407 JNC UNP_OK
408 RestoreReg <SI>
409 return
410
411UNP_OK:
412 MOV [CLUSNUM],DI
413 MOV DX,BX
414 XOR BL,BL
415 MOV BYTE PTR [SECCLUSPOS],BL
416 invoke FIGREC
417 RestoreReg <SI>
418 PUSH DX ;AN000; >32mb
419 MOV DX,[HIGH_SECTOR] ;AN000; >32mb
420 MOV WORD PTR [DIRSEC+2],DX ;AN000; >32mb
421 POP DX ;AN000; >32mb
422 MOV WORD PTR [DIRSEC],DX
423 CLC
424 return
425
426entry SETROOTSRCH
427 DOSAssume CS,<DS>,"SetRootSrch"
428 ASSUME ES:NOTHING
429 XOR AX,AX
430 MOV [DIRSTART],AX
431 MOV BYTE PTR [SECCLUSPOS],AL
432 DEC AX
433 MOV [CLUSNUM],AX
434 MOV AX,ES:[BP.dpb_first_sector]
435 MOV DX,ES:[BP.dpb_dir_sector]
436 SUB AX,DX
437 MOV BYTE PTR [CLUSFAC],AL
438 MOV WORD PTR [DIRSEC],DX ;F.C. >32mb
439 MOV WORD PTR [DIRSEC+2],0 ;F.C. >32mb
440 CLC
441 return
442EndProc SETDIRSRCH
443
444CODE ENDS
445 END
diff --git a/v4.0/src/DOS/DIR2.ASM b/v4.0/src/DOS/DIR2.ASM
new file mode 100644
index 0000000..1346f43
--- /dev/null
+++ b/v4.0/src/DOS/DIR2.ASM
@@ -0,0 +1,1353 @@
1; SCCSID = @(#)dir2.asm 1.2 85/07/23
2; SCCSID = @(#)dir2.asm 1.2 85/07/23
3TITLE DIR2 - Directory and path cracking
4NAME Dir2
5; Main Path cracking routines, low level search routines and device
6; name detection routines
7;
8; GETPATH
9; GetPathNoSet
10; CHKDEV
11; ROOTPATH
12; FINDPATH
13; StartSrch
14; MatchAttributes
15; DEVNAME
16; Build_device_ent
17; Validate_CDS
18; CheckThisDevice
19;
20; Revision history:
21;
22; A000 version 4.00 Jan. 1988
23; A001 PTM 3564 -- search using fastopen
24
25;
26; get the appropriate segment definitions
27;
28.xlist
29include dosseg.asm
30
31CODE SEGMENT BYTE PUBLIC 'CODE'
32 ASSUME SS:DOSGROUP,CS:DOSGROUP
33
34.xcref
35include dossym.inc
36include devsym.inc
37include fastopen.inc ;DOS 3.3
38.cref
39.list
40
41asmvar Kanji
42
43 i_need NoSetDir,BYTE
44 i_need EntFree,WORD
45 i_need DirStart,WORD
46 i_need LastEnt,WORD
47 i_need WFP_START,WORD
48 i_need CURR_DIR_END,WORD
49 i_need CurBuf,DWORD
50 i_need THISCDS,DWORD
51 i_need Attrib,BYTE
52 i_need SAttrib,BYTE
53 i_need VolID,BYTE
54 i_need Name1,BYTE
55 i_need ThisDPB,DWORD
56 i_need EntLast,WORD
57 i_need Creating,BYTE
58 i_need NULDEV,DWORD
59 i_need DEVPT,DWORD
60 i_need DEVFCB,BYTE
61 i_need ALLOWED,BYTE
62 i_need EXTERR_LOCUS,BYTE
63 I_need FastOpenFlg,BYTE ;DOS 3.3
64 I_need FastOpenTable,BYTE ;DOS 3.3
65 I_need Dir_Info_Buff,BYTE ;DOS 3.3
66 I_need FastOpen_Ext_Info,BYTE ;DOS 3.3
67 I_need CLUSNUM,WORD ;DOS 3.3
68 I_need Next_Element_Start,WORD ;DOS 3.3
69 I_need HIGH_SECTOR,WORD ;AN000;>32mb
70 I_need DOS34_FLAG,WORD ;AN000;>32mb
71
72
73Break <GETPATH -- PARSE A WFP>
74
75; Inputs:
76; [WFP_START] Points to WFP string ("d:\" must be first 3 chars, NUL
77; terminated; d:/ (note forward slash) indicates a real device).
78; [CURR_DIR_END] Points to end of Current dir part of string
79; ( = -1 if current dir not involved, else
80; Points to first char after last "/" of current dir part)
81; [THISCDS] Points to CDS being used
82; [SATTRIB] Is attribute of search, determines what files can be found
83; [NoSetDir] set
84; [THISDPB] set to DPB if disk otherwise garbage.
85; Function:
86; Crack the path
87; Outputs:
88; Sets EXTERR_LOCUS = errLOC_Disk if disk file
89; Sets EXTERR_LOCUS = errLOC_Unk if char device
90; ID1 field of [THISCDS] updated appropriately
91; [ATTRIB] = [SATTRIB]
92; ES:BP Points to DPB
93; Carry set if bad path
94; SI Points to path element causing failure
95; Zero set
96; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to
97; start a search on the last directory
98; CL is zero if there is a bad name in the path
99; CL is non-zero if the name was simply not found
100; [ENTFREE] may have free spot in directory
101; [NAME1] is the name.
102; CL = 81H if '*'s or '?' in NAME1, 80H otherwise
103; Zero reset
104; File in middle of path or bad name in path or attribute mismatch
105; or path too long or malformed path
106; ELSE
107; [CurBuf] = -1 if root directory
108; [CURBUF] contains directory record with match
109; [CURBUF+2]:BX Points into [CURBUF] to start of entry
110; [CURBUF+2]:SI Points into [CURBUF] to dir_first field for entry
111; AH = device ID
112; bit 7 of AH set if device SI and BX
113; will point DOSGROUP relative The firclus
114; field of the device entry contains the device pointer
115; [NAME1] Has name looked for
116; If last element is a directory zero is set and:
117; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC]
118; are set up to start a search on it.
119; unless [NoSetDir] is non zero in which case the return is
120; like that for a file (except for zero flag)
121; If last element is a file zero is reset
122; [DIRSEC],[CLUSNUM],[CLUSFAC],[NXTCLUSNUM],[SECCLUSPOS],
123; [LASTENT], [ENTLAST] are set to continue search of last
124; directory for furthur matches on NAME1 via the NEXTENT
125; entry point in FindEntry (or GETENT entry in GETENTRY in
126; which case [NXTCLUSNUM] and [SECCLUSPOS] need not be valid)
127; DS preserved, Others destroyed
128
129 procedure GETPATH,near
130 DOSAssume CS,<DS>,"GetPath"
131 ASSUME ES:NOTHING
132
133 MOV WORD PTR [CREATING],0E500H ; Not Creating, not DEL *.*
134
135;Same as GetPath only CREATING and DELALL already set
136 entry GetPathNoSet
137 MOV [EXTERR_LOCUS],errLOC_Disk
138 MOV WORD PTR CurBuf,-1 ; initial setting
139;
140; See if the input indicates a device that has already been detected. If so,
141; go build the guy quickly. Otherwise, let findpath find the device.
142;
143 MOV DI,Wfp_Start ; point to the beginning of the name
144 CMP WORD PTR [DI+1],'\' SHL 8 + ':'
145 JZ CrackIt
146;
147; Let ChkDev find it in the device list
148;
149 ADD DI,3
150 MOV SI,DI ; let CHKDEV see the original name
151 CALL CHKDEV
152 JC InternalError
153Build_devJ:
154 MOV AL,SAttrib
155 MOV Attrib,AL
156 MOV [EXTERR_LOCUS],errLOC_Unk ; In the particular case of
157 ; "finding" a char device
158 ; set LOCUS to Unknown. This makes
159 ; certain idiotic problems reported
160 ; by a certain 3 letter OEM go away.
161;
162; Take name in name1 and pack it back into where wfp_start points. This
163; guarantees wfp_start pointing to a canonical representation of a device.
164; We are allowed to do this as GetPath is *ALWAYS* called before entering a
165; wfp into the share set.
166;
167; We copy chars from name1 to wfp_start remembering the position of the last
168; non-space seen +1. This position is kept in DX.
169;
170 Context ES
171 mov si,offset DOSGroup:Name1
172 mov di,wfp_start
173 mov dx,di
174 mov cx,8 ; 8 chars in device name
175MoveLoop:
176 lodsb
177 stosb
178 cmp al," "
179 jz nosave
180 IF DBCS ;AN000;;
181; cmp al,81h ;AN000;; 2/23/KK
182; jne notKanji ;AN000;; 2/23/KK
183; cmp cx,1 ;AN000; 2/23/KK
184; je notKanji ;AN000; 2/23/KK
185; cmp byte ptr [si],40h ;AN000; 2/23/KK
186; jne notKanji ;AN000;; 2/23/KK
187; lodsb ;AN000;; 2/23/KK
188; stosb ;AN000;; 2/23/KK
189; dec cx ;AN000;; 2/23/KK
190; jmp nosave ;AN000;; 2/23/KK
191;notKanji: ;AN000;; 2/23/KK
192 ENDIF
193 mov dx,di
194NoSave:
195 loop MoveLoop
196;
197; DX is the position of the last seen non-space + 1. We terminate the name
198; at this point.
199;
200 mov di,dx
201 mov byte ptr [di],0 ; end of string
202 invoke Build_device_ent ; Clears carry sets zero
203 INC AL ; reset zero
204 return
205
206 assume es:nothing
207
208InternalError:
209 JMP InternalError ; freeze
210
211;
212; Start off at the correct spot. Optimize if the current dir part is valid.
213;
214CrackIt:
215 MOV SI,[CURR_DIR_END] ; get current directory pointer
216 CMP SI,-1 ; valid?
217 JNZ LOOK_SING ; Yes, use it.
218 LEA SI,[DI+3] ; skip D:\
219LOOK_SING:
220 Assert ISDPB,<<WORD PTR THISDPB+2>,<WORD PTR THISDPB>>,"Crackit"
221 MOV Attrib,attr_directory+attr_system+attr_hidden
222 ; Attributes to search through Dirs
223 LES DI,[THISCDS]
224 MOV AX,-1
225 MOV BX,ES:[DI.curdir_ID]
226 MOV SI,[CURR_DIR_END]
227;
228; AX = -1
229; BX = cluster number of current directory. THis number is -1 if the media
230; has been uncertainly changed.
231; SI = offset in DOSGroup into path to end of current directory text. This
232; may be -1 if no current directory part has been used.
233;
234 CMP SI,AX ; if Current directory is not part
235 JZ NO_CURR_D ; then we must crack from root
236 CMP BX,AX ; is the current directory cluster valid
237
238; DOS 3.3 6/25/86
239 JZ NO_CURR_D ; no, crack form the root
240 TEST [FastOpenFlg],FastOpen_Set ; for fastopen ?
241 JZ GOT_SEARCH_CLUSTER ; no
242 PUSH ES ; save registers
243 PUSH DI
244 PUSH CX
245 PUSH [SI-1] ; save \ and 1st char of next element
246 PUSH SI
247 PUSH BX
248
249 MOV BYTE PTR [SI-1],0 ; call fastopen to look up cur dir info
250 MOV SI,[Wfp_Start]
251 MOV BX,OFFSET DOSGROUP:FastOpenTable
252 MOV DI,OFFSET DOSGROUP:Dir_Info_Buff
253 MOV CX,OFFSET DOSGROUP:FastOpen_Ext_Info
254 MOV AL,FONC_look_up
255 PUSH DS
256 POP ES
257 CALL DWORD PTR [BX.FASTOPEN_NAME_CACHING]
258 JC GO_Chk_end1 ;fastopen not installed, or wrong drive. Go to Got_Srch_cluster
259 CMP BYTE PTR [SI],0 ;fastopen has current dir info?
260 JE GO_Chk_end ;yes. Go to got_serch_cluster
261 stc
262 jmp short GO_Chk_end ;Go to No_Curr_D
263GO_Chk_end1:
264 clc
265GO_Chk_end: ; restore registers
266 POP BX
267 POP SI
268 POP [SI-1]
269 POP CX
270 POP DI
271 POP ES
272 JNC GOT_SEARCH_CLUSTER ; crack based on cur dir
273
274; DOS 3.3 6/25/86
275;
276; We must cract the path beginning at the root. Advance pointer to beginning
277; of path and go crack from root.
278;
279NO_CURR_D:
280 MOV SI,[WFP_START]
281 LEA SI,[SI+3] ; Skip "d:/"
282 LES BP,[THISDPB] ; Get ES:BP
283 JMP ROOTPATH
284;
285; We are able to crack from the current directory part. Go set up for search
286; of specified cluster.
287;
288GOT_SEARCH_CLUSTER:
289 LES BP,[THISDPB] ; Get ES:BP
290 invoke SETDIRSRCH
291 JC SETFERR
292 JMP FINDPATH
293
294SETFERR:
295 XOR CL,CL ; set zero
296 STC
297 Return
298
299EndProc GETPATH
300
301; Check to see if the name at DS:DI is a device. Returns carry set if not a
302; device.
303; Blasts CX,SI,DI,AX,BX
304
305Procedure ChkDev,NEAR
306 ASSUME ES:Nothing,DS:NOTHING
307
308 MOV SI,DI
309 MOV DI,SS
310 MOV ES,DI
311 ASSUME ES:DOSGroup ; Now here is where ES is DOSGroup
312
313 MOV DI,OFFSET DOSGROUP:NAME1
314 MOV CX,9
315TESTLOOP:
316 invoke GETLET
317 IF DBCS ;AN000;
318 invoke Testkanj ;AN000;; 2/13/KK
319 jz Notkanja ;AN000;; 2/13/KK
320 stosb ;AN000;; Skip second byte 2/13/KK
321 dec cx ;AN000;; 2/13/KK
322 jcxz notdev ;AN000;; 2/13/KK
323 lodsb ;AN000;; 2/13/KK
324 jmp short stowit ;AN000;; 2/13/KK
325Notkanja: ;AN000;
326 ENDIF ;AN000;
327 CMP AL,'.'
328 JZ TESTDEVICE
329 invoke PATHCHRCMP
330 JZ NOTDEV
331 OR AL,AL
332 JZ TESTDEVICE
333stowit:
334 STOSB
335 LOOP TESTLOOP
336NOTDEV:
337 STC
338 return
339
340TESTDEVICE:
341 ADD CX,2
342 MOV AL,' '
343 REP STOSB
344 MOV AX,SS
345 MOV DS,AX
346 invoke DEVNAME
347 return
348EndProc ChkDev
349
350Break <ROOTPATH, FINDPATH -- PARSE A PATH>
351
352; Inputs:
353; Same as FINDPATH but,
354; SI Points to asciz string of path which is assumed to start at
355; the root (no leading '/').
356; Function:
357; Search from root for path
358; Outputs:
359; Same as FINDPATH but:
360; If root directory specified, [CURBUF] and [NAME1] are NOT set, and
361; [NoSetDir] is ignored.
362
363 procedure ROOTPATH,near
364
365 DOSAssume CS,<DS>,"RootPath"
366 ASSUME ES:NOTHING
367
368 invoke SETROOTSRCH
369 CMP BYTE PTR [SI],0
370 JNZ FINDPATH
371
372; Root dir specified
373 MOV AL,SAttrib
374 MOV Attrib,AL
375 XOR AH,AH ; Sets "device ID" byte, sets zero
376 ; (dir), clears carry.
377 return
378
379; Inputs:
380; [ATTRIB] Set to get through directories
381; [SATTRIB] Set to find last element
382; ES:BP Points to DPB
383; SI Points to asciz string of path (no leading '/').
384; [SECCLUSPOS] = 0
385; [DIRSEC] = Phys sec # of first sector of directory
386; [CLUSNUM] = Cluster # of next cluster
387; [CLUSFAC] = Sectors per cluster
388; [NoSetDir] set
389; [CURR_DIR_END] Points to end of Current dir part of string
390; ( = -1 if current dir not involved, else
391; Points to first char after last "/" of current dir part)
392; [THISCDS] Points to CDS being used
393; [CREATING] and [DELALL] set
394; Function:
395; Parse path name
396; Outputs:
397; ID1 field of [THISCDS] updated appropriately
398; [ATTRIB] = [SATTRIB]
399; ES:BP Points to DPB
400; [THISDPB] = ES:BP
401; Carry set if bad path
402; SI Points to path element causing failure
403; Zero set
404; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to
405; start a search on the last directory
406; CL is zero if there is a bad name in the path
407; CL is non-zero if the name was simply not found
408; [ENTFREE] may have free spot in directory
409; [NAME1] is the name.
410; CL = 81H if '*'s or '?' in NAME1, 80H otherwise
411; Zero reset
412; File in middle of path or bad name in path
413; or path too long or malformed path
414; ELSE
415; [CURBUF] contains directory record with match
416; [CURBUF+2]:BX Points into [CURBUF] to start of entry
417; [CURBUF+2]:SI Points to fcb_FIRCLUS field for entry
418; [NAME1] Has name looked for
419; AH = device ID
420; bit 7 of AH set if device SI and BX
421; will point DOSGROUP relative The firclus
422; field of the device entry contains the device pointer
423; If last element is a directory zero is set and:
424; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC]
425; are set up to start a search on it,
426; unless [NoSetDir] is non zero in which case the return is
427; like that for a file (except for zero flag)
428; If last element is a file zero is reset
429; [DIRSEC],[CLUSNUM],[CLUSFAC],[NXTCLUSNUM],[SECCLUSPOS],
430; [LASTENT], [ENTLAST] are set to continue search of last
431; directory for furthur matches on NAME1 via the NEXTENT
432; entry point in FindEntry (or GETENT entry in GETENTRY in
433; which case [NXTCLUSNUM] and [SECCLUSPOS] need not be valid)
434; Destroys all other registers
435
436 entry FINDPATH
437 DOSAssume CS,<DS>,"FindPath"
438 ASSUME ES:NOTHING
439
440 Assert ISDPB,<ES,BP>,"FindPath"
441 PUSH ES ; Save ES:BP
442 PUSH SI
443 MOV DI,SI
444 MOV CX,[DIRSTART] ; Get start clus of dir being searched
445 CMP [CURR_DIR_END],-1
446 JZ NOIDS ; No current dir part
447 CMP DI,[CURR_DIR_END]
448 JNZ NOIDS ; Not to current dir end yet
449 LES DI,[THISCDS]
450 MOV ES:[DI.curdir_ID],CX ; Set current directory currency
451NOIDS:
452;
453; Parse the name off of DS:SI into NAME1. AL = 1 if there was a meta
454; character in the string. CX,DI may be destroyed.
455;
456; invoke NAMETRANS
457; MOV CL,AL
458;
459; The above is the slow method. The name has *already* been munged by
460; TransPath so no special casing needs to be done. All we do is try to copy
461; the name until ., \ or 0 is hit.
462;
463 MOV AX,SS
464 MOV ES,AX
465 MOV DI,OFFSET DOSGroup:Name1
466 MOV AX,' '
467 STOSB
468 STOSW
469 STOSW
470 STOSW
471 STOSW
472 STOSW
473 MOV DI,OFFSET DOSGroup:Name1
474 XOR AH,AH ; bits for CL
475 IF DBCS ;AN000;
476;-------------------------- Start of DBC;AN000;S 2/13/KK
477 XOR CL,CL ;AN000;; clear count for volume id
478 LODSB ;AN000;;IBMJ fix 9/04/86
479 CMP AL,05h ;AN000;;IBMJ fix 9/04/86
480 JNE GetNam2 ;AN000;;IBMJ fix 9/04/86
481 PUSH AX ;AN000; ;IBMJ fix 9/04/86
482 MOV AL,0E5h ;AN000;;IBMJ fix 9/04/86
483 Invoke TestKanj ;AN000;;IBMJ fix 9/04/86
484 POP AX ;AN000; ;IBMJ fix 9/04/86
485 JZ Notkanjb ;AN000; ;IBMJ fix 9/04/86
486 JMP SHORT GetNam3 ;AN000;;IBMJ fix 9/04/86
487;-------------------------- End of DBCS ;AN000;2/13/KK
488 ENDIF
489GetNam:
490 INC CL ;AN000; KK incrment volid count
491 LODSB
492 IF DBCS ;AN000;
493GetNam2: ;AN000;; 2/13/KK
494 invoke Testkanj ;AN000;; 2/13/KK
495 jz Notkanjb ;AN000;; 2/13/KK
496GetNam3: ;AN000;; 2/13/KK
497 STOSB ;AN000;; 2/13/KK
498 INC CL ;AN000;; KK incrment volid count
499 LODSB ;AN000;; 2/13/KK
500 TEST [DOS34_FLAG],DBCS_VOLID ;AN000;; 2/13/KK
501 JZ notvol ;AN000;; 2/13/KK
502 CMP CL,8 ;AN000;; 2/13/KK
503 JNZ notvol ;AN000;; 2/13/KK
504 CMP AL,'.' ;AN000;; 2/13/KK
505 JNZ notvol ;AN000;; 2/13/KK
506 LODSB ;AN000;; 2/13/KK
507notvol: ;AN000;
508 jmp short StoNam ;AN000;; 2/13/KK
509Notkanjb: ;AN000;; 2/13/KK
510 ENDIF ;AN000;
511 CMP AL,'.'
512 JZ setExt
513 OR AL,AL
514 JZ GetDone
515 CMP AL,'\'
516 JZ GetDone
517 CMP AL,'?'
518 JNZ StoNam
519 OR AH,1
520StoNam: STOSB
521 JMP GetNam
522SetExt:
523 MOV DI,OFFSET DOSGroup:Name1+8
524GetExt:
525 LODSB
526 IF DBCS ;AN000;
527 invoke TestKanj ;AN000;; 2/13/KK
528 jz Notkanjc ;AN000;; 2/13/KK
529 STOSB ;AN000;; 2/13/KK
530 LODSB ;AN000;; 2/13/KK
531 jmp short StoExt ;AN000;; 2/13/KK
532Notkanjc: ;AN000;; 2/13/KK
533 ENDIF ;AN000;
534 OR AL,AL
535 JZ GetDone
536 CMP AL,'\'
537 JZ GetDone
538 CMP AL,'?'
539 JNZ StoExt
540 OR AH,1
541StoExt: STOSB
542 JMP GetExt
543GetDone:
544 DEC SI
545 MOV CL,AH
546
547
548 OR CL,80H
549 POP DI ; Start of this element
550 POP ES ; Restore ES:BP
551 CMP SI,DI
552 JNZ check_device
553 JMP BADPATH ; NUL parse (two delims most likely)
554check_device:
555 PUSH SI ; Start of next element
556 MOV AL,BYTE PTR [SI]
557 OR AL,AL
558 JNZ NOT_LAST
559
560;
561; for last element of the path switch to the correct search attributes
562;
563 MOV BH,SAttrib
564 MOV Attrib,BH
565NOT_LAST:
566
567;
568; check name1 to see if we have a device...
569;
570 PUSH ES ; Save ES:BP
571 context ES
572 invoke DevName ; blast BX
573 POP ES ; Restore ES:BP
574 ASSUME ES:NOTHING
575 JC FindFile ; Not a device
576 OR AL,AL ; Test next char again
577 JZ GO_BDEV
578 JMP FileInPath ; Device name in middle of path
579
580GO_BDEV:
581 POP SI ; Points to NUL at end of path
582 JMP Build_devJ
583
584FindFile:
585 ASSUME ES:NOTHING
586;;;; 7/28/86
587 CMP BYTE PTR [NAME1],0E5H ; if 1st char = E5
588 JNZ NOE5 ; no
589 MOV BYTE PTR [NAME1],05H ; change it to 05
590NOE5:
591
592;;;; 7/28/86
593 PUSH DI ; Start of this element
594 PUSH ES ; Save ES:BP
595 PUSH CX ; CL return from NameTrans
596;DOS 3.3 FastOPen 6/12/86 F.C.
597
598 CALL LookupPath ; call fastopen to get dir entry
599 JNC DIR_FOUND ; found dir entry
600
601;DOS 3.3 FastOPen 6/12/86 F.C.
602 invoke FINDENTRY
603DIR_FOUND:
604 POP CX
605 POP ES
606 POP DI
607 JNC LOAD_BUF
608 JMP BADPATHPOP
609
610LOAD_BUF:
611 LDS DI,[CURBUF]
612ASSUME DS:NOTHING
613 TEST BYTE PTR [BX+dir_attr],attr_directory
614 JNZ GO_NEXT ; DOS 3.3
615 JMP FileInPath ; Error or end of path
616;
617; if we are not setting the directory, then check for end of string
618;
619GO_NEXT:
620 CMP BYTE PTR [NoSetDir],0
621 JZ SetDir
622 MOV DX,DI ; Save pointer to entry
623 MOV CX,DS
624 context DS
625 POP DI ; Start of next element
626 TEST [FastOpenFlg],FastOpen_Set ;only DOSOPEN can take advantage of
627 JZ nofast ; the FastOpen
628 TEST [FastOpenFlg],Lookup_Success ; Lookup just happened
629 JZ nofast ; no
630 MOV DI,[Next_Element_Start] ; no need to insert it again
631nofast:
632 CMP BYTE PTR [DI],0
633 JNZ NEXT_ONE ; DOS 3.3
634 JMP SetRet ; Got it
635NEXT_ONE:
636 PUSH DI ; Put start of next element back on stack
637 MOV DI,DX
638 MOV DS,CX ; Get back pointer to entry
639ASSUME DS:NOTHING
640
641SetDir:
642 MOV DX,[SI] ; Dir_first
643
644;DOS 3.3 FastOPen 6/12/86 F.C.
645
646 PUSH DS ; save [curbuf+2]
647 context DS ; set DS Dosgroup
648 TEST [FastOpenFlg],Lookup_Success ;
649 JZ DO_NORMAL ; fastopen not in memory or path not
650 MOV BX,DX ; not found
651 MOV DI,[CLUSNUM] ; clusnum was set in LookupPath
652 PUSH AX ; save device id (AH)
653 invoke SETDIRSRCH
654 POP AX ; restore device id (AH)
655 ADD SP,2 ; pop ds in stack
656 JMP FAST_OPEN_SKIP
657
658DO_NORMAL:
659ASSUME DS:NOTHING
660 POP DS ; DS = [curbuf + 2]
661;DOS 3.3 FastOPen 6/12/86 F.C.
662
663 SUB BX,DI ; Offset into sector of start of entry
664 SUB SI,DI ; Offset into sector of dir_first
665 PUSH BX
666 PUSH AX
667 PUSH SI
668 PUSH CX
669 PUSH WORD PTR [DI.buf_sector] ;AN000;>32mb
670 PUSH WORD PTR [DI.buf_sector+2] ;AN000;>32mb
671 MOV BX,DX
672 context DS
673 invoke SETDIRSRCH ; This uses UNPACK which might blow
674 ; the entry sector buffer
675 POP [HIGH_SECTOR]
676 POP DX
677 JC SKIP_GETB
678 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
679 XOR AL,AL
680 invoke GETBUFFR ; Get the entry buffer back
681SKIP_GETB:
682 POP CX
683 POP SI
684 POP AX
685 POP BX
686 JNC SET_THE_BUF
687 POP DI ; Start of next element
688 MOV SI,DI ; Point with SI
689 JMP SHORT BADPATH
690
691SET_THE_BUF:
692 invoke SET_BUF_AS_DIR
693 MOV DI,WORD PTR [CURBUF]
694 ADD SI,DI ; Get the offsets back
695 ADD BX,DI
696; DOS 3.3 FasOpen 6/12/86 F.C.
697
698FAST_OPEN_SKIP:
699
700 POP DI ; Start of next element
701 CALL InsertPath ; insert dir entry info
702
703; DOS 3.3 FasOpen 6/12/86 F.C.
704
705
706 MOV AL,[DI]
707 OR AL,AL
708 JZ SETRET ; At end
709 INC DI ; Skip over "/"
710 MOV SI,DI ; Point with SI
711 invoke PATHCHRCMP
712 JNZ find_bad_name ; oops
713 JMP FINDPATH ; Next element
714
715find_bad_name:
716 DEC SI ; Undo above INC to get failure point
717BADPATH:
718 XOR CL,CL ; Set zero
719 JMP SHORT BADPRET
720
721FILEINPATH:
722 POP DI ; Start of next element
723 context DS ; Got to from one place with DS gone
724; DOS 3.3 FastOpen
725
726 TEST [FastOpenFlg],FastOpen_Set ; do this here is we don't want to
727 JZ NO_FAST ; device info to fastopen
728 TEST [FastOpenFlg],Lookup_Success
729 JZ NO_FAST
730 MOV DI,[Next_Element_Start] ; This takes care of one time lookup
731 ; success
732NO_FAST:
733
734; DOS 3.3 FastOpen
735
736 MOV AL,[DI]
737 OR AL,AL
738 JZ INCRET
739 MOV SI,DI ; Path too long
740 JMP SHORT BADPRET
741
742INCRET:
743; DOS 3.3 FasOpen 6/12/86 F.C.
744
745 CALL InsertPath ; insert dir entry info
746
747; DOS 3.3 FasOpen 6/12/86 F.C.
748 INC AL ; Reset zero
749SETRET:
750 return
751
752BADPATHPOP:
753 POP SI ; Start of next element
754 MOV AL,[SI]
755 MOV SI,DI ; Start of bad element
756 OR AL,AL ; zero if bad element is last, non-zero if path too long
757BADPRET:
758 MOV AL,SAttrib
759 MOV Attrib,AL ; Make sure return correct
760 STC
761 return
762EndProc ROOTPATH
763
764Break <STARTSRCH -- INITIATE DIRECTORY SEARCH>
765
766; Inputs:
767; [THISDPB] Set
768; Function:
769; Set up a search for GETENTRY and NEXTENTRY
770; Outputs:
771; ES:BP = Drive parameters
772; Sets up LASTENT, ENTFREE=ENTLAST=-1, VOLID=0
773; Destroys ES,BP,AX
774
775 procedure StartSrch,NEAR
776 DOSAssume CS,<DS>,"StartSrch"
777 ASSUME ES:NOTHING
778
779 Assert ISDPB,<<WORD PTR THISDPB+2>,<WORD PTR THISDPB>>,"StartSrch"
780 LES BP,[THISDPB]
781 XOR AX,AX
782 MOV [LASTENT],AX
783 MOV BYTE PTR [VOLID],AL ; No volume ID found
784 DEC AX
785 MOV [ENTFREE],AX
786 MOV [ENTLAST],AX
787 return
788EndProc StartSrch
789
790BREAK <MatchAttributes - the final check for attribute matching>
791
792;
793; Input: [Attrib] = attribute to search for
794; CH = found attribute
795; Output: JZ <match>
796; JNZ <nomatch>
797; Registers modified: noneski
798 procedure MatchAttributes,near
799 ASSUME DS:NOTHING,ES:NOTHING
800 PUSH AX
801 MOV AL,Attrib ; AL <- SearchSet
802 NOT AL ; AL <- SearchSet'
803 AND AL,CH ; AL <- SearchSet' and FoundSet
804 AND AL,attr_all ; AL <- SearchSet' and FoundSet and Important
805;
806; the result is non-zero if an attribute is not in the search set
807; and in the found set and in the important set. This means that we do not
808; have a match. Do a JNZ <nomatch> or JZ <match>
809;
810 POP AX
811 return
812EndProc MatchAttributes
813
814Break <DevName - Look for name of device>
815
816; Inputs:
817; DS,ES:DOSGROUP
818; Filename in NAME1
819; ATTRIB set so that we can error out if looking for Volume IDs
820; Function:
821; Determine if file is in list of I/O drivers
822; Outputs:
823; Carry set if not a device
824; ELSE
825; Zero flag set
826; BH = Bit 7,6 = 1, bit 5 = 0 (cooked mode)
827; bits 0-4 set from low byte of attribute word
828; DEVPT = DWORD pointer to Device header of device
829; BX destroyed, others preserved
830
831 procedure DEVNAME,NEAR
832 DOSAssume CS,<ES,DS>,"DevName"
833
834 PUSH SI
835 PUSH DI
836 PUSH CX
837 PUSH AX
838
839; E5 special code
840 PUSH WORD PTR [NAME1]
841 CMP [NAME1],5
842 JNZ NOKTR
843 MOV [NAME1],0E5H
844NOKTR:
845
846 TEST Attrib,attr_volume_id ; If looking for VOL id don't find devs
847 JNZ RET31
848 MOV SI,OFFSET DOSGROUP:NULDEV
849LOOKIO:
850ASSUME DS:NOTHING
851 TEST [SI.SDEVATT],DEVTYP
852 JZ SKIPDEV ; Skip block devices (NET and LOCAL)
853 MOV AX,SI
854 ADD SI,SDEVNAME
855 MOV DI,OFFSET DOSGROUP:NAME1
856 MOV CX,4 ; All devices are 8 letters
857 REPE CMPSW ; Check for name in list
858 MOV SI,AX
859 JZ IOCHK ; Found it?
860SKIPDEV:
861 LDS SI,DWORD PTR [SI] ; Get address of next device
862 CMP SI,-1 ; At end of list?
863 JNZ LOOKIO
864RET31: STC ; Not found
865RETNV: MOV CX,SS
866 MOV DS,CX
867 ASSUME DS:DOSGroup
868 POP WORD PTR [NAME1]
869 POP AX
870 POP CX
871 POP DI
872 POP SI
873 RET
874
875IOCHK:
876ASSUME DS:NOTHING
877 MOV WORD PTR [DEVPT+2],DS ; Save pointer to device
878 MOV BH,BYTE PTR [SI.SDEVATT]
879 OR BH,0C0H
880 AND BH,NOT 020H ; Clears Carry
881 MOV WORD PTR [DEVPT],SI
882 JMP RETNV
883EndProc DevName
884
885BREAK <Build_device_ent - Make a Directory entry>
886
887; Inputs:
888; [NAME1] has name
889; BH is attribute field (supplied by DEVNAME)
890; [DEVPT] points to device header (supplied by DEVNAME)
891; Function:
892; Build a directory entry for a device at DEVFCB
893; Outputs:
894; BX points to DEVFCB
895; SI points to dir_first field
896; AH = input BH
897; AL = 0
898; dir_first = DEVPT
899; Zero Set, Carry Clear
900; DS,ES,BP preserved, others destroyed
901
902 procedure Build_device_ent,near
903 DOSAssume CS,<ES,DS>,"Build_Device_Ent"
904
905 MOV AX," "
906 MOV DI,OFFSET DOSGROUP:DEVFCB+8 ; Point to extent field
907;
908; Fill dir_ext
909;
910 STOSW
911 STOSB ; Blank out extent field
912 MOV AL,attr_device
913;
914; Fill Dir_attr
915;
916 STOSB ; Set attribute field
917 XOR AX,AX
918 MOV CX,10
919;
920; Fill dir_pad
921;
922 REP STOSW ; Fill rest with zeros
923 invoke DATE16
924 MOV DI,OFFSET DOSGROUP:DEVFCB+dir_time
925 XCHG AX,DX
926;
927; Fill dir_time
928;
929 STOSW
930 XCHG AX,DX
931;
932; Fill dir_date
933;
934 STOSW
935 MOV SI,DI ; SI points to dir_first field
936 MOV AX,WORD PTR [DEVPT]
937;
938; Fill dir_first
939;
940 STOSW ; Dir_first points to device
941 MOV AX,WORD PTR [DEVPT+2]
942;
943; Fill dir_size_l
944;
945 STOSW
946 MOV AH,BH ; Put device atts in AH
947 MOV BX,OFFSET DOSGROUP:DEVFCB
948 XOR AL,AL ; Set zero, clear carry
949 return
950EndProc Build_device_ent
951
952Break <ValidateCDS - given a CDS, validate the media and the current directory>
953
954;
955; ValidateCDS - Get current CDS. Splice it. Call FatReadCDS to check
956; media. If media has been changed, do DOS_Chdir to validate path. If
957; invalid, reset original CDS to root.
958;
959; Inputs: ThisCDS points to CDS of interest
960; SS:DI points to temp buffer
961; Outputs: The current directory string is validated on the appropriate
962; drive
963; ThisDPB changed
964; ES:DI point to CDS
965; Carry set if error (currently user FAILed to I 24)
966; Registers modified: all
967
968Procedure ValidateCDS,NEAR
969 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
970Public DIR2001S,DIR2001E
971DIR2001S:
972 LocalVar Temp,WORD
973 LocalVar SaveCDS,DWORD
974DIR2001E:
975 Enter
976 MOV Temp,DI
977 LDS SI,ThisCDS
978 MOV SaveCDSL,SI
979 MOV SaveCDSH,DS
980 EnterCrit critDisk
981 TEST [SI].curdir_flags,curdir_isnet ; Clears carry
982 JZ DoSplice
983 JMP FatFail
984DoSplice:
985 XOR DL,DL
986 XCHG DL,NoSetDir
987 Context ES
988 Invoke FStrcpy
989 MOV SI,Temp
990 Context DS
991 Invoke Splice
992 ASSUME DS:NOTHING
993 Context DS ; FatReadCDS (ThisCDS);
994 MOV NoSetDir,DL
995 LES DI,ThisCDS
996 SaveReg <BP>
997 Invoke FatRead_CDS
998 RestoreReg <BP>
999 JC FatFail
1000 LDS SI,ThisCDS ; if (ThisCDS->ID == -1) {
1001 ASSUME DS:NOTHING
1002 CMP [SI].curdir_ID,-1
1003 JNZ RestoreCDS
1004 Context ES
1005 SaveReg <wfp_Start> ; t = wfp_Start;
1006 CMP SI,SaveCDSL ; if not spliced
1007 JNZ DoChdir
1008 MOV DI,Temp
1009 MOV wfp_Start,DI ; wfp_start = d;
1010 Invoke FStrCpy ; strcpy (d, ThisCDS->Text);
1011DoChdir:
1012 Context DS
1013 SaveReg <<WORD PTR SAttrib>,BP> ; c = DOSChDir ();
1014 Invoke DOS_ChDir
1015 RestoreReg <BP,BX,wfp_start> ; wfp_Start = t;
1016 MOV SAttrib,BL
1017 LDS SI,SaveCDS
1018 ASSUME DS:NOTHING
1019 JNC SetCluster ; if (c == -1) {
1020 MOV WORD PTR ThisCDS,SI ; ThisCDS = TmpCDS;
1021 MOV WORD PTR ThisCDS+2,DS
1022 XOR CX,CX ; TmpCDS->text[3] = c = 0;
1023 MOV [SI+3],CL ; }
1024SetCluster:
1025 MOV [SI].curdir_ID,-1 ; TmpCDS->ID = -1;
1026 LDS SI,ThisCDS ; ThisCDS->ID = c;
1027 TEST [SI].curdir_flags,curdir_splice ;AN000;;MS. for Join and Subst
1028 JZ setdirclus ;AN000;;MS.
1029 MOV CX,-1 ;AN000;;MS.
1030setdirclus:
1031 MOV [SI].curdir_ID,CX ; }
1032RestoreCDS:
1033 LES DI,SaveCDS
1034 MOV WORD PTR ThisCDS,DI
1035 MOV WORD PTR ThisCDS+2,ES
1036 CLC
1037FatFail:
1038 LeaveCrit critDisk
1039 LES DI,SaveCDS
1040 Leave
1041 return
1042EndProc ValidateCDS
1043
1044Break <CheckThisDevice - Check for being a device>
1045
1046;
1047; CheckThisDevice - Examine the area at DS:SI to see if there is a valid
1048; device specified. We will return carry if there is a device present. The
1049; forms of devices we will recognize are:
1050;
1051; [path]device
1052;
1053; Note that the drive letter has *already* been removed. All other forms
1054; are not considered to be devices. If such a device is found we change the
1055; source pointer to point to the device component.
1056;
1057; Inputs: ES is DOSGroup
1058; DS:SI contains name
1059; Outputs: ES is DOSGroup
1060; DS:SI point to name or device
1061; Carry flag set if device was found
1062; Carry flag reset otherwise
1063; Registers Modified: all except ES:DI, DS
1064
1065if FALSE
1066Procedure CheckThisDevice,NEAR
1067 DOSAssume CS,<ES>,"CheckThisDevice"
1068 ASSUME DS:NOTHING
1069 SaveReg <DI,SI>
1070;
1071; Advance to after the final path character.
1072;
1073 MOV DI,SI ; remember first character
1074PathSkip:
1075 LODSB
1076 OR AL,AL
1077 JZ FoundEnd
1078 IF DBCS ;AN000;
1079 invoke Testkanj ;AN000;; 2/13/KK
1080 jz Notkanje ;AN000;; 2/13/KK
1081 lodsb ;AN000;; 2/13/KK
1082 or al,al ;AN000;; Skip second byte 2/13/KK removed
1083 jz FoundEnd ;AN000;; 2/13/KK removed
1084 jmp Short Pathskip ;AN000;; Ignore missing second byte for now.
1085NotKanje: ;AN000;
1086 ENDIF ;AN000;
1087;kanji load of next char too 2/13/KK
1088IF Kanji
1089 kanji load of next char too
1090ENDIF
1091 invoke PathChrCmp ; is it a path char?
1092 JNZ PathSkip
1093 MOV DI,SI
1094 JMP PathSkip
1095FoundEnd:
1096 MOV SI,DI
1097;
1098; Parse the name
1099;
1100 SaveReg <DS,SI> ; preserve the source pointer
1101 invoke NameTrans ; advance DS:SI
1102 CMP BYTE PTR [SI],0 ; parse entire string?
1103 STC ; simulate a Carry return from DevName
1104 JNZ SkipSearch ; no parse. simulate a file return.
1105 Context DS
1106 Invoke DevName
1107 ASSUME DS:NOTHING
1108SkipSearch:
1109 RestoreReg <SI,DS>
1110;
1111; DS:SI points to the beginning of the potential device. If we have a device
1112; then we do not change SI. If we have a file, then we reset SI back to the
1113; original value. At this point Carry set indicates FILE.
1114;
1115 RestoreReg <DI> ; get original SI
1116 JNC CheckDone ; if device then do not reset pointer
1117 MOV SI,DI
1118CheckDone:
1119 RestoreReg <DI>
1120 CMC ; invert carry. Carry => device
1121 return
1122else
1123Procedure CheckThisDevice,NEAR
1124 DOSAssume CS,<ES>,"CheckThisDevice"
1125 ASSUME DS:NOTHING
1126 SaveReg <DI,SI>
1127 MOV DI,SI
1128;
1129; Check for presence of \dev\ (Dam multiplan!)
1130;
1131 MOV AL,[SI]
1132 Invoke PathChrCmp ; is it a path char?
1133 JNZ ParseDev ; no, go attempt to parse device
1134 INC SI ; simulate LODSB
1135;
1136; We have the leading path separator. Look for DEV part.
1137;
1138 LODSW
1139 OR AX,2020h
1140 CMP AX,"e" SHL 8 + "d"
1141 JNZ NotDevice ; not "de", assume not device
1142 LODSB
1143 OR AL,20h
1144 CMP AL,"v" ; Not "v", assume not device
1145 JNZ NotDevice
1146 LODSB
1147 invoke PathChrCmp ; do we have the last path separator?
1148 JNZ NotDevice ; no. go for it.
1149;
1150; DS:SI now points to a potential drive. Preserve them as NameTrans advances
1151; SI and DevName may destroy DS.
1152;
1153ParseDev:
1154 SaveReg <DS,SI> ; preserve the source pointer
1155 invoke NameTrans ; advance DS:SI
1156 CMP BYTE PTR [SI],0 ; parse entire string?
1157 STC ; simulate a Carry return from DevName
1158 JNZ SkipSearch ; no parse. simulate a file return.
1159 Context DS
1160 Invoke DevName
1161 ASSUME DS:NOTHING
1162SkipSearch:
1163 RestoreReg <SI,DS>
1164;
1165; SI points to the beginning of the potential device. If we have a device
1166; then we do not change SI. If we have a file, then we reset SI back to the
1167; original value. At this point Carry set indicates FILE.
1168;
1169CheckReturn:
1170 RestoreReg <DI> ; get original SI
1171 JNC CheckDone ; if device then do not reset pointer
1172 MOV SI,DI
1173CheckDone:
1174 RestoreReg <DI>
1175 CMC ; invert carry. Carry => device
1176 return
1177NotDevice:
1178 STC
1179 JMP CheckReturn
1180endif
1181
1182EndProc CheckThisDevice
1183
1184BREAK <LookupPath - call fastopen to get dir entry info>
1185
1186;
1187; Output DS:SI -> path name,
1188; ES:DI -> dir entry info buffer
1189; ES:CX -> extended dir info buffer
1190;
1191; carry flag clear : tables pointed by ES:DI and ES:CX are filled by
1192; FastOpen, DS:SI points to char just one after
1193; the last char of path name which is fully or
1194; partially found in FastOPen
1195; carry flag set : FastOpen not in memory or path name not found
1196;
1197 procedure LookupPath,NEAR
1198 ASSUME ES:NOTHING
1199
1200; PUSH AX
1201 TEST [FastOpenFlg],FastOpen_Set ; flg is set in DOSPEN
1202 JNZ FASTINST ; and this routine is
1203NOLOOK:
1204 JMP NOLOOKUP ; executed once
1205FASTINST:
1206 TEST [FastOpenFlg],No_Lookup ; no more lookup?
1207 JNZ NOLOOK ; yes
1208
1209 MOV BX,OFFSET DOSGROUP:FastOpenTable ; get fastopen related tab
1210 MOV SI,[Wfp_Start] ; si points to path name
1211 MOV DI,OFFSET DOSGROUP:Dir_Info_Buff
1212 MOV CX,OFFSET DOSGROUP:FastOpen_Ext_Info
1213 MOV AL,FONC_look_up ; al = 1
1214 PUSH DS
1215 POP ES
1216 CALL DWORD PTR [BX.FASTOPEN_NAME_CACHING] ;call fastopen
1217 JC NOTFOUND ; fastopen not in memory
1218
1219 LEA BX,[SI-2]
1220 CMP BX,[Wfp_Start] ; path found ?
1221 JZ NOTFOUND ; no
1222 ; fully or partially found
1223 CMP BYTE PTR [SI],0 ;AN000;FO.
1224 JNZ parfnd ;AN000;FO.; partiallyfound
1225 PUSH CX ;AN000;FO.; is attribute matched ?
1226 MOV CL,Attrib ;AN000;FO.;
1227 MOV CH,Sattrib ;AN000;FO.; attrib=sattrib
1228 MOV Attrib,CH ;AN000;FO.;
1229 MOV CH,ES:[DI.dir_attr] ;AN000;FO.;
1230 invoke Matchattributes ;AN000;FO.;
1231;;; MOV Attrib,CL ;AN001;FO.; retore attrib
1232 POP CX ;AN000;FO.;
1233 JNZ NOLOOKUP ;AN000;FO.; not matched
1234parfnd:
1235 MOV [Next_Element_Start],SI ; save si
1236 MOV BX,CX
1237 MOV AX,[BX.FEI_lastent] ;AN000;;FO. restore lastentry
1238 MOV [LASTENT],AX ;AN000;;FO.
1239 MOV AX,[BX.FEI_dirstart] ;AN001;;FO. restore dirstart
1240 MOV [DIRSTART],AX ;AN001;;FO.
1241 MOV AX,[BX.FEI_clusnum] ; restore next cluster num
1242 MOV [CLUSNUM],AX ;
1243
1244 PUSH ES ; save ES
1245 LES BX,[THISDPB] ; put drive id
1246 MOV AH,ES:[BX.dpb_drive] ; in AH for DOOPEN
1247 POP ES ; pop ES
1248
1249 MOV WORD PTR [CURBUF+2],ES ; [curbuf+2].bx points to
1250 MOV BX,DI ; start of entry
1251 LEA SI,[DI.dir_first] ; [curbuf+2]:si points to
1252 ; dir_first field in the
1253 ; dir entry
1254 OR [FastOpenFlg],Lookup_Success + set_for_search
1255; POP AX
1256 RET
1257NOTFOUND:
1258 CMP AX,-1 ; not in memory ?
1259 JNZ Partial_Success ; yes, in memory
1260 MOV [FastOpenFlg],0 ; no more fastopen
1261Partial_Success:
1262 AND [FastOpenFlg],Special_Fill_Reset
1263NOLOOKUP:
1264; POP AX
1265 STC
1266 RET
1267EndProc LookupPath
1268
1269BREAK <InsertPath - call fastopen to insert dir entry info>
1270
1271;
1272; Input: FastOpen_Set flag set when from DOSOPEN otherwise 0
1273; Lookup_Success flag set when got dir entry info from FASTOPEN
1274; DS = DOSGROUP
1275; Output: FastOPen_Ext_Info is set and path dir info is inserted
1276;
1277 procedure InsertPath,NEAR
1278 ASSUME ES:NOTHING
1279
1280 PUSHF
1281 TEST [FastOpenFlg],FastOpen_Set ;only DOSOPEN can take advantage of
1282 JZ GET_NEXT_ELEMENT ; the FastOpen
1283 TEST [FastOpenFlg],Lookup_Success ; Lookup just happened
1284 JZ INSERT_DIR_INFO ; no
1285 AND [FastOpenFlg],Lookup_Reset ; we got dir info from fastopen so
1286 MOV DI,[Next_Element_Start] ; no need to insert it again
1287 JMP GET_NEXT2
1288INSERT_DIR_INFO: ; save registers
1289 PUSH DS
1290 PUSH ES
1291 PUSH BX
1292 PUSH SI
1293 PUSH DI
1294 PUSH CX
1295 PUSH AX
1296; int 3
1297 LDS DI,[CURBUF] ; DS:DI -> buffer header
1298ASSUME DS:NOTHING
1299 MOV SI,OFFSET DOSGROUP:FastOpen_Ext_Info
1300 MOV AX,WORD PTR [DI.buf_sector] ; get directory sector
1301 MOV WORD PTR CS:[SI.FEI_dirsec],AX ;AN000; >32mb save dir sector
1302 MOV AX,WORD PTR [DI.buf_sector+2] ;AN000; >32mb
1303 context DS
1304 MOV WORD PTR [SI.FEI_dirsec+2],AX ;AN000;>32mb save high dir sector
1305 MOV AX,[CLUSNUM] ; save next cluster number
1306 MOV [SI.FEI_clusnum],AX
1307 MOV AX,[LASTENT] ;AN000;FO. save lastentry for search first
1308 MOV [SI.FEI_lastent],AX ;AN000;FO.
1309 MOV AX,[DIRSTART] ;AN001;FO. save for search first
1310 MOV [SI.FEI_dirstart],AX ;AN001;FO.
1311
1312 MOV AX,BX
1313 ADD DI,BUFINSIZ ; DS:DI -> start of data in buffer
1314 SUB AX,DI ; AX=BX relative to start of sector
1315 MOV CL,SIZE dir_entry
1316;invoke debug_DOS
1317 DIV CL
1318 MOV [SI.FEI_dirpos],AL ; save directory entry # in buffer
1319
1320 PUSH DS
1321 POP ES
1322
1323 MOV DS,WORD PTR [CURBUF+2]
1324 MOV DI,BX ; DS:DI -> dir entry info
1325ASSUME DS:NOTHING
1326 CMP DS:[DI.dir_first],0 ; never insert info when file is empty
1327 JZ SKIP_INSERT ; e.g. newly created file
1328
1329 PUSH SI ; ES:BX -> extended info
1330 POP BX
1331
1332 MOV AL,FONC_insert ; call fastopen insert operation
1333 MOV SI,OFFSET DOSGROUP:FastOpenTable
1334 CALL DWORD PTR ES:[SI.FASTOPEN_NAME_CACHING]
1335
1336 CLC
1337SKIP_INSERT:
1338 POP AX
1339 POP CX ; restore registers
1340 POP DI
1341 POP SI
1342 POP BX
1343 POP ES
1344 POP DS
1345GET_NEXT2:
1346 OR [FastOpenFlg],No_Lookup ; we got dir info from fastopen so
1347GET_NEXT_ELEMENT:
1348 POPF
1349 RET
1350EndProc InsertPath
1351
1352CODE ENDS
1353 END
diff --git a/v4.0/src/DOS/DIRCALL.ASM b/v4.0/src/DOS/DIRCALL.ASM
new file mode 100644
index 0000000..3c79fe0
--- /dev/null
+++ b/v4.0/src/DOS/DIRCALL.ASM
@@ -0,0 +1,415 @@
1; SCCSID = @(#)dircall.asm 1.1 85/04/10
2; SCCSID = @(#)dircall.asm 1.1 85/04/10
3TITLE DIRCALL - Directory manipulation internal calls
4NAME DIRCALL
5; Low level directory manipulation routines for making removing and
6; verifying local or NET directories
7;
8; DOS_MKDIR
9; DOS_CHDIR
10; DOS_RMDIR
11;
12; Modification history:
13;
14; Created: ARR 30 March 1983
15;
16
17;
18; get the appropriate segment definitions
19;
20.xlist
21include dosseg.asm
22
23CODE SEGMENT BYTE PUBLIC 'CODE'
24 ASSUME SS:DOSGROUP,CS:DOSGROUP
25
26.xcref
27INCLUDE DOSSYM.INC
28INCLUDE DEVSYM.INC
29INCLUDE FASTOPEN.INC
30INCLUDE FASTXXXX.INC
31.cref
32.list
33
34Installed = TRUE
35
36 i_need THISSFT,DWORD
37 i_need THISCDS,DWORD
38 i_need NoSetDir,BYTE
39 i_need CURBUF, DWORD
40 i_need DIRSTART,WORD
41 i_need THISDPB,DWORD
42 i_need NAME1,BYTE
43 i_need LASTENT,WORD
44 i_need SATTRIB,BYTE
45 i_need ATTRIB,BYTE
46 i_need ALLOWED,BYTE
47 i_need FAILERR,BYTE
48 i_need RenBuf,BYTE
49 i_need FastOpenFlg,BYTE ; DOS 3.3
50 i_need FastOpenTable,BYTE ; DOS 3.3
51 i_need WFP_START,WORD ; DOS 3.3
52 i_need HIGH_SECTOR,WORD ; F.C. >32mb
53
54BREAK <DOS_MkDir - Make a directory entry>
55
56; Inputs:
57; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
58; terminated)
59; [CURR_DIR_END] Points to end of Current dir part of string
60; ( = -1 if current dir not involved, else
61; Points to first char after last "/" of current dir part)
62; [THISCDS] Points to CDS being used
63; (Low word = -1 if NUL CDS (Net direct request))
64; Function:
65; Make a new directory
66; Returns:
67; Carry Clear
68; No error
69; Carry Set
70; AX is error code
71; error_path_not_found
72; Bad path (not in curr dir part if present)
73; error_bad_curr_dir
74; Bad path in current directory part of path
75; error_access_denied
76; Already exists, device name
77; DS preserved, Others destroyed
78
79 procedure DOS_MKDIR,NEAR
80 DOSAssume CS,<DS>,"DOS_MkDir"
81 ASSUME ES:NOTHING
82
83 Invoke TestNet
84 JNC local_mkdir
85IF NOT Installed
86 transfer NET_MKDIR
87ELSE
88 MOV AX,(multNET SHL 8) OR 3
89 INT 2FH
90 return
91ENDIF
92
93NODEACCERRJ:
94 MOV AX,error_access_denied
95BadRet:
96 STC
97 LeaveCrit critDisk
98 return
99
100PATHNFJ:
101 LeaveCrit critDisk
102 transfer SET_MKND_ERR ; Map the MakeNode error and return
103
104LOCAL_MKDIR:
105 EnterCrit critDisk
106;
107; MakeNode requires an SFT to fiddle with. We Use a temp spot (RENBUF)
108;
109 MOV WORD PTR [THISSFT+2],SS
110 MOV WORD PTR [THISSFT],OFFSET DOSGroup:RenBuf
111;
112; NOTE: Need WORD PTR because MASM takes type of
113; TempSFT (byte) instead of type of sf_mft (word).
114;
115 MOV WORD PTR RenBuf.sf_mft,0 ; make sure SHARER won't complain.
116 MOV AL,attr_directory
117 invoke MAKENODE
118
119 JC PATHNFJ
120 CMP AX,3
121 JZ NODEACCERRJ ; Can't make a device into a directory
122 LES BP,[THISDPB] ; Makenode zaps this
123 LDS DI,[CURBUF]
124ASSUME DS:NOTHING
125 SUB SI,DI
126 PUSH SI ; Pointer to dir_first
127 PUSH WORD PTR [DI.buf_sector+2] ;F.C. >32mb
128
129 PUSH WORD PTR [DI.buf_sector] ; Sector of new node
130 context DS
131 PUSH [DIRSTART] ; Parent for .. entry
132 XOR AX,AX
133 MOV [DIRSTART],AX ; Null directory
134 invoke NEWDIR
135 JC NODEEXISTSPOPDEL ; No room
136 invoke GETENT ; First entry
137 JC NODEEXISTSPOPDEL ; Screw up
138 LES DI,[CURBUF]
139
140 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
141 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
142 invoke INC_DIRTY_COUNT ;LB. ;AN000;
143 OR ES:[DI.buf_flags],buf_dirty
144yesdirty:
145 ADD DI,BUFINSIZ ; Point at buffer
146 MOV AX,202EH ; ". "
147 MOV DX,[DIRSTART] ; Point at itself
148 invoke SETDOTENT
149 MOV AX,2E2EH ; ".."
150 POP DX ; Parent
151 invoke SETDOTENT
152 LES BP,[THISDPB]
153 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
154 POP DX ; Entry sector
155 POP [HIGH_SECTOR] ;F.C. >32mb
156
157 XOR AL,AL ; Pre read
158 invoke GETBUFFR
159 JC NODEEXISTSP
160 MOV DX,[DIRSTART]
161 LDS DI,[CURBUF]
162ASSUME DS:NOTHING
163 OR [DI.buf_flags],buf_isDIR
164 POP SI ; dir_first pointer
165 ADD SI,DI
166 MOV [SI],DX
167 XOR DX,DX
168 MOV [SI+2],DX ; Zero size
169 MOV [SI+4],DX
170DIRUP:
171 TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
172 JNZ yesdirty2 ;LB. don't increment dirty count ;AN000;
173 invoke INC_DIRTY_COUNT ;LB. ;AN000;
174 OR [DI.buf_flags],buf_dirty ; Dirty buffer
175yesdirty2:
176 context DS
177 MOV AL,ES:[BP.dpb_drive]
178 invoke FLUSHBUF
179 MOV AX,error_access_denied
180 LeaveCrit critDisk
181 return
182
183NODEEXISTSPOPDEL:
184 POP DX ; Parent
185 POP DX ; Entry sector
186 POP [HIGH_SECTOR] ; F.C. >32mb
187
188 LES BP,[THISDPB]
189 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
190 XOR AL,AL ; Pre read
191 invoke GETBUFFR
192 JC NODEEXISTSP
193 LDS DI,[CURBUF]
194ASSUME DS:NOTHING
195 OR [DI.buf_flags],buf_isDIR
196 POP SI ; dir_first pointer
197 ADD SI,DI
198 SUB SI,dir_first ;Point back to start of dir entry
199 MOV BYTE PTR [SI],0E5H ; Free the entry
200 CALL DIRUP ; Error doesn't matter since erroring anyway
201NODEEXISTS:
202 JMP NODEACCERRJ
203
204NODEEXISTSP:
205 POP SI ; Clean stack
206 JMP NODEEXISTS
207
208EndProc DOS_MKDIR
209
210BREAK <DOS_ChDir -- Verify a directory>
211
212; Inputs:
213; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
214; terminated)
215; [CURR_DIR_END] Points to end of Current dir part of string
216; ( = -1 if current dir not involved, else
217; Points to first char after last "/" of current dir part)
218; [THISCDS] Points to CDS being used May not be NUL
219; Function:
220; Validate the path for potential new current directory
221; Returns:
222; NOTE:
223; [SATTRIB] is modified by this call
224; Carry Clear
225; CX is cluster number of the DIR, LOCAL CDS ONLY
226; Caller must NOT set ID fields on a NET CDS.
227; Carry Set
228; AX is error code
229; error_path_not_found
230; Bad path
231; error_access_denied
232; device or file name
233; DS preserved, Others destroyed
234
235 procedure DOS_CHDIR,NEAR
236 DOSAssume CS,<DS>,"DOS_Chdir"
237 ASSUME ES:NOTHING
238
239 Invoke TestNet
240 JNC LOCAL_CHDIR
241IF NOT Installed
242 transfer NET_CHDIR
243ELSE
244 MOV AX,(multNET SHL 8) OR 5
245 INT 2FH
246 return
247ENDIF
248
249LOCAL_CHDIR:
250 EnterCrit critDisk
251 TEST ES:[DI.curdir_flags],curdir_splice ;PTM.
252 JZ nojoin ;PTM.
253 MOV ES:[DI.curdir_ID],0FFFFH ;PTM.
254nojoin:
255 MOV [NoSetDir],FALSE
256 MOV [SATTRIB],attr_directory+attr_system+attr_hidden
257 ; Dir calls can find these
258; DOS 3.3 6/24/86 FastOpen
259
260 OR [FastOpenFlg],FastOpen_Set ; set fastopen flag
261 invoke GetPath
262 PUSHF ;AN000;
263 AND [FastOpenFlg],Fast_yes ; clear it all ;AC000;
264 POPF ;AN000;
265; DOS 3.3 6/24/86 FastOpen
266 MOV AX,error_path_not_found
267 JC ChDirDone
268 JNZ NOTDIRPATH ; Path not a DIR
269 MOV CX,[DIRSTART] ; Get cluster number
270 CLC
271ChDirDone:
272 LeaveCrit critDisk
273 return
274
275EndProc DOS_CHDIR
276
277BREAK <DOS_RmDir -- Remove a directory>
278
279; Inputs:
280; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
281; terminated)
282; [CURR_DIR_END] Points to end of Current dir part of string
283; ( = -1 if current dir not involved, else
284; Points to first char after last "/" of current dir part)
285; [THISCDS] Points to CDS being used
286; (Low word = -1 if NUL CDS (Net direct request))
287; Function:
288; Remove a directory
289; NOTE: Attempt to remove current directory must be detected by caller
290; Returns:
291; NOTE:
292; [SATTRIB] is modified by this call
293; Carry Clear
294; No error
295; Carry Set
296; AX is error code
297; error_path_not_found
298; Bad path (not in curr dir part if present)
299; error_bad_curr_dir
300; Bad path in current directory part of path
301; error_access_denied
302; device or file name, root directory
303; Bad directory ('.' '..' messed up)
304; DS preserved, Others destroyed
305
306 procedure DOS_RMDIR,NEAR
307 DOSAssume CS,<DS>,"DOS_RmDir"
308 ASSUME ES:NOTHING
309
310 Invoke TestNet
311 JNC Local_RmDIR
312IF NOT Installed
313 transfer NET_RMDIR
314ELSE
315 MOV AX,(multNET SHL 8) OR 1
316 INT 2FH
317 return
318ENDIF
319
320LOCAL_RMDIR:
321 EnterCrit critDisk
322 MOV [NoSetDir],0
323 MOV [SATTRIB],attr_directory+attr_system+attr_hidden
324 ; Dir calls can find these
325 invoke GetPath
326 JC NOPATH ; Path not found
327 JNZ NOTDIRPATH ; Path not a DIR
328 MOV DI,[DIRSTART]
329 OR DI,DI ; Root ?
330 JNZ rmdir_get_buf ; No
331 JMP SHORT NOTDIRPATH
332
333NOPATH:
334 MOV AX,error_path_not_found
335 JMP BadRet
336
337NOTDIRPATHPOP:
338 POP AX ;F.C. >32mb
339 POP AX
340NOTDIRPATHPOP2:
341 POP AX
342NOTDIRPATH:
343 JMP NodeAccErrJ
344
345rmdir_get_buf:
346 LDS DI,[CURBUF]
347ASSUME DS:NOTHING
348 SUB BX,DI ; Compute true offset
349 PUSH BX ; Save entry pointer
350 PUSH WORD PTR [DI.buf_sector+2] ;F.C. >32mb
351 PUSH WORD PTR [DI.buf_sector] ; Save sector number
352 context DS
353 context ES
354 MOV DI,OFFSET DOSGROUP:NAME1
355 MOV AL,'?'
356 MOV CX,11
357 REP STOSB
358 XOR AL,AL
359 STOSB ; Nul terminate it
360 invoke STARTSRCH ; Set search
361 invoke GETENTRY ; Get start of directory
362 JC NOTDIRPATHPOP ; Screw up
363 MOV DS,WORD PTR [CURBUF+2]
364ASSUME DS:NOTHING
365 MOV SI,BX
366 LODSW
367 CMP AX,(' ' SHL 8) OR '.' ; First entry '.'?
368 JNZ NOTDIRPATHPOP ; Nope
369 ADD SI,(SIZE dir_entry) - 2 ; Next entry
370 LODSW
371 CMP AX,('.' SHL 8) OR '.' ; Second entry '..'?
372 JNZ NOTDIRPATHPOP ; Nope
373 context DS
374 MOV [LASTENT],2 ; Skip . and ..
375 invoke GETENTRY ; Get next entry
376 JC NOTDIRPATHPOP ; Screw up
377 MOV [ATTRIB],attr_directory+attr_hidden+attr_system
378 invoke SRCH ; Do a search
379 JNC NOTDIRPATHPOP ; Found another entry!
380 CMP [FAILERR],0
381 JNZ NOTDIRPATHPOP ; Failure of search due to I 24 FAIL
382 LES BP,[THISDPB]
383 MOV BX,[DIRSTART]
384;; FastSeek 10/27/86
385 invoke Delete_FSeek ; delete the fastseek entry
386;; FastSeek 10/27/86
387 invoke RELEASE ; Release data in sub dir
388 JC NOTDIRPATHPOP ; Screw up
389 POP DX ; Sector # of entry
390 POP [HIGH_SECTOR] ; F.C. >32mb
391
392 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
393 XOR AL,AL ; Pre read
394 invoke GETBUFFR ; Get sector back
395 JC NOTDIRPATHPOP2 ; Screw up
396 LDS DI,[CURBUF]
397ASSUME DS:NOTHING
398 OR [DI.buf_flags],buf_isDIR
399 POP BX ; Pointer to start of entry
400 ADD BX,DI ; Corrected
401 MOV BYTE PTR [BX],0E5H ; Free the entry
402
403;DOS 3.3 FastOpen 6/16/86 F.C.
404 PUSH DS
405 context DS
406 invoke FastOpen_Delete ; call fastopen to delete an entry
407 POP DS
408;DOS 3.3 FastOpen 6/16/86 F.C.
409
410 JMP DIRUP ; In MKDIR, dirty buffer and flush
411
412EndProc DOS_RMDIR
413
414CODE ENDS
415 END
diff --git a/v4.0/src/DOS/DISK.ASM b/v4.0/src/DOS/DISK.ASM
new file mode 100644
index 0000000..2fad68b
--- /dev/null
+++ b/v4.0/src/DOS/DISK.ASM
@@ -0,0 +1,1073 @@
1; SCCSID = @(#)disk.asm 1.1 85/04/10
2; SCCSID = @(#)disk.asm 1.1 85/04/10
3TITLE DISK - Disk utility routines
4NAME Disk
5; Low level Read and write routines for local SFT I/O on files and devs
6;
7; SWAPCON
8; SWAPBACK
9; DOS_READ
10; DOS_WRITE
11; get_io_sft
12; DirRead
13; FIRSTCLUSTER
14; SET_BUF_AS_DIR
15; FATSecRd
16; DREAD
17; CHECK_WRITE_LOCK
18; CHECK_READ_LOCK
19;
20; Revision history:
21;
22; A000 version 4.00 Jan. 1988
23;
24
25;
26; get the appropriate segment definitions
27;
28.xlist
29include dosseg.asm
30include fastseek.inc ;AN000;
31include fastxxxx.inc ;AN000;
32
33CODE SEGMENT BYTE PUBLIC 'CODE'
34 ASSUME SS:DOSGROUP,CS:DOSGROUP
35
36.xcref
37INCLUDE DOSSYM.INC
38INCLUDE DEVSYM.INC
39include version.inc
40.cref
41.list
42
43Installed = TRUE
44
45 I_need DirStart,WORD
46 I_Need CONSft,DWORD ; SFT for swapped console In/Out
47 i_need CONSWAP,BYTE
48 i_need IDLEINT,BYTE
49 i_need THISSFT,DWORD
50 i_need DMAADD,DWORD
51 i_need DEVCALL,BYTE
52 i_need CALLSCNT,WORD
53 i_need CALLXAD,DWORD
54 i_need CONTPOS,WORD
55 i_need NEXTADD,WORD
56 i_need CONBUF,BYTE
57 i_need ClusFac,BYTE
58 i_need SecClusPos,BYTE
59 i_need DirSec,DWORD ;AN000;
60 i_need ClusNum,WORD
61 i_need NxtClusNum,WORD
62 i_need ReadOp,BYTE
63 i_need CURBUF,DWORD
64 i_need ALLOWED,BYTE
65 i_need EXTERR_LOCUS,BYTE
66 i_need FastSeekflg,BYTE ;AN000;
67 i_need HIGH_SECTOR,WORD ;AN000;
68 I_need JShare,DWORD ;AN000;
69 i_need DOS34_FLAG,WORD ;AN000;
70
71IF BUFFERFLAG
72
73 i_need BUF_EMS_MODE,BYTE
74 i_need BUF_EMS_LAST_PAGE,BYTE
75 I_need BUF_EMS_FIRST_PAGE,DWORD
76 I_need BUF_EMS_SAFE_FLAG,BYTE
77 I_need BUF_EMS_NPA640,WORD
78 I_need BUF_EMS_PAGE_FRAME,WORD
79 I_need BUF_EMS_PFRAME,WORD
80 I_need LASTBUFFER,DWORD
81
82 extrn save_user_map:near
83 extrn restore_user_map:near
84 extrn Setup_EMS_Buffers:near
85
86ENDIF
87
88Break <SwapCon, Swap Back - Old-style I/O to files>
89; * * * * Drivers for file input from devices * * * *
90
91; Indicate that ther is no more I/O occurring through another SFT outside of
92; handles 0 and 1
93;
94; Inputs: DS is DOSGroup
95; Outputs: CONSWAP is set to false.
96; Registers modified: none
97
98 procedure SWAPBACK,NEAR
99 DOSAssume CS,<DS>,"SwapBack"
100 ASSUME ES:NOTHING
101 MOV BYTE PTR [CONSWAP],0 ; signal no conswaps
102 return
103EndProc SWAPBACK
104
105; Copy ThisSFT to CONSFT for use by the 1-12 primitives.
106;
107; Inputs: ThisSFT as the sft of the desired file
108; DS is DOSGroup
109; Outputs: CONSWAP is set. CONSFT = ThisSFT.
110; Registers modified: none
111 procedure SWAPCON,NEAR
112 DOSAssume CS,<DS>,"SwapCon"
113 ASSUME ES:NOTHING
114 SaveReg <ES,DI>
115 MOV BYTE PTR [CONSWAP],1 ; CONSwap = TRUE;
116 LES DI,ThisSFT
117 Assert ISSFT,<ES,DI>,"SwapCon"
118 MOV WORD PTR CONSFT,DI
119 MOV WORD PTR CONSFT+2,ES
120 RestoreReg <DI,ES>
121 return
122EndProc SWAPCON
123
124Break <DOS_READ -- MAIN READ ROUTINE AND DEVICE IN ROUTINES>
125
126;
127; Inputs:
128; [THISSFT] set to the SFT for the file being used
129; [DMAADD] contains transfer address
130; CX = No. of bytes to read
131; Function:
132; Perform read operation
133; Outputs:
134; Carry clear
135; SFT Position and cluster pointers updated
136; CX = No. of bytes read
137; ES:DI point to SFT
138; Carry set
139; AX is error code
140; CX = 0
141; ES:DI point to SFT
142; DS preserved, all other registers destroyed
143
144 procedure DOS_READ,NEAR
145 DOSAssume CS,<DS>,"DOS_Read"
146 ASSUME ES:NOTHING
147
148IF BUFFERFLAG
149 cmp [BUF_EMS_MODE], -1
150 jz dos_rd_call
151 call choose_buf_page
152 jnc sav_map_rd_hndl
153 return
154sav_map_rd_hndl:
155; call save_user_map
156dos_rd_call:
157ENDIF
158
159
160 LES DI,[THISSFT]
161 Assert ISSFT,<ES,DI>,"DOS_Read"
162;
163; Verify that the sft has been opened in a mode that allows reading.
164;
165 MOV AL,BYTE PTR ES:[DI.sf_mode]
166 AND AL,access_mask
167 CMP AL,open_for_write
168 JNE READ_NO_MODE ;Is read or both
169 transfer SET_ACC_ERR
170
171READ_NO_MODE:
172 invoke SETUP
173 JCXZ NoIORet ; no bytes to read - fast return
174 invoke IsSFTNet
175 JZ LOCAL_READ
176
177; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ?
178; JZ IFS_HAS_SHARE ;AN000;;IFS. yes
179; EnterCrit critDisk ;AN000;;IFS. enter critical section
180; CALL CHECK_READ_LOCK ;AN000;;IFS. check read lock
181; JNC READ_OK2 ;AN000;;IFS. lock check ok
182; JMP SHORT critexit ;AN000;;IFS. fail
183READ_OK2: ;AN000;
184; LeaveCrit critDisk ;AN000;;IFS. leave critical section
185IFS_HAS_SHARE: ;AN000;
186
187IF NOT Installed
188 transfer NET_READ
189ELSE
190 MOV AX,(multNET SHL 8) OR 8
191 INT 2FH
192 return
193ENDIF
194
195;
196; The user ended up requesting 0 bytes of input. We do nothing for this case
197; except return immediately.
198;
199NoIORet:
200 CLC
201 return
202
203LOCAL_READ:
204 TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O
205 JNZ READDEV
206 MOV [EXTERR_LOCUS],errLOC_Disk
207 EnterCrit critDisk
208 TEST [FastSeekflg],Fast_yes ; FastSeek installed ?
209 JZ FS_no ; no
210 OR [FastSeekflg],FS_begin ; set fastseek mode
211FS_no:
212 invoke DISKREAD
213 PUSHF ; save flag
214 AND CS:[FastSeekflg],FS_end ; reset fastseek mode
215 POPF ; retore flag
216critexit:
217 LeaveCrit critDisk
218 return
219
220;
221; We are reading from a device. Examine the status of the device to see if we
222; can short-circuit the I/O. If the device in the EOF state or if it is the
223; null device, we can safely indicate no transfer.
224;
225READDEV:
226 DOSAssume CS,<DS>,"DISK/ReadDev"
227 ASSUME ES:NOTHING
228 MOV [EXTERR_LOCUS],errLOC_SerDev
229 MOV BL,BYTE PTR ES:[DI.sf_flags]
230 LES DI,[DMAADD]
231 TEST BL,devid_device_EOF ; End of file?
232 JZ ENDRDDEVJ3
233 TEST BL,devid_device_null ; NUL device?
234 JZ TESTRAW ; NO
235 XOR AL,AL ; Indicate EOF by setting zero
236ENDRDDEVJ3:
237 JMP ENDRDDEVJ2
238
239;
240; We need to hit the device. Figure out if we do a raw read or we do the
241; bizarre std_con_string_input.
242;
243TESTRAW:
244 TEST BL,devid_device_raw ; Raw mode?
245 JNZ DVRDRAW ; Yes, let the device do all local editing
246 TEST BL,devid_device_con_in ; Is it console device?
247 JZ NOTRDCON
248 JMP READCON
249
250DVRDRAW:
251 DOSAssume CS,<DS>,"DISK/DvRdRaw"
252 PUSH ES
253 POP DS ; Xaddr to DS:DI
254ASSUME DS:NOTHING
255ReadRawRetry:
256 MOV BX,DI ; DS:BX transfer addr
257 XOR AX,AX ; Media Byte, unit = 0
258 MOV DX,AX ; Start at 0
259 invoke SETREAD
260 PUSH DS ; Save Seg part of Xaddr
261 LDS SI,[THISSFT]
262 Assert ISSFT,<DS,SI>,"DOS_Read/DvRdRawR"
263 invoke DEVIOCALL
264 MOV DX,DI ; DS:DX is preserved by INT 24
265 MOV AH,86H ; Read error
266 MOV DI,[DEVCALL.REQSTAT]
267 TEST DI,STERR
268 JZ CRDROK ; No errors
269 invoke CHARHARD
270 MOV DI,DX ; DS:DI is Xaddr
271 OR AL,AL
272 JZ CRDROK ; Ignore
273 CMP AL,3
274 JZ CRDFERR ; fail.
275 POP DS ; Recover saved seg part of Xaddr
276 JMP ReadRawRetry ; Retry
277
278;
279; We have encountered a device-driver error. We have informed the user of it
280; and he has said for us to fail the system call.
281;
282CRDFERR:
283 POP DI ; Clean stack
284DEVIOFERR:
285 LES DI,[THISSFT]
286 Assert ISSFT,<ES,DI>,"DOS_Read/DEVIOFERR"
287 transfer SET_ACC_ERR_DS
288
289CRDROK:
290 POP DI ; Chuck saved seg of Xaddr
291 MOV DI,DX
292 ADD DI,[CALLSCNT] ; Amount transferred
293 JMP SHORT ENDRDDEVJ3
294
295; We are going to do a cooked read on some character device. There is a
296; problem here, what does the data look like? Is it a terminal device, line
297; CR line CR line CR, or is it file data, line CR LF line CR LF? Does it have
298; a ^Z at the end which is data, or is the ^Z not data? In any event we're
299; going to do this: Read in pieces up to CR (CRs included in data) or ^z (^z
300; included in data). this "simulates" the way con works in cooked mode
301; reading one line at a time. With file data, however, the lines will look
302; like, LF line CR. This is a little weird.
303
304NOTRDCON:
305 MOV AX,ES
306 MOV DS,AX
307ASSUME DS:NOTHING
308 MOV BX,DI
309 XOR DX,DX
310 MOV AX,DX
311 PUSH CX
312 MOV CX,1
313 invoke SETREAD
314 POP CX
315 LDS SI,[THISSFT]
316 Assert ISSFT,<DS,SI>,"DOS_Read/NotRdCon"
317 LDS SI,[SI.sf_devptr]
318DVRDLP:
319 invoke DSKSTATCHK
320 invoke DEVIOCALL2
321 PUSH DI ; Save "count" done
322 MOV AH,86H
323 MOV DI,[DEVCALL.REQSTAT]
324 TEST DI,STERR
325 JZ CRDOK
326 invoke CHARHARD
327 POP DI
328 MOV [CALLSCNT],1
329 CMP AL,1
330 JZ DVRDLP ;Retry
331 CMP AL,3
332 JZ DEVIOFERR ; FAIL
333 XOR AL,AL ; Ignore, Pick some random character
334 JMP SHORT DVRDIGN
335
336CRDOK:
337 POP DI
338 CMP [CALLSCNT],1
339 JNZ ENDRDDEVJ2
340 PUSH DS
341 MOV DS,WORD PTR [CALLXAD+2]
342 MOV AL,BYTE PTR [DI] ; Get the character we just read
343 POP DS
344DVRDIGN:
345 INC WORD PTR [CALLXAD] ; Next character
346 MOV [DEVCALL.REQSTAT],0
347 INC DI ; Next character
348 CMP AL,1AH ; ^Z?
349 JZ ENDRDDEVJ2 ; Yes, done zero set (EOF)
350 CMP AL,c_CR ; CR?
351 LOOPNZ DVRDLP ; Loop if no, else done
352 INC AX ; Resets zero flag so NOT EOF, unless
353 ; AX=FFFF which is not likely
354ENDRDDEVJ2:
355 JMP SHORT ENDRDDEV
356
357ASSUME DS:NOTHING,ES:NOTHING
358
359TRANBUF:
360 LODSB
361 STOSB
362 CMP AL,c_CR ; Check for carriage return
363 JNZ NORMCH
364 MOV BYTE PTR [SI],c_LF
365NORMCH:
366 CMP AL,c_LF
367 LOOPNZ TRANBUF
368 JNZ ENDRDCON
369 XOR SI,SI ; Cause a new buffer to be read
370 invoke OUTT ; Transmit linefeed
371 OR AL,1 ; Clear zero flag--not end of file
372ENDRDCON:
373 Context DS
374 CALL SWAPBACK
375 MOV [CONTPOS],SI
376ENDRDDEV:
377 Context DS
378 MOV [NEXTADD],DI
379 JNZ SETSFTC ; Zero set if Ctrl-Z found in input
380 LES DI,[THISSFT]
381 Assert ISSFT,<ES,DI>,"DOS_Read/EndRdDev"
382 AND BYTE PTR ES:[DI.sf_flags],NOT devid_device_EOF ; Mark as no more data available
383SETSFTC:
384 invoke SETSFT
385 return
386
387ASSUME DS:NOTHING,ES:NOTHING
388
389READCON:
390 DOSAssume CS,<DS>,"ReadCon"
391 CALL SWAPCON
392 MOV SI,[CONTPOS]
393 OR SI,SI
394 JNZ TRANBUF
395 CMP BYTE PTR [CONBUF],128
396 JZ GETBUF
397 MOV WORD PTR [CONBUF],0FF80H ; Set up 128-byte buffer with no template
398GETBUF:
399 PUSH CX
400 PUSH ES
401 PUSH DI
402 MOV DX,OFFSET DOSGROUP:CONBUF
403 invoke $STD_CON_STRING_INPUT ; Get input buffer
404 POP DI
405 POP ES
406 POP CX
407 MOV SI,2 + OFFSET DOSGROUP:CONBUF
408 CMP BYTE PTR [SI],1AH ; Check for Ctrl-Z in first character
409 JNZ TRANBUF
410 MOV AL,1AH
411 STOSB
412 DEC DI
413 MOV AL,c_LF
414 invoke OUTT ; Send linefeed
415 XOR SI,SI
416 JMP ENDRDCON
417
418EndProc DOS_READ
419
420Break <DOS_WRITE -- MAIN WRITE ROUTINE AND DEVICE OUT ROUTINES>
421
422;
423; Inputs:
424; [THISSFT] set to the SFT for the file being used
425; [DMAADD] contains transfer address
426; CX = No. of bytes to write
427; Function:
428; Perform write operation
429; NOTE: If CX = 0 on input, file is truncated or grown
430; to current sf_position
431; Outputs:
432; Carry clear
433; SFT Position and cluster pointers updated
434; CX = No. of bytes written
435; ES:DI point to SFT
436; Carry set
437; AX is error code
438; CX = 0
439; ES:DI point to SFT
440; DS preserved, all other registers destroyed
441
442 procedure DOS_WRITE,NEAR
443 DOSAssume CS,<DS>,"DOS_Write"
444 ASSUME ES:NOTHING
445
446IF BUFFERFLAG
447 cmp [BUF_EMS_MODE], -1
448 jz dos_wrt_call
449 call choose_buf_page
450 jnc sav_map_wrt_hndl
451 return
452sav_map_wrt_hndl:
453; call save_user_map
454dos_wrt_call:
455ENDIF
456
457
458 LES DI,[THISSFT]
459 Assert ISSFT,<ES,DI>,"DosWrite"
460 MOV AL,BYTE PTR ES:[DI.sf_mode]
461 AND AL,access_mask
462 CMP AL,open_for_read
463 JNE Check_FCB_RO ;Is write or both
464BadMode:
465 transfer SET_ACC_ERR
466
467;
468; NOTE: The following check for writting to a Read Only File is performed
469; ONLY on FCBs!!!!
470; We ALLOW writes to Read Only files via handles to allow a CREATE
471; of a read only file which can then be written to.
472; This is OK because we are NOT ALLOWED to OPEN a RO file via handles
473; for writting, or RE-CREATE an EXISTING RO file via handles. Thus,
474; CREATing a NEW RO file, or RE-CREATing an existing file which
475; is NOT RO to be RO, via handles are the only times we can write
476; to a read-only file.
477;
478Check_FCB_RO:
479 TEST ES:[DI.sf_mode],sf_isfcb
480 JZ WRITE_NO_MODE ; Not an FCB
481 TEST ES:[DI].sf_attr,attr_read_only
482 JNZ BadMode ; Can't write to Read_Only files via FCB
483WRITE_NO_MODE:
484 invoke SETUP
485 invoke IsSFTNet
486 JZ LOCAL_WRITE
487
488; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ?
489; JZ IFS_HAS_SHARE2 ;AN000;;IFS. yes
490; EnterCrit critDisk ;AN000;;IFS. enter critical section
491; CALL CHECK_WRITE_LOCK ;AN000;;IFS. check write lock
492; JC nocommit ;AN000;;IFS. lock error
493;
494; LeaveCrit critDisk ;AN000;;IFS. leave critical section
495IFS_HAS_SHARE2: ;AN000;
496
497
498IF NOT Installed
499 transfer NET_WRITE
500ELSE
501 MOV AX,(multNET SHL 8) OR 9
502 INT 2FH
503; JC nomore ;AN000;;IFS. error
504; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ?
505; JZ nomore ;AN000;;IFS. yes
506;
507; MOV AX,1 ;AN000;;IFS. update all SFT for new size
508; call JShare + 14 * 4 ;AN000;;IFS. call ShSu
509
510nomore: ;AN000;
511 return
512ENDIF
513
514
515LOCAL_WRITE:
516 TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O
517 JNZ WRTDEV
518 MOV [EXTERR_LOCUS],errLOC_Disk
519 EnterCrit critDisk
520 TEST [FastSeekflg],Fast_yes ;AN000;FO. FastSeek installed ?
521 JZ FS_no2 ;AN000;FO. no
522 OR [FastSeekflg],FS_begin ;AN000;FO. set fastseek mode
523FS_no2: ;AN000;
524 invoke DISKWRITE
525 PUSHF ;AN000;FO. save flag
526 AND CS:[FastSeekflg],FS_end ;AN000;FO. reset fastseek mode
527 POPF ;AN000;FO. restore flag
528;; Extended Open
529 JC nocommit ;AN000;EO.
530 LES DI,[THISSFT] ;AN000;EO.
531 TEST ES:[DI.sf_mode],auto_commit_write ;AN000;EO.
532 JZ nocommit ;AN000;EO.
533 PUSH CX ;AN000;EO.
534 invoke DOS_COMMIT ;AN000;EO.
535 POP CX ;AN000;EO.
536nocommit: ;AN000;
537;; Extended Open
538 LeaveCrit critDisk
539 return
540
541DVWRTRAW:
542ASSUME DS:NOTHING
543 XOR AX,AX ; Media Byte, unit = 0
544 invoke SETWRITE
545 PUSH DS ; Save seg of transfer
546 LDS SI,[THISSFT]
547 Assert ISSFT,<DS,SI>,"DosWrite/DvWrtRaw"
548 invoke DEVIOCALL ; DS:SI -> DEVICE
549 MOV DX,DI ; Offset part of Xaddr saved in DX
550 MOV AH,87H
551 MOV DI,[DEVCALL.REQSTAT]
552 TEST DI,STERR
553 JZ CWRTROK
554 invoke CHARHARD
555 MOV BX,DX ; Recall transfer addr
556 OR AL,AL
557 JZ CWRTROK ; Ignore
558 CMP AL,3
559 JZ CWRFERR
560 POP DS ; Recover saved seg of transfer
561 JMP DVWRTRAW ; Try again
562
563CWRFERR:
564 POP AX ; Chuck saved seg of transfer
565 JMP CRDFERR ; Will pop one more stack element
566
567CWRTROK:
568 POP AX ; Chuck saved seg of transfer
569 POP DS
570 DOSAssume CS,<DS>,"DISK/CWrtOK"
571 MOV AX,[CALLSCNT] ; Get actual number of bytes transferred
572ENDWRDEV:
573 LES DI,[THISSFT]
574 Assert ISSFT,<ES,DI>,"DosWrite/EndWrDev"
575 MOV CX,AX
576 invoke ADDREC
577 return
578
579WRTNUL:
580 MOV DX,CX ;Entire transfer done
581WrtCookJ:
582 JMP WRTCOOKDONE
583
584WRTDEV:
585 DOSAssume CS,<DS>,"DISK/WrtDev"
586 MOV [EXTERR_LOCUS],errLOC_SerDev
587 OR BYTE PTR ES:[DI.sf_flags],devid_device_EOF ; Reset EOF for input
588 MOV BL,BYTE PTR ES:[DI.sf_flags]
589 XOR AX,AX
590 JCXZ ENDWRDEV ; problem of creating on a device.
591 PUSH DS
592 MOV AL,BL
593 LDS BX,[DMAADD] ; Xaddr to DS:BX
594ASSUME DS:NOTHING
595 MOV DI,BX ; Xaddr to DS:DI
596 XOR DX,DX ; Set starting point
597 TEST AL,devid_device_raw ; Raw?
598 JZ TEST_DEV_CON
599 JMP DVWRTRAW
600
601TEST_DEV_CON:
602 TEST AL,devid_device_con_out ; Console output device?
603 JNZ WRITECON
604 TEST AL,devid_device_null
605 JNZ WRTNUL
606 MOV AX,DX
607 CMP BYTE PTR [BX],1AH ; ^Z?
608 JZ WRTCOOKJ ; Yes, transfer nothing
609 PUSH CX
610 MOV CX,1
611 invoke SETWRITE
612 POP CX
613 LDS SI,[THISSFT]
614 OR CS:[DOS34_FLAG],X25_Special;AN000;;PTM. bad x25 driver
615 MOV AH,3 ;AN000;;PTM. prompt critical error ASAP
616 invoke IOFUNC ;AN000;;PTM.
617 Assert ISSFT,<DS,SI>,"DosWrite/TestDevCon"
618 LDS SI,[SI.sf_devptr]
619DVWRTLP:
620 invoke DSKSTATCHK
621 invoke DEVIOCALL2
622 PUSH DI
623 MOV AH,87H
624 MOV DI,[DEVCALL.REQSTAT]
625 TEST DI,STERR
626 JZ CWROK
627 invoke CHARHARD
628 POP DI
629 MOV [CALLSCNT],1
630 CMP AL,1
631 JZ DVWRTLP ; Retry
632 OR AL,AL
633 JZ DVWRTIGN ; Ignore
634 JMP CRDFERR ; Fail, pops one stack element
635
636CWROK:
637 POP DI
638 CMP [CALLSCNT],0
639 JZ WRTCOOKDONE
640DVWRTIGN:
641 INC DX
642 INC WORD PTR [CALLXAD]
643 INC DI
644 PUSH DS
645 MOV DS,WORD PTR [CALLXAD+2]
646 CMP BYTE PTR [DI],1AH ; ^Z?
647 POP DS
648 JZ WRTCOOKDONE
649 MOV [DEVCALL.REQSTAT],0
650 LOOP DVWRTLP
651WRTCOOKDONE:
652 MOV AX,DX
653 POP DS
654 JMP ENDWRDEV
655
656WRITECON:
657 PUSH DS
658 Context DS
659 CALL SWAPCON
660 POP DS
661ASSUME DS:NOTHING
662 MOV SI,BX
663 PUSH CX
664WRCONLP:
665 LODSB
666 CMP AL,1AH ; ^Z?
667 JZ CONEOF
668 invoke OUTT
669 LOOP WRCONLP
670CONEOF:
671 POP AX ; Count
672 SUB AX,CX ; Amount actually written
673 POP DS
674 DOSAssume CS,<DS>,"DISK/ConEOF"
675 CALL SWAPBACK
676 JMP ENDWRDEV
677EndProc DOS_WRITE
678
679; Convert JFN number in BX to sf_entry in DS:SI We get the normal SFT if
680; CONSWAP is FALSE or if the handle desired is 2 or more. Otherwise, we
681; retrieve the sft from ConSFT which is set by SwapCon.
682
683 procedure get_io_sft,near
684ASSUME DS:NOTHING,ES:NOTHING
685 TEST ConSwap,-1
686 JNZ GetRedir
687GetNormal:
688 Context DS
689 PUSH ES
690 PUSH DI
691 invoke SFFromHandle
692 JC RET44P
693 MOV SI,ES
694 MOV DS,SI
695ASSUME DS:NOTHING
696 MOV SI,DI
697RET44P:
698 POP DI
699 POP ES
700 return
701GetRedir:
702 CMP BX,1
703 JA GetNormal
704 LDS SI,ConSFT
705 Assert ISSFT,<DS,SI>,"GetIOSft"
706 CLC
707 return
708EndProc get_io_sft
709
710Break <DIRREAD -- READ A DIRECTORY SECTOR>
711
712; Inputs:
713; AX = Directory block number (relative to first block of directory)
714; ES:BP = Base of drive parameters
715; [DIRSEC] = First sector of first cluster of directory
716; [CLUSNUM] = Next cluster
717; [CLUSFAC] = Sectors/Cluster
718; Function:
719; Read the directory block into [CURBUF].
720; Outputs:
721; [NXTCLUSNUM] = Next cluster (after the one skipped to)
722; [SECCLUSPOS] Set
723; ES:BP unchanged
724; [CURBUF] Points to Buffer with dir sector
725; Carry set if error (user said FAIL to I 24)
726; DS preserved, all other registers destroyed.
727
728 procedure DirRead,NEAR
729 DOSAssume CS,<DS>,"DirRead"
730 ASSUME ES:NOTHING
731 Assert ISDPB,<ES,BP>,"DirRead"
732
733;
734; Note that ClusFac is is the sectors per cluster. This is NOT necessarily
735; the same as what is in the DPB! In the case of the root directory, we have
736; ClusFac = # sectors in the root directory. The root directory is detected
737; by DIRStart = 0.
738;
739 XOR DX,DX
740 CMP DirStart,0
741 jnz SubDir
742 XCHG AX,DX
743 JMP DoRead
744;
745; Convert the sector number in AX into cluster and sector-within-cluster pair
746;
747SubDir:
748 MOV DL,AL
749 AND DL,ES:[BP.dpb_cluster_mask]
750;
751; DX is the sector-in-cluster
752;
753 MOV CL,ES:[BP.dpb_cluster_shift]
754 SHR AX,CL
755;
756; DX is position in cluster
757; AX is number of clusters to skip
758;
759DoRead:
760 MOV [SECCLUSPOS],DL
761 MOV CX,AX
762 MOV AH,DL
763;
764; CX is number of clusters to skip.
765; AH is remainder
766;
767 MOV DX,WORD PTR [DIRSEC+2] ;AN000;>32mb
768 MOV [HIGH_SECTOR],DX ;AN000;>32mb
769 MOV DX,WORD PTR [DIRSEC]
770 ADD DL,AH
771 ADC DH,0
772 ADC [HIGH_SECTOR],0 ;AN000;>32mb
773
774 MOV BX,[CLUSNUM]
775 MOV [NXTCLUSNUM],BX
776 JCXZ FIRSTCLUSTER
777SKPCLLP:
778 invoke UNPACK
779 retc
780 XCHG BX,DI
781 invoke IsEOF ; test for eof based on fat size
782 JAE HAVESKIPPED
783 LOOP SKPCLLP
784HAVESKIPPED:
785 MOV [NXTCLUSNUM],BX
786 MOV DX,DI
787 MOV BL,AH
788 invoke FIGREC
789
790 entry FIRSTCLUSTER
791
792 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
793 XOR AL,AL ; Indicate pre-read
794 invoke GETBUFFR
795 retc
796
797 entry SET_BUF_AS_DIR
798 DOSAssume CS,<DS>,"SET_BUF_AS_DIR"
799 ASSUME ES:NOTHING
800; Set the type of CURBUF to be a directory sector.
801; Only flags are modified.
802
803 PUSH DS
804 PUSH SI
805 LDS SI,[CURBUF]
806 Assert ISBUF,<DS,SI>,"SetBufAsDir"
807 OR [SI.buf_flags],buf_isDIR ; Clears carry
808 POP SI
809 POP DS
810 return
811EndProc DirRead
812
813Break <FATSECRD -- READ A FAT SECTOR>
814
815; Inputs:
816; Same as DREAD
817; DS:BX = Transfer address
818; CX = Number of sectors
819; DX = Absolute record number
820; ES:BP = Base of drive parameters
821; Function:
822; Calls BIOS to perform FAT read.
823; Outputs:
824; Same as DREAD
825
826 procedure FATSecRd,NEAR
827ASSUME DS:NOTHING,ES:NOTHING
828
829 Assert ISDPB,<ES,BP>,"FATSecRd"
830 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
831 MOV DI,CX
832 MOV CL,ES:[BP.dpb_FAT_count]
833 MOV AX,ES:[BP.dpb_FAT_size] ;AN000;>32mb
834; XOR AH,AH
835 XOR CH,CH ;AN000;>32mb
836 PUSH DX
837NXTFAT:
838 MOV [HIGH_SECTOR],0 ;AN000;>32mb FAT sectors cannot exceed
839 PUSH CX ;AN000;>32mb
840 PUSH AX
841 MOV CX,DI
842 invoke DSKREAD
843 POP AX
844 POP CX
845 JZ RET41P ; Carry clear
846 ADD DX,AX
847 LOOP NXTFAT
848 POP DX
849 MOV CX,DI
850
851; NOTE FALL THROUGH
852
853Break <DREAD -- DO A DISK READ>
854
855; Inputs:
856; DS:BX = Transfer address
857; CX = Number of sectors
858; DX = Absolute record number (LOW)
859; [HIGH_SECTOR]= Absolute record number (HIGH)
860; ES:BP = Base of drive parameters
861; [ALLOWED] must be set in case call to HARDERR needed
862; Function:
863; Calls BIOS to perform disk read. If BIOS reports
864; errors, will call HARDERRRW for further action.
865; Outputs:
866; Carry set if error (currently user FAILED to INT 24)
867; DS,ES:BP preserved. All other registers destroyed.
868
869 entry DREAD
870ASSUME DS:NOTHING,ES:NOTHING
871
872 Assert ISDPB,<ES,BP>,"DREAD"
873 invoke DSKREAD
874 retz ; Carry clear
875 MOV BYTE PTR [READOP],0
876 invoke HARDERRRW
877 CMP AL,1 ; Check for retry
878 JZ DREAD
879 CMP AL,3 ; Check for FAIL
880 CLC
881 JNZ NO_CAR ; Ignore
882 STC
883NO_CAR:
884 return
885
886RET41P: POP DX
887 return
888EndProc FATSecRd
889
890
891Break <CHECK_WRITE_LOCK>
892
893; Inputs:
894; output of SETUP
895; ES:DI -> SFT
896; Function:
897; check write lock
898; Outputs:
899; Carry set if error
900; Carry clear if ok
901
902 procedure CHECK_WRITE_LOCK,NEAR ;AN000;
903ASSUME DS:NOTHING,ES:NOTHING ;AN000;
904
905 TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id
906 JZ write_cont ;AN000;;MS. no
907 invoke SET_ACC_ERR_DS ;AN000;;MS.
908 return ;AN000;;MS.
909write_cont: ;AN000;
910 PUSH CX ;AN000;;MS. save reg
911 OR CX,CX ;AN000;;MS.
912 JNZ Not_Truncate ;AN000;;MS.
913 MOV CX,0FFFFH ;AN000;;MS. check for lock on whole file
914Not_Truncate: ;AN000;
915 MOV AL,80H ;AN000;;MS. check write access
916 invoke LOCK_CHECK ;AN000;;MS. check lock
917 POP CX ;AN000;;MS. restore reg
918 JNC WRITE_OK ;AN000;;MS. lock ok
919 invoke WRITE_LOCK_VIOLATION ;AN000;;MS. issue I24
920 JNC CHECK_WRITE_LOCK ;AN000;;MS. retry
921WRITE_OK: ;AN000;
922 return ;AN000;;MS.
923EndProc CHECK_WRITE_LOCK ;AN000;
924
925
926Break <CHECK_READ_LOCK>
927
928; Inputs:
929; ES:DI -> SFT
930; output of SETUP
931; Function:
932; check read lock
933; Outputs:
934; Carry set if error
935; Carry clear if ok
936
937 procedure CHECK_READ_LOCK,NEAR ;AN000;
938ASSUME DS:NOTHING,ES:NOTHING ;AN000;
939
940 TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id
941 JZ do_retry ;AN000;;MS. no
942 invoke SET_ACC_ERR ;AN000;;MS.
943 return ;AN000;;MS.
944do_retry: ;AN000;
945 MOV AL,0 ;AN000;;MS. check read access
946 invoke LOCK_CHECK ;AN000;;MS. check lock
947 JNC READ_OK ;AN000;;MS. lock ok
948 invoke READ_LOCK_VIOLATION ;AN000;;MS. issue I24
949 JNC CHECK_READ_LOCK ;AN000;;MS. retry
950READ_OK: ;AN000; MS.
951 return ;AN000;;MS.
952EndProc CHECK_READ_LOCK ;AN000;
953
954IF BUFFERFLAG
955
956;-------------------------------------------------------------------------
957; Function name : choose_buf_page
958; Inputs : DMAADD = Xaddr
959; cx = # of bytes to transfer
960; Outputs : if NC
961;
962; SAFE_FLAG - 0 ==> page is safe. no need to
963; detect collision between
964; user & system buffer.
965; SAFE_FLAG - 1 ==> page is unsafe. Must check
966; for collision
967;
968; CY - error
969;
970;
971; High Level Alogrithm:
972;
973; 1. If Xaddr. is above the first physical page above 640K
974; 2. choose that page
975; 3. set safe flag
976; 4. else
977; 5. choose highest page above 640K
978; 6. If 6 or more pages above 640k
979; 7. Set safe flag
980; 8. else
981; 9. if Xaddr. + # of bytes to transfer does not spill into the
982; chosen page
983; 10. set safe flag
984; 11.else
985; 12. clear safe flag
986; 13.endif
987; 14.endif
988; 15.endif
989;
990;----------------------------------------------------------------------------
991Procedure choose_buf_page,near
992
993 assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup
994
995 push cx
996 push bx
997 push dx
998 push si
999 push ds
1000 push ax
1001
1002 mov ax, word ptr [DMAADD+2]
1003 and ax, 0fc00h ; page segment of transfer segment
1004
1005 cmp ax, word ptr [BUF_EMS_FIRST_PAGE]
1006 ja pick_first
1007
1008 cmp [BUF_EMS_NPA640], 6
1009 jae safe_pick_last
1010
1011 add cx, word ptr [DMAADD] ; get final offset
1012 mov bx, cx
1013
1014 mov cl, 4
1015 shr bx, cl ; get # of paragraphs
1016 mov ax, word ptr [DMAADD+2] ; get initial segment
1017 add ax, bx ; get final segment
1018
1019 and ax, 0fc00h
1020 cmp ax, word ptr [BUF_EMS_LAST_PAGE]
1021 jne safe_pick_last
1022
1023 mov [BUF_EMS_SAFE_FLAG], 0
1024 jmp fin_choose_page
1025
1026safe_pick_last:
1027 mov [BUF_EMS_SAFE_FLAG], 1
1028 jmp fin_choose_page
1029
1030;pick_last:
1031; mov ax, word ptr [BUF_EMS_LAST_PAGE]
1032; mov [BUF_EMS_PFRAME], ax
1033; mov ax, word ptr [BUF_EMS_LAST_PAGE+2]
1034; mov [BUF_EMS_PAGE_FRAME], ax
1035; xor ax, ax
1036; jmp fin_choose_page
1037
1038pick_first:
1039 mov ax, word ptr [BUF_EMS_FIRST_PAGE]
1040 cmp [BUF_EMS_PFRAME], ax
1041 je fin_choose_page
1042 call restore_user_map
1043 mov word ptr [LASTBUFFER], -1
1044 mov [BUF_EMS_PFRAME], ax
1045 mov ax, word ptr [BUF_EMS_FIRST_PAGE+2]
1046 mov [BUF_EMS_PAGE_FRAME], ax
1047 mov [BUF_EMS_SAFE_FLAG], 1
1048 call Setup_EMS_Buffers
1049 call save_user_map
1050 jmp fin_choose_page
1051
1052err_choose_page:
1053 stc
1054
1055fin_choose_page:
1056 clc
1057
1058 pop ax
1059 pop ds
1060 pop si
1061 pop dx
1062 pop bx
1063 pop cx
1064 return
1065
1066EndProc choose_buf_page
1067
1068ENDIF
1069
1070CODE ENDS
1071 END
1072
1073
diff --git a/v4.0/src/DOS/DISK2.ASM b/v4.0/src/DOS/DISK2.ASM
new file mode 100644
index 0000000..bb76e89
--- /dev/null
+++ b/v4.0/src/DOS/DISK2.ASM
@@ -0,0 +1,784 @@
1; SCCSID = @(#)disk2.asm 1.3 85/06/19
2; SCCSID = @(#)disk2.asm 1.3 85/06/19
3TITLE DISK2 - Disk utility routines
4NAME Disk2
5; Low level Read and write routines for local SFT I/O on files and devs
6;
7; DskRead
8; DWRITE
9; DSKWRITE
10; HarderrRW
11; SETUP
12; BREAKDOWN
13; READ_LOCK_VIOLATION
14; WRITE_LOCK_VIOLATION
15; DISKREAD
16; SET_ACC_ERR_DS
17; SET_ACC_ERR
18; SETSFT
19; SETCLUS
20; AddRec
21;
22; Revision history:
23;
24; AN000 version 4.00 Jan. 1988
25;
26
27;
28; get the appropriate segment definitions
29;
30.xlist
31include dosseg.asm
32
33CODE SEGMENT BYTE PUBLIC 'CODE'
34 ASSUME SS:DOSGROUP,CS:DOSGROUP
35
36.xcref
37INCLUDE DOSSYM.INC
38INCLUDE DEVSYM.INC
39include version.inc
40.cref
41.list
42
43Installed = TRUE
44
45 i_need THISSFT,DWORD
46 i_need DMAADD,DWORD
47 i_need NEXTADD,WORD
48 i_need ThisDrv,BYTE
49 i_need SecClusPos,BYTE
50 i_need ClusNum,WORD
51 i_need ReadOp,BYTE
52 i_need Trans,BYTE
53 i_need BytPos,4
54 i_need SecPos,DWORD ; DOS 4.00 >32mb ;AN000;
55 i_need BytSecPos,WORD
56 i_need BytCnt1,WORD
57 i_need BytCnt2,WORD
58 i_need SecCnt,WORD
59 i_need ThisDPB,DWORD
60 i_need LastPos,WORD
61 i_need EXTERRPT,DWORD
62 i_need CALLVIDRW,DWORD
63 i_need ALLOWED,BYTE
64 i_need DEVCALL,BYTE
65 i_need CALLSCNT,WORD
66 i_need DISK_FULL,BYTE ; disk full flag for ran blk wrt
67 i_need FSeek_drive,BYTE ; DOS 4.00 ;AN000;
68 i_need FSeek_firclus,WORD ; DOS 4.00 ;AN000;
69 i_need HIGH_SECTOR,WORD ; F.C. >32mb ;AN000;
70 i_need TEMP_VAR2,WORD ; LB. ;AN000;
71 i_need TEMP_VAR,WORD ; LB. ;AN000;
72 i_need IFS_DRIVER_ERR,WORD ; LB. ;AN000;
73 i_need CurHashEntry,DWORD ; DOS 4.00 current Hash entry ;AN000;
74 i_need BUF_HASH_PTR,DWORD ; DOS 4.00 Hash table pointer ;AN000;
75 i_need BUF_HASH_COUNT,WORD ; DOS 4.00 Hash table entries ;AN000;
76 i_need LastBuffer,DWORD
77 i_need FIRST_BUFF_ADDR,WORD ; first buffer address ;AN000;
78
79IF BUFFERFLAG
80 EXTRN SAVE_MAP:NEAR
81 EXTRN RESTORE_MAP:NEAR
82 EXTRN SAVE_USER_MAP:NEAR
83 EXTRN RESTORE_USER_MAP:NEAR
84 i_need BUF_EMS_SAFE_FLAG,BYTE
85 i_need BUF_EMS_MODE,BYTE
86 i_need CURADD,WORD
87ENDIF
88
89
90Break <DSKREAD -- PHYSICAL DISK READ>
91
92; Inputs:
93; DS:BX = Transfer addr
94; CX = Number of sectors
95; [HIGH_SECTOR] = Absolute record number (HIGH)
96; DX = Absolute record number (LOW)
97; ES:BP = Base of drive parameters
98; Function:
99; Call BIOS to perform disk read
100; Outputs:
101; DI = CX on entry
102; CX = Number of sectors unsuccessfully transfered
103; AX = Status word as returned by BIOS (error code in AL if error)
104; Zero set if OK (from BIOS) (carry clear)
105; Zero clear if error (carry clear)
106; SI Destroyed, others preserved
107
108 procedure DskRead,NEAR
109ASSUME DS:NOTHING,ES:NOTHING
110
111 Assert ISDPB,<ES,BP>,"DskRead"
112 PUSH CX
113 MOV AH,ES:[BP.dpb_media]
114 MOV AL,ES:[BP.dpb_UNIT]
115 PUSH BX
116 PUSH ES
117 invoke SETREAD
118 JMP DODSKOP
119
120Break <DWRITE -- SEE ABOUT WRITING>
121
122; Inputs:
123; DS:BX = Transfer address
124; CX = Number of sectors
125; [HIGH_SECTOR] = Absolute record number (HIGH)
126; DX = Absolute record number (LOW)
127; ES:BP = Base of drive parameters
128; [ALLOWED] must be set in case HARDERR called
129; Function:
130; Calls BIOS to perform disk write. If BIOS reports
131; errors, will call HARDERRRW for further action.
132; Output:
133; Carry set if error (currently, user FAILed to I 24)
134; BP preserved. All other registers destroyed.
135
136 entry DWRITE
137ASSUME DS:NOTHING,ES:NOTHING
138
139 Assert ISDPB,<ES,BP>,"DWrite"
140 CALL DSKWRITE
141 retz ; Carry clear
142 MOV BYTE PTR [READOP],1
143 invoke HARDERRRW
144 CMP AL,1 ; Check for retry
145 JZ DWRITE
146 CMP AL,3 ; Check for FAIL
147 CLC
148 JNZ NO_CAR2 ; Ignore
149 STC
150NO_CAR2:
151 return
152
153Break <DSKWRITE -- PHYSICAL DISK WRITE>
154
155; Inputs:
156; DS:BX = Transfer addr
157; CX = Number of sectors
158; DX = Absolute record number (LOW)
159; [HIGH_SECTOR] = Absolute record number (HIGH)
160; ES:BP = Base of drive parameters
161; Function:
162; Call BIOS to perform disk read
163; Outputs:
164; DI = CX on entry
165; CX = Number of sectors unsuccessfully transfered
166; AX = Status word as returned by BIOS (error code in AL if error)
167; Zero set if OK (from BIOS) (carry clear)
168; Zero clear if error (carry clear)
169; SI Destroyed, others preserved
170
171 entry DSKWRITE
172ASSUME DS:NOTHING,ES:NOTHING
173
174 Assert ISDPB,<ES,BP>,"DskWrite"
175 PUSH CX
176 MOV AH,ES:[BP.dpb_media]
177 MOV AL,ES:[BP.dpb_UNIT]
178 PUSH BX
179 PUSH ES
180 invoke SETWRITE
181DODSKOP:
182 MOV CX,DS ; Save DS
183 POP DS ; DS:BP points to DPB
184 PUSH DS
185 LDS SI,DS:[BP.dpb_driver_addr]
186 invoke DEVIOCALL2
187 MOV DS,CX ; Restore DS
188 POP ES ; Restore ES
189 POP BX
190 MOV CX,[CALLSCNT] ; Number of sectors transferred
191 POP DI
192 SUB CX,DI
193 NEG CX ; Number of sectors not transferred
194 MOV AX,[DEVCALL.REQSTAT]
195 MOV [IFS_DRIVER_ERR],AX ;IFS. save it for IFS ;AN000;
196 TEST AX,STERR
197 return
198EndProc DskRead
199
200
201
202Break <HardErrRW - map extended errors and call harderr>
203
204; Inputs:
205; AX is error code from read or write
206; Other registers set as per HARDERR
207; Function:
208; Checks the error code for special extended
209; errors and maps them if needed. Then invokes
210; Harderr
211; Outputs:
212; Of HARDERR
213; AX may be modified prior to call to HARDERR.
214; No other registers altered.
215
216 procedure HARDERRRW,near
217ASSUME DS:NOTHING,ES:NOTHING
218
219 CMP AL,error_I24_wrong_disk
220 JNZ DO_ERR ; Nothing to do
221 PUSH DS
222 PUSH SI
223 LDS SI,[CALLVIDRW] ; Get pointer from dev
224 MOV WORD PTR [EXTERRPT+2],DS ; Set ext err pointer
225 MOV WORD PTR [EXTERRPT],SI
226 POP SI
227 POP DS
228DO_ERR:
229 invoke HARDERR
230 return
231
232EndProc HARDERRRW
233
234Break <SETUP -- SETUP A DISK READ OR WRITE FROM USER>
235
236; Inputs:
237; ES:DI point to SFT (value also in THISSFT)
238; [DMAADD] contains transfer address
239; CX = Byte count
240; WARNING Stack must be clean, two ret addrs on stack, 1st of caller,
241; 2nd of caller of caller.
242; Outputs:
243; CX = byte count
244; [THISDPB] = Base of drive parameters if file
245; = Pointer to device header if device or NET
246; ES:DI Points to SFT
247; [NEXTADD] = Displacement of disk transfer within segment
248; [TRANS] = 0 (No transfers yet)
249; [BYTPOS] = Byte position in file
250;
251; The following fields are relevant to local files (not devices) only:
252;
253; [SECPOS] = Position of first sector (local files only)
254; [BYTSECPOS] = Byte position in first sector (local files only)
255; [CLUSNUM] = First cluster (local files only)
256; [SECCLUSPOS] = Sector within first cluster (local files only)
257; [THISDRV] = Physical unit number (local files only)
258;
259; RETURNS ONE LEVEL UP WITH:
260; CX = 0
261; CARRY = Clear
262; IF AN ERROR IS DETECTED
263; All other registers destroyed
264
265 procedure SETUP,NEAR
266 DOSAssume CS,<DS>,"SetUp"
267 ASSUME ES:NOTHING
268
269 Assert ISSFT,<ES,DI>,"SetUp"
270 LDS SI,ES:[DI.sf_devptr]
271ASSUME DS:NOTHING
272 MOV WORD PTR [THISDPB+2],DS
273 context DS
274 MOV WORD PTR [THISDPB],SI
275 MOV BX,WORD PTR [DMAADD]
276 MOV [NEXTADD],BX ;Set NEXTADD to start of Xaddr
277 MOV BYTE PTR [TRANS],0 ;No transferes
278 MOV AX,WORD PTR ES:[DI.sf_Position]
279 MOV DX,WORD PTR ES:[DI.sf_Position+2]
280 MOV WORD PTR [BYTPOS+2],DX ;Set it
281 MOV WORD PTR [BYTPOS],AX
282 TEST ES:[DI.sf_flags],sf_isnet + devid_device
283 JNZ NOSETSTUFF ;Following not done on devs or NET
284 PUSH ES
285 LES BP,[THISDPB] ;Point at the DPB
286 Assert ISDPB,<ES,BP>,"Setup"
287 MOV BL,ES:[BP.dpb_drive]
288 MOV [THISDRV],BL ;Set THISDRV
289 MOV BX,ES:[BP.dpb_sector_size]
290; CMP DX,BX ; See if divide will overflow
291; JNC EOFERR ; for 16 bit sector
292;; 32 bit divide
293 invoke DIV32 ; F.C. >32mb ;AN000;
294 MOV WORD PTR [SECPOS],AX ; F.C. >32mb ;AN000;
295 MOV BX,[HIGH_SECTOR] ; F.C. >32mb ;AN000;
296 MOV WORD PTR [SECPOS+2],BX ; F.C. >32mb ;AN000;
297
298 MOV [BYTSECPOS],DX
299 MOV DX,AX
300 AND AL,ES:[BP.dpb_cluster_mask]
301 MOV [SECCLUSPOS],AL
302 MOV AX,CX ; Save byte count
303; MOV CL,ES:[BP.dpb_cluster_shift]
304 PUSH WORD PTR [SECPOS+2] ; F.C. >32mb ;AN000;
305 POP [HIGH_SECTOR] ; F.C. >32mb ;AN000;
306 PUSH AX ; F.C. >32mb save ax ;AN000;
307 MOV AX,DX ; F.C. >32mb ax=dx ;AN000;
308 invoke SHR32 ; F.C. >32mb shift ax ;AN000;
309 MOV DX,AX ; F.C. >32mb dx=ax ;AN000;
310 POP AX ; F.C. >32mb restore dx ;AN000;
311
312; SHR DX,CL
313 CMP DX,ES:[BP.dpb_max_cluster] ;>32mb if > disk size ;AN000; ;AN000;
314 JA EOFERR ;>32mb then EOF ;AN000; ;AN000;
315
316 MOV [CLUSNUM],DX
317 POP ES ; ES:DI point to SFT
318 MOV CX,AX ; Put byte count back in CX
319NOSETSTUFF:
320 MOV AX,CX ; Need it in AX too
321 ADD AX,WORD PTR [DMAADD] ; See if it will fit in one segment
322 JNC OK ; Must be less than 64K
323 MOV AX,WORD PTR [DMAADD]
324 NEG AX ; Amount of room left in segment (know
325 ; less than 64K since max value of CX
326 ; is FFFF).
327 JNZ NoDec
328 DEC AX
329NoDec:
330 MOV CX,AX ; Can do this much
331 JCXZ NOROOM ; Silly user gave Xaddr of FFFF in segment
332OK:
333 return
334
335EOFERR:
336 POP ES ; ES:DI point to SFT
337 XOR CX,CX ; No bytes read
338;;;;;;;;;;; 7/18/86
339; MOV BYTE PTR [DISK_FULL],1 ; set disk full flag
340;;;;;;;;;;;
341NOROOM:
342 POP BX ; Kill return address
343 CLC
344 return ; RETURN TO CALLER OF CALLER
345EndProc SETUP
346
347Break <BREAKDOWN -- CUT A USER READ OR WRITE INTO PIECES>
348
349; Inputs:
350; CX = Length of disk transfer in bytes
351; ES:BP = Base of drive parameters
352; [BYTSECPOS] = Byte position witin first sector
353; Outputs:
354; [BYTCNT1] = Bytes to transfer in first sector
355; [SECCNT] = No. of whole sectors to transfer
356; [BYTCNT2] = Bytes to transfer in last sector
357; AX, BX, DX destroyed. No other registers affected.
358
359 procedure BREAKDOWN,near
360 DOSAssume CS,<DS>,"BreakDown"
361 ASSUME ES:NOTHING
362
363 Assert ISDPB,<ES,BP>,"BreakDown"
364 MOV AX,[BYTSECPOS]
365 MOV BX,CX
366 OR AX,AX
367 JZ SAVFIR ; Partial first sector?
368 SUB AX,ES:[BP.dpb_sector_size]
369 NEG AX ; Max number of bytes left in first sector
370 SUB BX,AX ; Subtract from total length
371 JAE SAVFIR
372 ADD AX,BX ; Don't use all of the rest of the sector
373 XOR BX,BX ; And no bytes are left
374SAVFIR:
375 MOV [BYTCNT1],AX
376 MOV AX,BX
377 XOR DX,DX
378 DIV ES:[BP.dpb_sector_size] ; How many whole sectors?
379 MOV [SECCNT],AX
380 MOV [BYTCNT2],DX ; Bytes remaining for last sector
381 OR DX,[BYTCNT1]
382 retnz ; NOT (BYTCNT1 = BYTCNT2 = 0)
383 CMP AX,1
384 retnz
385 MOV AX,ES:[BP.dpb_sector_size] ; Buffer EXACT one sector I/O
386 MOV [BYTCNT2],AX
387 MOV [SECCNT],DX ; DX = 0
388RET45:
389 return
390EndProc BreakDown
391
392; ES:DI points to SFT. This entry used by NET_READ
393; Carry set if to return error (CX=0,AX=error_sharing_violation).
394; Else do retrys.
395; ES:DI,DS,CX preserved
396
397 procedure READ_LOCK_VIOLATION,NEAR
398 DOSAssume CS,<DS>,"Read_Lock_Violation"
399 ASSUME ES:NOTHING
400
401 Assert ISSFT,<ES,DI>,"ReadLockViolation"
402
403 MOV [READOP],0
404ERR_ON_CHECK:
405 TEST ES:[DI.sf_mode],sf_isfcb
406 JNZ HARD_ERR
407 PUSH CX
408 MOV CL,BYTE PTR ES:[DI.sf_mode]
409 AND CL,sharing_mask
410 CMP CL,sharing_compat
411 POP CX
412 JNE NO_HARD_ERR
413HARD_ERR:
414 invoke LOCK_VIOLATION
415 retnc ; User wants Retrys
416NO_HARD_ERR:
417 XOR CX,CX ;No bytes transferred
418 MOV AX,error_lock_violation
419 STC
420 return
421
422EndProc READ_LOCK_VIOLATION
423
424; Same as READ_LOCK_VIOLATION except for READOP.
425; This entry used by NET_WRITE
426 procedure WRITE_LOCK_VIOLATION,NEAR
427 DOSAssume CS,<DS>,"Write_Lock_Violation"
428 ASSUME ES:NOTHING
429 Assert ISSFT,<ES,DI>,"WriteLockViolation"
430
431 MOV [READOP],1
432 JMP ERR_ON_CHECK
433
434EndProc WRITE_LOCK_VIOLATION
435
436
437Break <DISKREAD -- PERFORM USER DISK READ>
438
439; Inputs:
440; Outputs of SETUP
441; Function:
442; Perform disk read
443; Outputs:
444; Carry clear
445; CX = No. of bytes read
446; ES:DI point to SFT
447; SFT offset and cluster pointers updated
448; Carry set
449; CX = 0
450; ES:DI point to SFT
451; AX has error code
452
453 procedure DISKREAD,NEAR
454 DOSAssume CS,<DS>,"DiskRead"
455 ASSUME ES:NOTHING
456
457 Assert ISSFT,<ES,DI>,"DISKREAD"
458 PUSH ES:[DI.sf_firclus] ; set up 1st cluster # for FastSeek
459 POP [FSeek_firclus] ; 11/5/86
460
461 MOV AX,WORD PTR ES:[DI.sf_size]
462 MOV BX,WORD PTR ES:[DI.sf_size+2]
463 SUB AX,WORD PTR [BYTPOS]
464 SBB BX,WORD PTR [BYTPOS+2]
465 JB RDERR ;Read starts past EOF
466 JNZ ENUF ;More than 64k to EOF
467 OR AX,AX
468 JZ RDERR ;Read starts at EOF
469 CMP AX,CX
470 JAE ENUF ;I/O fits
471 MOV CX,AX ;Limit read to up til EOF
472ENUF:
473 invoke CHECK_READ_LOCK ;IFS. check read lock ;AN000;
474 JNC Read_Ok ; There are no locks
475 return
476
477READ_OK:
478 LES BP,[THISDPB]
479 Assert ISDPB,<ES,BP>,"DISKREAD/ReadOK"
480 MOV AL,ES:[BP.dpb_drive] ; set up drive # for FastSeek
481 MOV [FSeek_drive],AL ; 11/5/86 ;AN000;
482
483 CALL BREAKDOWN
484 MOV CX,[CLUSNUM]
485 invoke FNDCLUS
486;------------------------------------------------------------------------
487IF NOT IBMCOPYRIGHT
488 JC SET_ACC_ERR_DS ; fix to take care of I24 fail
489 ; migrated from 330a - HKN
490ENDIF
491;------------------------------------------------------------------------
492 OR CX,CX
493 JZ SKIPERR
494RDERR:
495 MOV [DISK_FULL],1 ;MS. EOF detection ;AN000;
496 MOV AH,0EH ;MS. read/data/fail ;AN000;
497 transfer WRTERR22
498RDLASTJ:JMP RDLAST
499SETSFTJ2: JMP SETSFT
500
501CANOT_READ:
502 POP CX ; Clean stack
503 POP CX
504 POP BX
505
506 entry SET_ACC_ERR_DS
507ASSUME DS:NOTHING,ES:NOTHING
508 Context DS
509
510 entry SET_ACC_ERR
511 DOSAssume CS,<DS>,"SET_ACC_ERR"
512
513 XOR CX,CX
514 MOV AX,error_access_denied
515 STC
516 return
517
518SKIPERR:
519 MOV [LASTPOS],DX
520 MOV [CLUSNUM],BX
521 CMP [BYTCNT1],0
522 JZ RDMID
523 invoke BUFRD
524 JC SET_ACC_ERR_DS
525RDMID:
526 CMP [SECCNT],0
527 JZ RDLASTJ
528 invoke NEXTSEC
529 JC SETSFTJ2
530 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
531ONSEC:
532 MOV DL,[SECCLUSPOS]
533 MOV CX,[SECCNT]
534 MOV BX,[CLUSNUM]
535RDLP:
536 invoke OPTIMIZE
537 JC SET_ACC_ERR_DS
538 PUSH DI
539 PUSH AX
540 PUSH BX
541 MOV [ALLOWED],allowed_RETRY + allowed_FAIL + allowed_IGNORE
542 MOV DS,WORD PTR [DMAADD+2]
543ASSUME DS:NOTHING
544 PUSH DX
545 PUSH CX
546 invoke SET_RQ_SC_PARMS ;LB. do this for SC ;AN000;
547
548IF BUFFERFLAG
549 pushf
550 cmp [BUF_EMS_SAFE_FLAG], 1
551 je safe_read
552 call save_map
553 call restore_user_map
554safe_read:
555 popf
556ENDIF
557
558 invoke DREAD
559
560IF BUFFERFLAG
561 pushf
562 cmp [BUF_EMS_SAFE_FLAG], 1
563 je safe_mapping
564 call save_user_map
565 call restore_map
566safe_mapping:
567 popf
568ENDIF
569
570 POP BX
571 POP DX
572 JNC SKP_CANOT_READ
573 JMP CANOT_READ
574SKP_CANOT_READ:
575 MOV [TEMP_VAR],BX ;LB. save sector count ;AN000;
576 MOV [TEMP_VAR2],DX ;LB. 1st sector ;AN000;
577SCAN_NEXT:
578;;;;;;; invoke GETCURHEAD ;LB. get buffer header ;AN000;
579 PUSH DX ;LB. save regs ;AN000;
580 PUSH AX ;LB. ;AN000;
581 PUSH BX ;LB. ;AN000;
582 MOV AX,DX ;LB.
583; MOV DX,[HIGH_SECTOR] ;LB. HASH(sector#) and get entry # ;AN000;
584 XOR DX,DX ;LB. to avoid divide overflow ;AN000;
585 DIV [BUF_HASH_COUNT] ;LB. get remainder ;AN000;
586 ADD DX,DX ;LB. 8 bytes per entry ;AN000;
587 ADD DX,DX ;LB. ;AN000;
588 ADD DX,DX ;LB. times 8 ;AN000;
589
590 LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000;
591 ADD DI,DX ;LB position to entry ;AN000;
592 CMP [DI.Dirty_Count],0 ;LB dirty hash entry ? ;AN000;
593 JNZ yesdirty ;LB yes and map it ;AN000;
594 POP BX ;LB. ;AN000;
595 POP AX ;LB. ;AN000;
596 POP DX ;LB. ;AN000;
597
598IF NOT BUFFERFLAG
599 JMP SHORT end_scan ;LB. ;AN000;
600ELSE
601 JMP END_SCAN
602ENDIF
603
604yesdirty:
605 MOV WORD PTR [CurHashEntry+2],DS ;LB. update current Hash entry ptr ;AN000;
606 MOV WORD PTR [CurHashEntry],DI ;LB. ;AN000;
607 MOV WORD PTR [LASTBUFFER],-1 ;LB. invalidate last buffer ;AN000;
608 MOV BX,[DI.EMS_PAGE_NUM] ;LB. logical page ;AN000;
609
610IF NOT BUFFERFLAG
611 LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000;
612 MOV [FIRST_BUFF_ADDR],DI ;LB. save first buff addr 1/19/88 ;AN000;
613 invoke SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000;
614ELSE
615; int 3
616 push ds
617 push di ; save hash ptr
618
619 LDS DI,[DI.BUFFER_BUCKET] ;ds:di is 1st buffer addr
620 POP AX ; Recall transfer address
621 PUSH AX
622 PUSH DI ; Save search environment
623 PUSH DX ; F.C. no need for high sector, <64K
624 push cx
625
626 MOV DX,[TEMP_VAR2] ;LB. get 1st sector #
627 SUB DX,WORD PTR [DI.buf_sector] ; How far into transfer?
628 NEG DX
629 MOV DI,AX
630 MOV AX,DX
631 MOV CX,ES:[BP.dpb_sector_size]
632 MUL CX
633 ADD DI,AX ; Put the buffer here
634 mov [CURADD], di
635
636 pop cx
637 pop dx
638 pop di
639
640 invoke SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000;
641 pop di ; restore hash ptr.
642 pop ds
643 LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000;
644 MOV [FIRST_BUFF_ADDR],DI ;LB. save first buff addr 1/19/88 ;AN000;
645ENDIF
646 ;AN000;
647 POP BX ;LB. ;AN000;
648 POP AX ;LB. ;AN000;
649 POP DX ;LB. ;AN000;
650
651
652 Assert ISDPB,<ES,BP>,"DISKREAD/RdLp"
653 MOV AL,ES:[BP.dpb_drive]
654NXTBUF: ; Must see if one of these sectors is buffered
655 invoke BUFF_RANGE_CHECK ;F.C. >32mb
656 JNC inrange ;LB. ;AN000;
657 mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000;
658 JMP DONXTBUF ;LB. ;AN000;
659inrange:
660 TEST [DI.buf_flags],buf_dirty
661 JZ CLBUFF ; Buffer is clean, so OK
662; A sector has been read in when a dirty copy of it is in a buffer
663; The buffered sector must now be read into the right place
664 POP AX ; Recall transfer address
665 PUSH AX
666 PUSH DI ; Save search environment
667 PUSH DX ; F.C. no need for high sector, <64K
668
669 MOV DX,[TEMP_VAR2] ;LB. get 1st sector #
670 SUB DX,WORD PTR [DI.buf_sector] ; How far into transfer?
671 NEG DX
672 MOV SI,DI
673 MOV DI,AX
674 MOV AX,DX
675 MOV CX,ES:[BP.dpb_sector_size]
676 MUL CX
677 ADD DI,AX ; Put the buffer here
678 LEA SI,[SI].BUFINSIZ
679 SHR CX,1
680 PUSH ES
681 MOV ES,WORD PTR [DMAADD+2]
682 REP MOVSW
683 JNC EVENMOV
684 MOVSB
685EVENMOV:
686 POP ES
687 POP DX
688 POP DI
689 MOV AL,ES:[BP.dpb_drive]
690 invoke SCANPLACE ;LB. done with this chain ;AN000;
691 JMP SHORT end_scan ;LB. ;AN000;
692CLBUFF:
693 invoke SCANPLACE
694DONXTBUF:
695 CMP DI,[FIRST_BUFF_ADDR] ;LB. end of buffers ;AN000;
696 JNZ NXTBUF
697end_scan:
698 ADD DX,1 ;LB. next sector # ;AN000;
699 ADC [HIGH_SECTOR],0 ;LB. ;AN000;
700 DEC [TEMP_VAR] ;LB. decrement count ;AN000;
701 JZ SCAN_DONE ;LB. scan next sector ;AN000;
702 JMP SCAN_NEXT ;LB. scan next sector ;AN000;
703SCAN_DONE:
704 Context DS
705 POP CX
706 POP CX
707 POP BX
708 JCXZ RDLAST
709 invoke IsEOF ; test for eof on fat size
710 JAE SETSFT
711 MOV DL,0
712 INC [LASTPOS] ; We'll be using next cluster
713 JMP RDLP
714
715RDLAST:
716 MOV AX,[BYTCNT2]
717 OR AX,AX
718 JZ SETSFT
719 MOV [BYTCNT1],AX
720 invoke NEXTSEC
721 JC SETSFT
722 MOV [BYTSECPOS],0
723 invoke BUFRD
724 JNC SETSFT
725 JMP SET_ACC_ERR_DS
726
727; Inputs:
728; [NEXTADD],[CLUSNUM],[LASTPOS] set to determine transfer size
729; and set cluster fields
730; Function:
731; Update [THISSFT] based on the transfer
732; Outputs:
733; sf_position, sf_lstclus, and sf_cluspos updated
734; ES:DI points to [THISSFT]
735; CX No. of bytes transferred
736; Carry clear
737
738 entry SETSFT
739 DOSAssume CS,<DS>,"SetSFT"
740 ASSUME ES:NOTHING
741
742 LES DI,[THISSFT]
743
744; Same as SETSFT except ES:DI already points to SFT
745 entry SETCLUS
746 DOSAssume CS,<DS>,"SetClus"
747 ASSUME ES:NOTHING
748
749 Assert ISSFT,<ES,DI>,"SetClus"
750 MOV CX,[NEXTADD]
751 SUB CX,WORD PTR [DMAADD] ; Number of bytes transfered
752 TEST ES:[DI.sf_flags],devid_device
753 JNZ ADDREC ; don't set clusters if device
754 MOV AX,[CLUSNUM]
755 MOV ES:[DI.sf_lstclus],AX
756 MOV AX,[LASTPOS]
757 MOV ES:[DI.sf_cluspos],AX
758
759; Inputs:
760; ES:DI points to SFT
761; CX is No. Bytes transferred
762; Function:
763; Update the SFT offset based on the transfer
764; Outputs:
765; sf_position updated to point to first byte after transfer
766; ES:DI points to SFT
767; CX No. of bytes transferred
768; Carry clear
769
770 entry AddRec
771 DOSAssume CS,<DS>,"AddRec"
772 ASSUME ES:NOTHING
773
774 Assert ISSFT,<ES,DI>,"AddRec"
775 JCXZ RET28 ; If no records read, don't change position
776 ADD WORD PTR ES:[DI.sf_position],CX ; Update current position
777 ADC WORD PTR ES:[DI.sf_position+2],0
778RET28: CLC
779 return
780EndProc DISKREAD
781
782CODE ENDS
783 END
784 \ No newline at end of file
diff --git a/v4.0/src/DOS/DISK3.ASM b/v4.0/src/DOS/DISK3.ASM
new file mode 100644
index 0000000..306b34e
--- /dev/null
+++ b/v4.0/src/DOS/DISK3.ASM
@@ -0,0 +1,662 @@
1; SCCSID = @(#)disk3.asm 1.3 85/07/26
2; SCCSID = @(#)disk3.asm 1.3 85/07/26
3TITLE DISK3 - Disk utility routines
4NAME Disk3
5; Low level Read and write routines for local SFT I/O on files and devs
6;
7; DISKWRITE
8; WRTERR
9;
10; Revision history:
11;
12; AN000 version 4.00 Jan. 1988
13;
14
15;
16; get the appropriate segment definitions
17;
18.xlist
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xcref
25INCLUDE DOSSYM.INC
26INCLUDE DEVSYM.INC
27include version.inc
28.cref
29.list
30
31Installed = TRUE
32
33 i_need THISSFT,DWORD
34 i_need DMAADD,DWORD
35 i_need SecClusPos,BYTE
36 i_need ClusNum,WORD
37 i_need Trans,BYTE
38 i_need BytPos,4
39 i_need SecPos,DWORD ;F.C. >32mb ;AN000;
40 i_need BytSecPos,WORD
41 i_need BytCnt1,WORD
42 i_need BytCnt2,WORD
43 i_need SecCnt,WORD
44 i_need ThisDPB,DWORD
45 i_need LastPos,WORD
46 i_need ValSec,WORD ;F.C. >32mb ;AN000;
47 i_need GrowCnt,DWORD
48 i_need ALLOWED,BYTE
49 I_need JShare,DWORD
50 I_need FSeek_drive,BYTE ; DOS 4.00 ;AN000;
51 I_need FSeek_firclus,WORD ; DOS 4.00 ;AN000;
52 I_need FSeek_logclus,WORD ; DOS 4.00 ;AN000;
53 I_need HIGH_SECTOR,WORD ;F.C. >32mb ;AN000;
54 I_need HIGH_SECTOR_TEMP,WORD ;F.C. >32mb ;AN000;
55 I_need EXTERR,WORD ; DOS 4.00 ;AN000;
56 I_need EXTERR_LOCUS,BYTE ; DOS 4.00 ;AN000;
57 I_need EXTERR_ACTION,BYTE ; DOS 4.00 ;AN000;
58 I_need EXTERR_CLASS,BYTE ; DOS 4.00 ;AN000;
59 I_need EXITHOLD,DWORD ; DOS 4.00 ;AN000;
60 I_need DISK_FULL,BYTE ; DOS 4.00 ;AN000;
61 I_need SC_DRIVE,BYTE ; DOS 4.00 ;AN000;
62 I_need SC_CACHE_COUNT,WORD ; DOS 4.00 ;AN000;
63 I_need ThisDRV,BYTE ; DOS 4.00 ;AN000;
64 I_need User_In_AX,WORD ; DOS 4.00 ;AN000;
65 I_need DOS34_FLAG,WORD ; DOS 4.00 ;AN000;
66 I_need FIRST_BUFF_ADDR,WORD ; DOS 4.00 ;AN000;
67
68IF BUFFERFLAG
69 EXTRN SAVE_MAP:NEAR
70 EXTRN RESTORE_MAP:NEAR
71 EXTRN SAVE_USER_MAP:NEAR
72 EXTRN RESTORE_USER_MAP:NEAR
73 i_need BUF_EMS_SAFE_FLAG,BYTE
74 i_need BUF_EMS_MODE,BYTE
75ENDIF
76
77
78
79Break <DISKWRITE -- PERFORM USER DISK WRITE>
80
81; Inputs:
82; Outputs of SETUP
83; Function:
84; Perform disk write
85; Outputs:
86; Carry clear
87; CX = No. of bytes read
88; ES:DI point to SFT
89; SFT offset and cluster pointers updated
90; Carry set
91; CX = 0
92; ES:DI point to SFT
93; AX has error code
94
95 procedure DISKWRITE,NEAR
96 DOSAssume CS,<DS>,"DiskWrite"
97 ASSUME ES:NOTHING
98
99 Assert ISSFT,<ES,DI>,"DiskWrite"
100 PUSH ES:[DI.sf_firclus] ; set up 1st cluster # for FastSeek
101 POP [FSeek_firclus]
102
103 invoke CHECK_WRITE_LOCK ;IFS. check write lock ;AN000;
104 JNC WRITE_OK ;IFS. lock check ok ;AN000;
105 return
106
107WRTEOFJ:
108 JMP WRTEOF
109
110WRITE_OK:
111 AND ES:[DI.sf_flags],NOT (sf_close_nodate OR devid_file_clean)
112 ; Mark file as dirty, clear no date on close
113 LES BP,[THISDPB]
114 Assert ISDPB,<ES,BP>,"DiskWrite/WriteOk"
115 MOV AL,ES:[BP.dpb_drive] ; set up drive # for FastSeek
116 MOV [FSeek_drive],AL ; 11/5/86 DOS 4.00
117
118 invoke BREAKDOWN
119 MOV AX,WORD PTR [BYTPOS]
120 MOV DX,WORD PTR [BYTPOS+2]
121 JCXZ WRTEOFJ ;Make the file length = sf_position
122 ADD AX,CX
123 ADC DX,0 ; AX:DX=byte after last byte accessed
124;
125; Make sure divide won't overflow
126;
127 MOV BX,ES:[BP.dpb_sector_size]
128; CMP DX,BX ;F.C. >32mb 16 bit sector check ;AN000;
129; JAE WrtErr ;F.C. >32mb ;AN000;
130
131 CALL DIV32 ;F.C. perform 32 bit divide ;AN000;
132 MOV BX,AX ; Save last full sector
133 OR DX,DX
134 JNZ CALCLUS
135 SUB AX,1 ; AX must be zero base indexed ;AC000;
136 SBB [HIGH_SECTOR],0 ;F.C. >32mb ;AN000;
137CALCLUS:
138 PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000;
139 CALL SHR32 ;F.C. >32mb ;AN000;
140 POP [HIGH_SECTOR] ;F.C. >32mb ;AN000;
141
142; SHR AX,CL ; Last cluster to be accessed
143 PUSH AX
144 PUSH DX ; Save the size of the "tail"
145 PUSH ES
146 LES DI,[THISSFT]
147 Assert ISSFT,<ES,DI>,"DiskWrite/CalClus"
148 MOV AX,WORD PTR ES:[DI.sf_size]
149 MOV DX,WORD PTR ES:[DI.sf_size+2]
150 POP ES
151
152
153
154 PUSH AX ;F.C. >32mb ;AN000;
155 MOV AX,DX ;F.C. >32mb ;AN000;
156 XOR DX,DX ;F.C. >32mb ;AN000;
157 DIV ES:[BP.dpb_sector_size] ;F.C. >32mb ;AN000;
158 MOV [HIGH_SECTOR_TEMP],AX ;F.C. >32mb ;AN000;
159 POP AX ;F.C. >32mb ;AN000;
160
161 DIV ES:[BP.dpb_sector_size]
162 MOV CX,AX ; Save last full sector of current file
163 OR DX,DX
164 JZ NORNDUP
165 ADD AX,1 ; Round up if any remainder ;AC000;
166 ADC [HIGH_SECTOR_TEMP],0 ;F.C. >32mb ;AN000;
167NORNDUP:
168 PUSH [HIGH_SECTOR_TEMP] ;F.C. >32mb ;AN000;
169 POP WORD PTR [VALSEC+2] ;F.C. >32mb ;AN000;
170 MOV WORD PTR [VALSEC],AX ;Number of sectors that have been written
171 XOR AX,AX
172 MOV WORD PTR [GROWCNT],AX
173 MOV WORD PTR [GROWCNT+2],AX
174 POP AX
175
176 MOV DI,[HIGH_SECTOR] ;F.C. >32mb ;AN000;
177 CMP DI,[HIGH_SECTOR_TEMP] ;F.C. >32mb ;AN000;
178 JB NOGROW ;F.C. >32mb ;AN000;
179 JZ lowsec ;F.C. >32mb ;AN000;
180 SUB BX,CX ;F.C. >32mb ;AN000;
181 SBB DI,[HIGH_SECTOR_TEMP] ;F.C. >32mb di:bx no. of sectors ;AN000;
182 JMP yesgrow ;F.C. >32mb ;AN000;
183lowsec:
184 MOV DI,0 ;F.C. >32mb
185 SUB BX,CX ; Number of full sectors
186 JB NOGROW
187 JZ TESTTAIL
188yesgrow:
189 MOV CX,DX
190 XCHG AX,BX
191 MUL ES:[BP.dpb_sector_size] ; Bytes of full sector growth
192 MOV [HIGH_SECTOR],DX ;F.C. >32mb save dx ;AN000;
193 MOV [HIGH_SECTOR_TEMP],AX ;F.C. >32mb save ax ;AN000;
194 MOV AX,DI ;F.C. >32mb ;AN000;
195 MUL ES:[BP.dpb_sector_size] ;F.C. >32mb do higher word multiply ;AN000;
196 ADD AX,[HIGH_SECTOR] ;F.C. >32mb add lower value ;AN000;
197 MOV DX,AX ;F.C. >32mb DX:AX is the result of ;AN000;
198 MOV AX,[HIGH_SECTOR_TEMP] ;F.C. >32mb a 32 bit multiply ;AN000;
199
200 SUB AX,CX ; Take off current "tail"
201 SBB DX,0 ; 32-bit extension
202 ADD AX,BX ; Add on new "tail"
203 ADC DX,0 ; ripple tim's head off
204 JMP SHORT SETGRW
205HAVSTART:
206;int 3
207 MOV CX,AX
208 invoke SKPCLP
209 JCXZ DOWRTJ
210;;; 11/5/86 FastSeek
211 MOV [FSeek_logclus],DX ; delete EOF (FFFFH)
212 INC [FSeek_logclus]
213 invoke FastSeek_Truncate ;
214;;; 11/5/86 FastSeek
215 invoke ALLOCATE
216 JNC DOWRTJ
217
218 entry WRTERR
219 DOSAssume CS,<DS>,"DiskWrite/WrtErr"
220 ASSUME ES:NOTHING
221
222 MOV AH,0FH ;MS. write/data/fail/abort ;AN000;
223 entry WRTERR22
224 MOV AL,[THISDRV] ;MS. ;AN000;
225 CALL File_Handle_Fail_Error ;MS. issue disk full I24
226 MOV CX,0 ;No bytes transferred
227; XOR CX,CX ; will be deleted
228 LES DI,[THISSFT]
229 Assert ISSFT,<ES,DI>,"DiskWrite/WrtErr"
230; CLC
231 return
232
233DOWRTJ: JMP DOWRT
234
235ACC_ERRWJ:
236 JMP SET_ACC_ERRW
237
238TESTTAIL:
239 SUB AX,DX
240 JBE NOGROW
241 XOR DX,DX
242SETGRW:
243 MOV WORD PTR [GROWCNT],AX
244 MOV WORD PTR [GROWCNT+2],DX
245NOGROW:
246 POP AX
247 MOV CX,[CLUSNUM] ; First cluster accessed
248 invoke FNDCLUS
249 JC ACC_ERRWJ
250 MOV [CLUSNUM],BX
251 MOV [LASTPOS],DX
252;;; 11/5/86 FastSeek
253 MOV [FSeek_logclus],AX ; set up last position
254 SUB AX,DX ; Last cluster minus current cluster
255 JZ DOWRT ; If we have last clus, we must have first
256 JCXZ HAVSTART ; See if no more data
257 PUSH CX ; No. of clusters short of first
258 MOV CX,AX
259
260;;; 11/5/86 FastSeek
261 CMP [CLUSNUM],0 ;FS. null file ;AN000;
262 JZ NULL_FILE ;FS. yes ;AN000;
263 MOV [FSeek_logclus],DX ;FS. delete EOF (FFFFH) ;AN000;
264 INC [FSeek_logclus] ;FS. ;AN000;
265 invoke FastSeek_Truncate ;FS. ;AN000;
266NULL_FILE:
267;;; 11/5/86 FastSeek
268 invoke ALLOCATE
269 POP AX
270 JC WRTERR
271 MOV CX,AX
272 MOV DX,[LASTPOS]
273 INC DX
274 DEC CX
275 JZ NOSKIP
276;;; 11/5/86 FastSeek
277 MOV [FSeek_logclus],DX ;
278 ADD [FSeek_logclus],CX ; set up last position
279 invoke SKPCLP
280 JC ACC_ERRWJ
281NOSKIP:
282 MOV [CLUSNUM],BX
283 MOV [LASTPOS],DX
284DOWRT:
285 CMP [BYTCNT1],0
286 JZ WRTMID
287 MOV BX,[CLUSNUM]
288 invoke BUFWRT
289 JC ACC_ERRWJ
290WRTMID:
291 MOV AX,[SECCNT]
292 OR AX,AX
293 JNZ havemid
294 JMP WRTLAST
295havemid:
296 ADD WORD PTR [SECPOS],AX
297 ADC WORD PTR [SECPOS+2],0 ;F.C. >32mb ;AN000;
298 invoke NEXTSEC
299 JNC gotok
300 JMP ACC_ERRWJ
301gotok:
302 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
303 MOV DL,[SECCLUSPOS]
304 MOV BX,[CLUSNUM]
305 MOV CX,[SECCNT]
306WRTLP:
307 invoke OPTIMIZE
308 JNC wokok
309 JMP ACC_ERRWJ
310wokok:
311 PUSH DI
312 PUSH AX
313 PUSH DX
314 PUSH BX
315 Assert ISDPB,<ES,BP>,"DiskWrite/WrtLp"
316 MOV AL,ES:[BP.dpb_drive]
317 MOV [SC_DRIVE],AL ;LB. save it for INVALIDATE_SC ;AN000;
318 PUSH CX ;LB. ;AN000;
319 PUSH [HIGH_SECTOR] ;LB. ;AN000;
320SCANNEXT: ;LB. ;AN000;
321 invoke GETCURHEAD ;LB. ;AN000;
322ASSUME DS:NOTHING
323NEXTBUFF: ; Search for buffers
324 CMP [SC_CACHE_COUNT],0 ;LB. SC support ? ;AN000;
325 JZ nosc ;LB. no ;AN000;
326 PUSH AX ;LB. save reg ;AN000;
327 PUSH CX ;LB. save reg ;AN000;
328 PUSH DX ;LB. save reg ;AN000;
329 invoke INVALIDATE_SC ;LB. invalidate SC ;AN000;
330 POP DX ;LB. save reg ;AN000;
331 POP CX ;LB. save reg ;AN000;
332 POP AX ;LB. save reg ;AN000;
333nosc:
334 CALL BUFF_RANGE_CHECK ;F.C. >32mb ;AN000;
335 JNC inrange2 ;F.C. >32mb ;AN000;
336 mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000;
337 JMP DONEXTBUFF ;LB. ;AN000;
338inrange2:
339 TEST [DI.buf_flags],buf_dirty ;LB. if dirty ;AN000;
340 JZ not_dirty ;LB. ;AN000;
341 invoke DEC_DIRTY_COUNT ;LB. then decrement dirty count ;AN000;
342not_dirty:
343 MOV WORD PTR [DI.buf_ID],(buf_visit SHL 8) OR 0FFH ; Free the buffer, it is being over written
344 invoke SCANPLACE
345DONEXTBUFF:
346 CMP DI,[FIRST_BUFF_ADDR] ;LB. end of chain ;AN000;
347 JNZ NEXTBUFF ;LB. no ;AN000;
348 ADD DX,1 ;LB. next sector number ;AN000;
349 ADC [HIGH_SECTOR],0 ;LB. ;AN000;
350 LOOP SCANNEXT ;LB. check again ;AN000;
351 POP [HIGH_SECTOR] ;LB. ;AN000;
352 POP CX ;LB. get count back ;AN000;
353
354 POP BX
355 POP DX
356 MOV DS,WORD PTR [DMAADD+2]
357 MOV [ALLOWED],allowed_RETRY + allowed_FAIL + allowed_IGNORE
358
359IF BUFFERFLAG
360 pushf
361 cmp [BUF_EMS_MODE], -1
362 je safe_write
363 call save_map
364 call restore_user_map
365safe_write:
366 popf
367ENDIF
368
369 invoke DWRITE
370
371IF BUFFERFLAG
372 pushf
373 cmp [BUF_EMS_MODE], -1
374 je safe_map
375 call save_user_map
376 call restore_map
377safe_map:
378 popf
379ENDIF
380
381 POP CX
382 POP BX
383 Context DS
384 JC SET_ACC_ERRW
385 JCXZ WRTLAST
386 MOV DL,0
387 INC [LASTPOS] ; We'll be using next cluster
388 JMP WRTLP
389
390WRTLAST:
391 MOV AX,[BYTCNT2]
392 OR AX,AX
393 JZ FINWRT
394 MOV [BYTCNT1],AX
395 invoke NEXTSEC
396 JC SET_ACC_ERRW
397 MOV [BYTSECPOS],0
398 invoke BUFWRT
399 JC SET_ACC_ERRW
400FINWRT:
401 LES DI,[THISSFT]
402 Assert ISSFT,<ES,DI>,"DiskWrite/FinWrt"
403 MOV AX,WORD PTR [GROWCNT]
404 MOV CX,WORD PTR [GROWCNT+2]
405 OR AX,AX
406 JNZ UPDATE_size
407 JCXZ SAMSIZ
408Update_size:
409 ADD WORD PTR ES:[DI.sf_size],AX
410 ADC WORD PTR ES:[DI.sf_size+2],CX
411;
412; Make sure that all other SFT's see this growth also.
413;
414 MOV AX,1
415if installed
416 call JShare + 14 * 4
417else
418 Call ShSU
419endif
420SAMSIZ:
421 transfer SETCLUS ; ES:DI already points to SFT
422
423SET_ACC_ERRW:
424 transfer SET_ACC_ERR_DS
425
426WRTEOF:
427 MOV CX,AX
428 OR CX,DX
429 JZ KILLFIL
430 SUB AX,1
431 SBB DX,0
432
433 PUSH BX
434 MOV BX,ES:[BP.dpb_sector_size] ;F.C. >32mb ;AN000;
435 CALL DIV32 ;F.C. >32mb ;AN000;
436 POP BX ;F.C. >32mb ;AN000;
437 CALL SHR32 ;F.C. >32mb ;AN000;
438
439
440; SHR AX,CL
441 MOV CX,AX
442 invoke FNDCLUS
443SET_ACC_ERRWJ2:
444 JC SET_ACC_ERRW
445;;; 11/5/86 FastSeek
446 MOV [FSeek_logclus],DX ; truncate clusters starting from DX
447 invoke FastSeek_Truncate
448;;; 11/5/86 FastSeek
449 JCXZ RELFILE
450 invoke ALLOCATE
451 JC WRTERRJ ;;;;;;;;; disk full
452UPDATE:
453 LES DI,[THISSFT]
454 Assert ISSFT,<ES,DI>,"DiskWrite/update"
455 MOV AX,WORD PTR [BYTPOS]
456 MOV WORD PTR ES:[DI.sf_size],AX
457 MOV AX,WORD PTR [BYTPOS+2]
458 MOV WORD PTR ES:[DI.sf_size+2],AX
459;
460; Make sure that all other SFT's see this growth also.
461;
462 MOV AX,2
463if installed
464 Call JShare + 14 * 4
465else
466 Call ShSU
467endif
468 XOR CX,CX
469 transfer ADDREC
470
471WRTERRJ: JMP WRTERR
472;;;;;;;;;;;;;;;; 7/18/86
473;;;;;;;;;;;;;;;;;
474RELFILE:
475 MOV DX,0FFFFH
476 invoke RELBLKS
477Set_Acc_ERRWJJ:
478 JC SET_ACC_ERRWJ2
479 JMP SHORT UPDATE
480
481KILLFIL:
482 XOR BX,BX
483 PUSH ES
484 LES DI,[THISSFT]
485 Assert ISSFT,<ES,DI>,"DiskWrite/KillFil"
486 MOV ES:[DI.sf_cluspos],BX
487 MOV ES:[DI.sf_lstclus],BX
488 XCHG BX,ES:[DI.sf_firclus]
489 POP ES
490;; 11/5/86 FastSeek
491 invoke Delete_FSeek ; delete fastseek entry
492
493 OR BX,BX
494 JZ UPDATEJ
495;; 10/23/86 FastOpen update
496 PUSH ES ; since first cluster # is 0
497 PUSH BP ; we must delete the old cache entry
498 PUSH AX
499 PUSH CX
500 PUSH DX
501 LES BP,[THISDPB] ; get current DPB
502 MOV DL,ES:[BP.dpb_drive] ; get current drive
503 MOV CX,BX ; first cluster #
504 MOV AH,2 ; delete cache entry by drive:firclus
505 invoke FastOpen_Update ; call fastopen
506 POP DX
507 POP CX
508 POP AX
509 POP BP
510 POP ES
511;; 10/23/86 FastOpen update
512
513 invoke RELEASE
514 JC SET_ACC_ERRWJJ
515UpDateJ:
516 JMP UPDATE
517EndProc DISKWRITE
518
519
520
521Break <DIV32 -- PERFORM 32 BIT DIVIDE>
522
523; Inputs:
524; DX:AX = 32 bit dividend BX= divisor
525; Function:
526; Perform 32 bit division
527; Outputs:
528; [HIGH_SECTOR]:AX = quotiend , DX= remainder
529
530 procedure DIV32,NEAR
531 ASSUME DS:NOTHING,ES:NOTHING
532
533
534 PUSH AX ;F.C. >32mb ;AN000;
535 MOV AX,DX ;F.C. >32mb ;AN000;
536 XOR DX,DX ;F.C. >32mb ;AN000;
537 DIV BX ;F.C. >32mb ;AN000;
538 MOV [HIGH_SECTOR],AX ;F.C. >32mb ;AN000;
539 POP AX ;F.C. >32mb ;AN000;
540
541
542 DIV BX ; AX=last sector accessed
543 return
544
545EndProc DIV32
546
547Break <SHR32 -- PERFORM 32 BIT SHIFT RIGHT>
548
549; Inputs:
550; [HIGH_SECTOR]:AX = 32 bit sector number
551; Function:
552; Perform 32 bit shift right
553; Outputs:
554; AX= cluster number
555
556 procedure SHR32,NEAR
557 ASSUME DS:NOTHING,ES:NOTHING
558
559
560 MOV CL,ES:[BP.dpb_cluster_shift]
561 XOR CH,CH
562entry ROTASHFT ;F.C. >32mb ;AN000;
563 OR CX,CX ;F.C. >32mb ;AN000;
564 JZ norota ;F.C. >32mb ;AN000;
565ROTASHFT2:
566 CLC ;F.C. >32mb ;AN000;
567 RCR [HIGH_SECTOR],1 ;F.C. >32mb ;AN000;
568 RCR AX,1 ;F.C. >32mb ;AN000;
569 LOOP ROTASHFT2 ;F.C. >32mb: ;AN000;
570norota:
571 return
572
573EndProc SHR32
574
575
576; Issue File Handle Fail INT 24 Critical Error
577; Input: Disk_Full=0 ok
578; 1 disk full or EOF
579; Function: issue critical error for disk full or EOF error
580;
581; OutPut: carry clear , no I24
582; carry set, fail from I24
583
584procedure File_Handle_Fail_Error,NEAR ;AN000;
585 ASSUME ES:NOTHING,DS:NOTHING ;AN000;
586 ;AN000;
587 CMP [DISK_FULL],0 ;MS. disk full or EOF ;AN000;
588 JZ Fexit ;MS. no ;AN000;
589 TEST [DOS34_FLAG],Disable_EOF_I24 ;MS. check input status ? ;AN000;
590 JNZ Fexit ;MS. yes ;AN000;
591 ;AN000;
592 LES DI,[THISSFT] ;MS. get current SFT ;AN000;
593; LES DI,ES:[DI.sf_DEVPTR];MS. get device header ;AN000;
594 TEST ES:[DI.sf_flags],Handle_Fail_I24 ;MS. gen I24 ? ;AN000;
595 JZ Fexit ;MS. no ;AN000;
596 PUSH DS ;MS. save DS ;AN000;
597 TEST AH,1 ;MS. READ ? ;AN000;
598 JZ readeof ;MS. yes ;AN000;
599 MOV [EXTERR],error_Handle_Disk_Full ;MS. set extended error ;AN000;
600 JMP SHORT errset ;MS. set extended error ;AN000;
601readeof:
602 MOV [EXTERR],error_Handle_EOF ;MS. set extended error ;AN000;
603errset:
604 MOV [EXTERR_CLASS],errCLASS_OutRes ;MS. set class ;AN000;
605 MOV [EXTERR_ACTION],errACT_Abort ;MS. set action ;AN000;
606 MOV [EXTERR_LOCUS],errLOC_Unk ;MS. set locus ;AN000;
607 MOV word ptr [EXITHOLD + 2],ES ;MS. save es:bp in exithold ;AN000;
608 MOV word ptr [EXITHOLD],BP ;MS. ;AN000;
609 TEST ES:[DI.sf_flags],devid_device ;MS. device ? ;AN000;
610 JNZ chardev2 ;MS. yes ;AN000;
611 LDS SI,ES:[DI.sf_DEVPTR] ;MS. get dpb ;AN000;
612 LDS SI,[SI.dpb_driver_addr] ;MS. get drive device haeder ;AN000;
613 JMP SHORT doi24 ;MS. gen I24 ? ;AN000;
614chardev2:
615 LDS SI,ES:[DI.sf_DEVPTR] ;MS. get chr dev header ;AN000;
616doi24:
617 MOV BP,DS ;MS. bp:si -> device header ;AN000;
618 MOV DI,error_I24_gen_failure ;MS. general error ;AN000;
619 invoke NET_I24_ENTRY ;MS. issue I24 ;AN000;
620 STC ;MS. must be fail ;AN000;
621 POP DS ;MS. restore DS ;AN000;
622 MOV AX,[EXTERR] ;MS. set error ;AN000;
623 JMP SHORT Fend ;MS. exit ;AN000;
624Fexit: ;AN000;
625 CLC ;MS. clear carry ;AN000;
626Fend: ;AN000;
627 return ;MS. ;AN000;
628 ;AN000;
629EndProc File_Handle_Fail_Error ;AN000;
630
631
632Break <BUFF_RANGE_CHECK- buffer range checkink>
633
634; Inputs:
635; DS:DI -> buffer. AL= drive #
636; [HIGH_SECTOR]:DX = sector #
637; Function:
638; check if sector is in the buffer
639; Outputs:
640; carry clear= in the range
641; set = not in the range
642
643 procedure BUFF_RANGE_CHECK,NEAR
644 ASSUME DS:NOTHING,ES:NOTHING
645
646 CMP WORD PTR [DI.buf_sector],DX ;AN000;
647 JNZ DONEXTBUFF2 ; not this sector ;F.C. >32mb ;AN000;
648 MOV SI,[HIGH_SECTOR] ;F.C. >32mb ;AN000;
649 CMP WORD PTR [DI.buf_sector+2],SI ;F.C. >32mb ;AN000;
650 JNZ DONEXTBUFF2 ; Not for this drive
651 CMP AL,[DI.buf_ID]
652 JZ secfound ; Buffer has the sector ;AN000;
653DONEXTBUFF2:
654 STC
655secfound:
656 return
657
658EndProc BUFF_RANGE_CHECK
659
660CODE ENDS
661 END
662 \ No newline at end of file
diff --git a/v4.0/src/DOS/DISP.ASM b/v4.0/src/DOS/DISP.ASM
new file mode 100644
index 0000000..fba9764
--- /dev/null
+++ b/v4.0/src/DOS/DISP.ASM
@@ -0,0 +1,579 @@
1; SCCSID = @(#)disp.asm 1.1 85/04/10
2; SCCSID = @(#)disp.asm 1.1 85/04/10
3;
4; Dispatcher code
5;
6
7.xlist
8.xcref
9INCLUDE DOSSYM.INC
10include dosseg.asm
11.cref
12.list
13
14AsmVars <Kanji, Debug>
15
16BREAK <Copyright notice and version>
17CODE SEGMENT BYTE PUBLIC 'CODE'
18
19
20 I_need CurrentPDB,WORD
21 I_need CntCFlag,BYTE
22 I_need User_SS,WORD
23 I_need User_SP,WORD
24 I_need NSS,WORD
25 I_need NSP,WORD
26 I_need MaxCall,BYTE
27 I_need MaxCom,BYTE
28 I_need SaveDS,WORD
29 I_need SaveBX,WORD
30 I_need INDOS,BYTE
31 I_need User_ID,WORD
32 I_need Proc_ID,WORD
33 I_need AuxStack,BYTE
34 I_need IOSTACK,BYTE
35 I_need DSKSTACK,BYTE
36 I_need fsharing,BYTE
37 I_need NoSetDir,BYTE
38 I_need FailERR,BYTE
39 I_need Errormode,BYTE
40 I_need restore_tmp,WORD
41 I_need WPERR,BYTE
42 I_need Dispatch,WORD
43 I_need ConSwap,BYTE
44 I_need User_In_AX,WORD
45 I_need EXTERR_LOCUS,BYTE
46 I_need IdleInt,BYTE
47 I_need Printer_Flag,BYTE
48 I_need CPSWFLAG,BYTE ;AN000;
49 I_need CPSWSAVE,BYTE ;AN000;
50 I_need DISK_FULL,BYTE ;AN000;
51 I_need InterCon,BYTE ;AN000;
52 I_need BOOTDRIVE,BYTE ;AN000;
53 I_need EXTOPEN_ON,BYTE ;AN000;
54 I_need DOS34_FLAG,WORD ;AN000;
55 I_need ACT_PAGE,WORD ;AN000;
56
57 IF NOT IBM
58 I_need OEM_HANDLER,DWORD
59 ENDIF
60
61 IF BUFFERFLAG
62 I_am SETVECTFLAG,BYTE,<0>
63 i_need BUF_EMS_SEG_CNT,WORD ; DOS 4.00 EMS seg count ;AN000;
64 i_need BUF_EMS_MODE,BYTE ; DOS 4.00 EMS mode ;AN000;
65 i_am BUF_EMS_MAP_USER,12,<0,0,0,0,0,0,0,0,0,0,0,0>
66 ENDIF
67
68ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
69
70BREAK <System call entry points and dispatcher>
71ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
72
73BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher>
74
75; Inputs:
76; AL = 0 read ^C status
77; AL = 1 Set ^C status, DL = 0/1 for ^C off/on
78; AL = 2 Set ^C status to contents of DL. Output is old state.
79; AL = 3 Get CPSW state to DL DOS 3.4
80; AL = 4 Set CPSW state from DL DOS 3.4
81; AL = 5 get DOS boot drive
82; Function:
83; Enable disable ^C checking in dispatcher
84; Outputs:
85; If AL = 0 then DL = 0/1 for ^C off/on
86
87 procedure $SET_CTRL_C_TRAPPING,NEAR
88ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
89 OR AL,AL
90 JNZ Check1
91 MOV DL,CntCFlag
92 IRET
93Check1:
94 CMP AL,2
95 JA CPSWchk ;AN000;
96 JZ SetAndRet
97 PUSH DX
98 AND DL,01h
99 MOV [CNTCFLAG],DL
100 POP DX
101 IRET
102SetAndRet:
103 AND DL,01h
104 XCHG CntCFlag,DL
105 IRET
106BadVal:
107 MOV AL,0FFH
108 IRET
109;; DOS 4.00 File Tagging
110
111CPSWchk: ;AN000;
112; PUSH AX ;AN000;;FT.
113; MOV AL,[CPSWSAVE] ;AN000;;FT. DOS 3.4
114; MOV [CPSWFLAG],AL ;AN000;;FT. DOS 3.4 in case ABORT
115; POP AX ;AN000;;FT.
116 CMP AL,3 ;AN000;;FT get CPSW state ?
117 JNZ CPSWset ;AN000;;FT. no
118; MOV DL,CPSWFLAG ;AN000;;FT. return CPSW state
119 IRET ;AN000;
120CPSWset: ;AN000;
121 CMP AL,4 ;AN000;;FT. set CPSW state ?
122 JA QueryDOSboot ;AN000;;FT. check query dos boot drive
123; PUSH AX ;AN000;;FT.
124; CallInstall NLSInstall,NLSFUNC,0 ;AN000;;FT. NLSFUNC installed ?
125; CMP AL,0FFH ;AN000;;FT.
126; POP AX ;AN000;;FT.
127; JNZ BadVal ;AN000;;FT. not loaded, therefore ignore
128;;;; AND DL,01H ;AN000;;FT. only 0 or 1
129;;;; MOV [CPSWFLAG],DL ;AN000;;FT. set the flag
130;;;; MOV [CPSWSAVE],DL ;AN000;;FT. save one copy
131 IRET ;AN000;;FT.
132QueryDOSboot: ;AN000;
133 CMP AL,5 ;AN000;MS.
134 JA BadVal ;AN000;MS.
135 MOV DL,[BOOTDRIVE] ;AN000;;MS. put boot drive in DL
136 IRET ;AN000;;MS.
137
138
139;; DOS 4.00 File Tagging
140
141EndProc $SET_CTRL_C_TRAPPING
142
143BREAK <$Get_current_PDB -- Set/Get PDB value>
144;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
145; C A V E A T P R O G R A M M E R ;
146; ;
147; The following two routines are dispatched to directly with ints disabled
148; immediately after the int 21h entry. no DIS state is set.
149;
150; $Set_current_PDB takes BX and sets it to be the current process
151; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
152;
153 procedure $SET_CURRENT_PDB,NEAR
154 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
155 MOV [CurrentPDB],BX
156 IRET
157EndProc $SET_CURRENT_PDB
158
159;
160; $get_current_PDB returns in BX the current process
161; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
162;
163procedure $GET_CURRENT_PDB,NEAR
164 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
165 MOV BX,[CurrentPDB]
166 IRET
167EndProc $GET_CURRENT_PDB
168; C A V E A T P R O G R A M M E R ;
169; ;
170;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
171
172;
173; Sets the Printer Flag to whatever is in AL.
174; NOTE: THIS PROCEDURE IS SUBJECT TO CHANGE!!!
175;
176Procedure $Set_Printer_Flag
177ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING
178 mov [Printer_Flag],al
179 IRET
180EndProc $Set_Printer_Flag
181
182 procedure SYSTEM_CALL,NEAR
183;
184; The Quit entry point is where all INT 20h's come from. These are old- style
185; exit system calls. The CS of the caller indicates which Process is dying.
186; The error code is presumed to be 0. We simulate an ABORT system call.
187;
188 entry QUIT
189 MOV AH,0
190 JMP SHORT SAVREGS
191;
192; The system call in AH is out of the range that we know how to handle. We
193; arbitrarily set the contents of AL to 0 and IRET. Note that we CANNOT set
194; the carry flag to indicate an error as this may break some programs
195; compatability.
196;
197BADCALL:
198 MOV AL,0
199 entry IRETT
200 IRET
201;
202; An alternative method of entering the system is to perform a CALL 5 in the
203; program segment prefix with the contents of CL indicating what system call
204; the user would like. A subset of the possible system calls is allowed here;
205; only the CPM-compatible calls may get dispatched.
206;
207 entry CALL_ENTRY ; System call entry point and dispatcher
208 POP AX ; IP from the long call at 5
209 POP AX ; Segment from the long call at 5
210 POP [User_SP] ; IP from the CALL 5
211;
212; Re order the stack to simulate an interrupt 21.
213;
214 PUSHF ; Start re-ordering the stack
215 CLI
216 PUSH AX ; Save segment
217 PUSH [User_SP] ; Stack now ordered as if INT had been used
218 CMP CL,MAXCALL ; This entry point doesn't get as many calls
219 JA BADCALL
220 MOV AH,CL
221 JMP SHORT SavRegs
222;
223; This is the normal INT 21 entry point. We first perform a quick test to see
224; if we need to perform expensive DOS-entry functions. Certain system calls
225; are done without interrupts being enabled.
226;
227
228entry COMMAND ; Interrupt call entry point (INT 21H)
229
230 IF NOT IBM
231 CMP AH,SET_OEM_HANDLER
232 JB NOTOEM
233 JMP $SET_OEM_HANDLER
234NOTOEM:
235 ENDIF
236
237 CMP AH,MAXCOM
238 JA BadCall
239
240;
241; The following set of calls are issued by the server at *arbitrary* times
242; and, therefore, must be executed on the user's entry stack and executed with
243; interrupts off.
244;
245SAVREGS:
246 CMP AH,GET_CURRENT_PDB
247 JZ $GET_CURRENT_PDB
248 CMP AH,GetCurrentPSP
249 JZ $GET_CURRENT_PDB
250 CMP AH,SET_CURRENT_PDB
251 JZ $SET_CURRENT_PDB
252 CMP AH,Set_CTRL_C_Trapping
253 JNZ chkprt
254 JMP $Set_CTRL_C_Trapping
255chkprt:
256 CMP AH,SET_PRINTER_FLAG
257 JZ $Set_Printer_Flag
258;
259; Preserve all user's registers on his own stack.
260;
261 CALL save_world
262 MOV [SaveDS],DS
263 MOV [SaveBX],BX
264 MOV BX,CS
265 MOV DS,BX
266 ASSUME DS:DOSGROUP
267 INC [INDOS] ; Flag that we're in the DOS
268 XOR AX,AX
269 MOV [USER_ID],AX
270 MOV AX,CurrentPDB ; current process
271 MOV [PROC_ID],AX ; Assume local machine for the moment
272;
273; Provide one level of reentrancy for INT 24 recallability.
274;
275 MOV AX,[user_SP]
276 MOV [NSP],AX
277 MOV AX,[user_SS]
278 MOV [NSS],AX
279 POP AX
280 PUSH AX
281 MOV [user_SP],SP
282 MOV [user_SS],SS
283;
284; save user stack in his area for later returns (possibly from EXEC)
285;
286 MOV DS,[CurrentPDB]
287ASSUME DS:NOTHING
288 MOV WORD PTR DS:[PDB_User_stack],SP
289 MOV WORD PTR DS:[PDB_User_stack+2],SS
290
291 MOV fSharing,0 ; allow redirection
292
293 MOV BX,CS ; no holes here.
294 MOV SS,BX
295ASSUME SS:DOSGROUP
296
297entry REDISP
298 MOV SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts
299 STI ; stack is in our space now...
300 IF DBCS ;AN000;
301 MOV BH, BYTE PTR DS:[PDB_InterCon] ;AN000;; get interim mode 2/13/KK
302 MOV SS:[InterCon], BH ;AN000;; 2/13/KK
303 ENDIF ;AN000;
304 MOV BX,CS
305 MOV DS,BX
306 DOSAssume CS,<DS>,"MSCODE/ReDisp"
307;; DOS 3.4 INIT
308; MOV BL,[CPSWSAVE] ;AN000;;FT. DOS 3.4
309; MOV [CPSWFLAG],BL ;AN000;;FT. DOS 3.4 in case ABORT
310 MOV [DISK_FULL],0 ;AN000;;MS. no disk full
311 MOV [EXTOPEN_ON],0 ;AN000;;EO. clear extended open flag
312 MOV [DOS34_FLAG],0 ;AN000;;MS. clear common flag
313 MOV [ACT_PAGE],-1 ;BN000;BL;AN000;;LB. invalidate active page
314;; DOS 4.00 INIT
315 XOR BH,BH
316 MOV [CONSWAP],BH ; random clean up of possibly mis-set flags
317 MOV [IDLEINT],1 ; presume that we can issue INT 28
318 MOV BYTE PTR [NoSetDir],BH ; set directories on search
319 MOV BYTE PTR [FAILERR],BH ; FAIL not in progress
320 MOV BL,AH
321 SHL BX,1 ; 2 bytes per call in table
322 CLD
323;
324; Since the DOS maintains mucho state information across system calls, we
325; must be very careful about which stack we use.
326;
327; First, all abort operations must be on the disk stack. THis is due to the
328; fact that we may be hitting the disk (close operations, flushing) and may
329; need to report an INT 24.
330;
331 OR AH,AH
332 JZ DSKROUT ; ABORT
333;
334; Second, PRINT and PSPRINT and the server issue GetExtendedError calls at
335; INT 28 and INT 24 time. This call MUST, therefore, use the AUXSTACK.
336;
337 CMP AH,GetExtendedError
338 JZ DISPCALL
339;
340; Old 1-12 system calls may be either on the IOSTACK (normal operation) or
341; on the AUXSTACK (at INT 24 time).
342;
343 CMP AH,12
344 JA DSKROUT
345 CMP [ERRORMODE],0 ; Are we in an INT 24?
346 JNZ DISPCALL ; Stay on AUXSTACK if INT 24.
347 MOV SP,OFFSET DOSGROUP:IOSTACK
348 JMP SHORT DISPCALL
349;
350; We are on a system call that is classified as "the rest". We place
351; ourselves onto the DSKSTACK and away we go. We know at this point:
352;
353; o An INT 24 cannot be in progress. Therefore we reset errormode and
354; wperr
355; o That there can be no critical sections in effect. We signal the
356; server to remove all the resources.
357;
358DSKROUT:
359 MOV [USER_IN_AX],AX ; Remember what user is doing
360 MOV [EXTERR_LOCUS],errLOC_Unk ; Default
361 MOV [ERRORMODE],0 ; Cannot make non 1-12 calls in
362 MOV [WPERR],-1 ; error mode, so good place to make
363;
364; Release all resource information
365;
366 PUSH AX
367 MOV AH,82h
368 INT int_IBM
369 POP AX
370
371;
372; Since we are going to be running on the DSKStack and since INT 28 people
373; will use the DSKStack, we must turn OFF the generation of INT 28's.
374;
375 MOV IdleInt,0
376 MOV SP,OFFSET DOSGROUP:DSKSTACK
377 TEST [CNTCFLAG],-1
378 JZ DISPCALL ; Extra ^C checking is disabled
379 PUSH AX
380 invoke DSKSTATCHK
381 POP AX
382DISPCALL:
383 MOV BX,CS:Dispatch[BX]
384 XCHG BX,SaveBX
385 MOV DS,SaveDS
386
387IF BUFFERFLAG
388 mov cs:[SETVECTFLAG], 0
389 cmp ah, 25h
390 jne saveuser
391 cmp ah, 35h
392 jne saveuser
393 mov cs:[SETVECTFLAG], 1
394saveuser:
395 invoke SAVE_USER_MAP ;AN000;LB. save EMS map
396ENDIF
397
398 ASSUME DS:NOTHING
399 CALL SaveBX
400
401IF BUFFERFLAG
402 invoke RESTORE_USER_MAP ;AN000;LB. retsore EMS map
403ENDIF
404
405 entry LEAVEDOS
406ASSUME SS:NOTHING ; User routines may misbehave
407 CLI
408 DEC [INDOS]
409 MOV SS,[user_SS]
410 MOV SP,[user_SP]
411 MOV BP,SP
412 MOV BYTE PTR [BP.user_AX],AL
413 MOV AX,[NSP]
414 MOV [user_SP],AX
415 MOV AX,[NSS]
416 MOV [user_SS],AX
417 CALL restore_world
418 IRET
419EndProc SYSTEM_CALL
420
421;
422; restore_world restores all registers ('cept SS:SP, CS:IP, flags) from
423; the stack prior to giving the user control
424;
425 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
426 procedure restore_world,NEAR
427 POP restore_tmp ; POP restore_tmp
428 POP AX ; PUSH ES
429 POP BX ; PUSH DS
430 POP CX ; PUSH BP
431 POP DX ; PUSH DI
432 POP SI ; PUSH SI
433 POP DI ; PUSH DX
434 POP BP ; PUSH CX
435 POP DS ; PUSH BX
436 POP ES ; PUSH AX
437 JMP restore_tmp ; PUSH restore_tmp
438EndProc restore_world
439
440;
441; save_world saves complete registers on the stack
442;
443 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
444 procedure save_world,NEAR
445 POP restore_tmp
446 PUSH ES
447 PUSH DS
448 PUSH BP
449 PUSH DI
450 PUSH SI
451 PUSH DX
452 PUSH CX
453 PUSH BX
454 PUSH AX
455 JMP restore_tmp ; PUSH restore_tmp
456EndProc save_world
457
458IF BUFFERFLAG
459
460Break <SAVE_USER_MAP - save map > ;AN000;
461; Inputs: ;AN000;
462; none ;AN000;
463; Function: ;AN000;
464; save map ;AN000;
465; Outputs: ;AN000;
466; none ;AN000;
467; No other registers altered ;AN000;
468 ;AN000;
469Procedure SAVE_USER_MAP,NEAR ;AN000;
470 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
471 ;AN000;
472 CMP cs:[BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
473 JZ No_user_save ;LB. no ;AN000;
474 CMP cs:[SETVECTFLAG], 1
475 jz No_user_save
476; MOV [ACT_PAGE],-1 ;LB. invalidate active page ;AN000;
477; MOV WORD PTR [LASTBUFFER],-1 ;LB. and last buffer pointer ;AN000;
478 PUSH AX ;LB. save regs ;AN000;
479 PUSH DS ;LB. save regs ;AN000;
480 PUSH ES ;LB. ;AN000;
481 PUSH SI ;LB. ;AN000;
482 PUSH DI ;LB. ;AN000;
483 MOV SI,OFFSET DOSGROUP:BUF_EMS_SEG_CNT ;LB. ;AN000;
484 MOV DI,OFFSET DOSGROUP:BUF_EMS_MAP_USER ;LB. ;AN000;
485
486 PUSH CS
487 POP ES
488 PUSH CS ;LB. ds:si -> ems seg cnt ;AN000;
489 POP DS ;LB. ;AN000;
490
491 MOV AX,4F00H ;LB. save map ;AN000;
492 EnterCrit critDisk ;LB. enter critical section ;AN000;
493 INT 67H ;LB. ;AN000;
494 LeaveCrit critDisk ;LB. leave critical section ;AN000;
495 POP DI ;LB. ;AN000;
496 POP SI ;LB. restore regs ;AN000;
497 POP ES ;LB. ;AN000;
498 POP DS ;LB. ;AN000;
499 POP AX ;LB. restore ;AN000;
500No_user_save: ;AN000;
501 return ;AN000;
502EndProc SAVE_USER_MAP ;AN000;
503 ;AN000;
504
505Break <RESTORE_USER_MAP- retore map > ;AN000;
506; Inputs: ;AN000;
507; none ;AN000;
508; Function: ;AN000;
509; restore_map ;AN000;
510; Outputs: ;AN000;
511; none ;AN000;
512; No other registers altered ;AN000;
513 ;AN000;
514Procedure RESTORE_USER_MAP,NEAR ;AN000;
515 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
516
517 CMP cs:[BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
518 JZ No_user_restore ;LB. no ;AN000;
519 CMP cs:[SETVECTFLAG], 1
520 jz No_user_restore
521 PUSH AX ;LB. save regs ;AN000;
522 PUSH DS ;LB. save regs ;AN000;
523 PUSH SI ;LB. ;AN000;
524 MOV SI,OFFSET DOSGROUP:BUF_EMS_MAP_USER ;LB. ;AN000;
525
526 PUSH CS
527 POP DS
528
529 MOV AX,4F01H ;LB. restore map ;AN000;
530 EnterCrit critDisk ;LB. enter critical section ;AN000;
531 INT 67H ;LB. ;AN000;
532 LeaveCrit critDisk ;LB. leave critical section ;AN000;
533 POP SI ;LB. restore regs ;AN000;
534 POP DS ;LB. ;AN000;
535 POP AX ;LB. ;AN000;
536No_user_restore: ;AN000;
537 return ;AN000;
538EndProc RESTORE_USER_MAP
539
540ENDIF
541
542;
543; get_user_stack returns the user's stack (and hence registers) in DS:SI
544;
545 procedure get_user_stack,NEAR
546 LDS SI,DWORD PTR [user_SP]
547 return
548EndProc get_user_stack
549
550 IF NOT IBM
551BREAK <Set_OEM_Handler -- Set OEM sys call address and handle OEM Calls
552
553$SET_OEM_HANDLER:
554ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
555
556; Inputs:
557; User registers, User Stack, INTS disabled
558; If CALL F8, DS:DX is new handler address
559; Function:
560; Process OEM INT 21 extensions
561; Outputs:
562; Jumps to OEM_HANDLER if appropriate
563
564 JNE DO_OEM_FUNC ; If above F8 try to jump to handler
565 MOV WORD PTR [OEM_HANDLER],DX ; Set Handler
566 MOV WORD PTR [OEM_HANDLER+2],DS
567 IRET ; Quick return, Have altered no registers
568
569DO_OEM_FUNC:
570 CMP WORD PTR [OEM_HANDLER],-1
571 JNZ OEM_JMP
572 JMP BADCALL ; Handler not initialized
573
574OEM_JMP:
575 JMP [OEM_HANDLER]
576 ENDIF
577
578
579CODE ENDS
diff --git a/v4.0/src/DOS/DISPATCH.ASM b/v4.0/src/DOS/DISPATCH.ASM
new file mode 100644
index 0000000..0f50ef0
--- /dev/null
+++ b/v4.0/src/DOS/DISPATCH.ASM
@@ -0,0 +1,214 @@
1; SCCSID = @(#)dispatch.asm 1.1 85/04/10
2; SCCSID = @(#)dispatch.asm 1.1 85/04/10
3;
4; Major dispatch code and table for MSDOS 2.X and above.
5;
6; Modification history:
7;
8; Created: MZ 30 March 1983
9;
10; The system calls are dispatched to in such a fashion as to have their entire
11; register set passed to them except for CS:IP and SS:SP. This reduces the
12; need for retreiving information from the user's stack.
13;
14; There are also critical sections that need to be observed when running in a
15; multitasking environment. These sections are:
16;
17; 1 critDisk any of the disk code that will twiddle the buffer cache
18; 2 critDevice all device drivers
19;
20; 4 critMem memory allocation stuff
21; 5 critNet network critical section
22;
23; The system calls below are noted as to which of these critical sections they
24; belong. The critical sections are noted in the source files by the macros
25; EnterCrit and LeaveCrit.
26;
27; The break-down of the individual system calls into source files is as
28; follows (* means done):
29;
30; * handle.asm: Close, Read, Write, LSeek, XDup, XDup2, FileTimes
31; IOCTL.INC: IOCTL
32; * file.asm: Open, Creat, ChMod, Unlink, Rename, CreateTemp,
33; CreateNew
34; * srvcall.asm: $ServerCall
35; * path.asm: MkDir, RmDir, ChDir, CurrentDir
36; * alloc.asm: $Alloc, $Dealloc, $SetBlock, $AllocOper
37; arena_free_process, arena_next -> LOW LEVEL <-
38; check_signature, Coalesce
39; * search.asm: DirSearchFirst, DirSearchNext, FindFirst, FindNext,
40; PackName -> LOW LEVEL <-
41; * proc.asm: Exec, Exit, Abort, Wait, KeepProcess
42; * cpmio.asm: StdConInput, StdConOutput, StdAuxInput, StdAuxOutput,
43; StdPrinterOutput, RawConIO, RawConInput,
44; StdConInputNoEcho, StdConStringInput,
45; StdConStringOutput, StdConInputStatus,
46; StdConInputFlush
47; OUT, BUFOUT, RAWOUT, RAWOUT2 -> LOW LEVEL <-
48; * fcbio.asm: FCBOpen, FCBClose, FCBDelete, FCBSeqRead, FCBSeqWrite,
49; FCBCreate, FCBRename, FCBRandomRead, FCBRandomWrite,
50; GetFCBFileLength, GetFCBPosition, FCBRandomReadBlock,
51; FCBRandomWriteBlock
52; * Time.asm: GetDate, SetDate, GetTime, SetTime
53; * Parse.asm: Parse_file_descriptor, PathParse
54; * GetSet.asm: GetInterruptVector, SetInterruptVector,
55; GetVerifyOnWrite, SetVerifyOnWrite, GetDMA, SetDMA,
56; GetVersion, SetCTRLCTrapping, GetDriveFreespace,
57; CharOper, International, SetDefaultDrive,
58; GetDefaultDrive
59; * Misc.asm: Sleazefunc, SleazefuncDL, GetDefaultDPB, GetDPB,
60; CreateProcessDataBlock, GetINDOSFlag, GetInVars,
61; SetDPB, DupPDB, DiskReset
62; StrCmp, StrCpy, Ucase -> LOW LEVEL <-
63;
64; STUB MODULES
65; Net.asm **** This will get broken down more???
66; * Share.asm Share_Check, Share_Violation
67; * Lock.asm $LockOper
68; DOS_LOCK,DOS_UNLOCK,Lock_Check, Lock_Violation
69
70; INTERNAL INTERFACE MODULES
71; * Lock.asm DOS_LOCK, DOS_UNLOCK -->> STUBS <<--
72; * Dinfo.asm DISK_INFO
73; * Finfo.asm GET_FILE_INFO, SET_FILE_ATTRIBUTE
74; * Create.asm DOS_CREATE, DOS_CREATE_NEW,
75; Set_Mknd_Err --> Low level routine <--
76; * Dup.asm DOS_DUP
77; * Open.asm DOS_OPEN,
78; SetBadPathError, --> Low level routines <--
79; Check_Access_AX, Share_Error, Set_SFT_Mode
80; * Close.asm DOS_CLOSE, DOS_COMMIT, DOS_CLOSE_GOT_SFT,
81; Free_SFT --> Low level routine <--
82; * Abort.asm DOS_ABORT
83; * ISearch.asm DOS_SEARCH_FIRST, DOS_SEARCH_NEXT,
84; RENAME_NEXT --> Low level routine <--
85; * Dircall.asm DOS_MKDIR, DOS_CHDIR, DOS_RMDIR
86; * Rename.asm DOS_RENAME
87; * Delete.asm DOS_DELETE,
88; REN_DEL_Check --> Low level routine <--
89; * Disk.asm DOS_READ, DOS_WRITE
90
91; LOW LEVEL MODULES
92; * Fat.asm UNPACK, PACK, MAPCLUSTER, FATREAD_SFT,
93; FATREAD_CDS, FAT_operation
94; * Ctrlc.asm --> STD/IBM versions <--
95; FATAL, FATAL1, reset_environment, DSKSTATCHK,
96; SPOOLINT, STATCHK, CNTCHAND, DIVOV, RealDivOv,
97; CHARHARD, HardErr
98; * Buf.asm SETVISIT, ScanPlace, PLACEBUF, PLACEHEAD, PointComp,
99; GETBUFFR, GETBUFFRB, FlushBuf, BufWrite,
100; SKIPVISIT
101; * Disk.asm SWAPBACK, SWAPCON, get_io_sft, DirRead, FATSecRd,
102; DskRead, SETUP, BREAKDOWN, DISKREAD, DISKWRITE,
103; FIRSTCLUSTER, DREAD, DWRITE, DSKWRITE,
104; READ_LOCK_VIOLATION, WRITE_LOCK_VIOLATION,
105; SETSFT, SETCLUS, AddRec
106; * Mknode.asm BUILDDIR, SETDOTENT, MakeNode, NEWENTRY, FREEENT,
107; NEWDIR, DOOPEN,RENAME_MAKE
108; * FCB.asm MakeFcb, NameTrans, PATHCHRCMP, GetLet, TESTKANJ,
109; NORMSCAN, CHK, DELIM
110; * Rom.asm GET_random_record, GETRRPOS1, GetRRPos, SKPCLP,
111; FNDCLUS, BUFSEC, BUFRD, BUFWRT, NEXTSEC,
112; OPTIMIZE, FIGREC, GETREC, ALLOCATE, RESTFATBYT,
113; RELEASE, RELBLKS, GETEOF
114; * Dev.asm IOFUNC, DEVIOCALL, SETREAD, SETWRITE, GOTDPB,
115; DEVIOCALL2, DEV_CLOSE_SFT, DEV_OPEN_SFT
116; * Dir.asm SEARCH, SETDIRSRCH, GETPATH, ROOTPATH, StartSrch,
117; MatchAttributes, DEVNAME, Build_device_ent,
118; FindEntry, Srch, NEXTENT, GETENTRY, GETENT,
119; NEXTENTRY, GetPathNoSet, FINDPATH
120;
121
122; critical section information for the system calls
123
124; System Call Who takes care of the reentrancy
125; Abort 0 (flushbuf) DOS_Close
126; Std_Con_Input 1 DOS_Read
127; Std_Con_Output 2 DOS_Write
128; Std_Aux_Input 3 DOS_Read
129; Std_Aux_Output 4 DOS_Write
130; Std_Printer_Output 5 DOS_Write
131; Raw_Con_IO 6 DOS_Read/DOS_Write
132; Raw_Con_Input 7 DOS_Read
133; Std_Con_Input_No_Echo 8 DOS_Read
134; Std_Con_String_Output 9 DOS_Write
135; Std_Con_String_Input A DOS_Read
136; Std_Con_Input_Status B DOS_Read
137; Std_Con_Input_Flush C DOS_Read
138; Disk_Reset D (FlushBuf, ScanPlace, SkipVisit)
139; Set_Default_Drive E *none*
140; FCB_Open F DOS_Open
141; FCB_Close 10 DOS_Close
142; Dir_Search_First 11 DOS_Search_First
143; Dir_Search_Next 12 DOS_Search_Next
144; FCB_Delete 13 DOS_Delete
145; FCB_Seq_Read 14 DOS_Read/DOS_Write
146; FCB_Seq_Write 15 DOS_Read/DOS_Write
147; FCB_Create 16 DOS_Create
148; FCB_Rename 17 DOS_rename
149; Get_Default_Drive 19 *none*
150; Set_DMA 1A *none*
151; Get_Default_DPB 1F *none*
152; FCB_Random_Read 21 DOS_Read/DOS_Write
153; FCB_Random_Write 22 DOS_Read/DOS_Write
154; Get_FCB_File_Length 23 Get_file_info
155; Get_FCB_Position 24 *none*
156; Set_Interrupt_Vector 25 *none*
157; Create_Process_Data_Block 26 *none*
158; FCB_Random_Read_Block 27 DOS_Read/DOS_Write
159; FCB_Random_Write_Block 28 DOS_Read/DOS_Write
160; Parse_File_Descriptor 29 *none*
161; Get_Date 2A DEVIOCALL
162; Set_Date 2B DEVIOCALL
163; Get_Time 2C DEVIOCALL
164; Set_Time 2D DEVIOCALL
165; Set_Verify_On_Write 2E *none*
166; Get_DMA 2F *none*
167; Get_Version 30 *none*
168; Keep_Process 31 $abort...
169; Get_DPB 32 *none*
170; Set_CTRL_C_Trapping 33 *none*
171; Get_InDOS_Flag 34 *none*
172; Get_Interrupt_Vector 35 *none*
173; Get_Drive_Freespace 36 Disk_Info
174; Char_Oper 37 *none*
175; International 38 *none*
176; MKDir 39 DOS_MkDir
177; RMDir 3A DOS_RmDir
178; CHDir 3B DOS_ChDir
179; Creat 3C DOS_Create
180; Open 3D DOS_Open
181; Close 3E DOS_Close
182; Read 3F DOS_Read
183; Write 40 DOS_Write
184; Unlink 41 DOS_Delete
185; LSeek 42 *none*
186; CHMod 43 Get_file_info, Set_File_Attribute
187; IOCtl 44 DEVIOCALL
188; XDup 45 *none*
189; XDup2 46 *none*
190; Current_Dir 47 $Current_Dir
191; Alloc 48 $Alloc
192; Dealloc 49 $Dealloc
193; Setblock 4A $SetBlock
194; Exec 4B
195; Exit 4C $abort...
196; Wait 4D *none*
197; Find_First 4E DOS_Search_First
198; Find_Next 4F DOS_Search_Next
199; Set_Current_PDB 50 *none*
200; Get_Current_PDB 51 *none*
201; Get_In_Vars 52 *none*
202; SetDPB 53 *none*
203; Get_Verify_On_Write 54 *none*
204; Dup_PDB 55
205; Rename 56 DOS_Rename
206; File_Times 57 *none*
207; AllocOper 58 *none*
208; GetExtendedError 59 *none*
209; CreateTempFile 5A DOS_Create_New
210; CreateNewFile 5B DOS_Create_New
211; LockOper 5C
212; ServerCall 5D
213; UserOper 5E
214; AssignOper 5F
diff --git a/v4.0/src/DOS/DOSMES.ASM b/v4.0/src/DOS/DOSMES.ASM
new file mode 100644
index 0000000..3770c5d
--- /dev/null
+++ b/v4.0/src/DOS/DOSMES.ASM
@@ -0,0 +1,442 @@
1; SCCSID = @(#)dosmes.asm 1.7 85/10/23
2; SCCSID = @(#)dosmes.asm 1.7 85/10/23
3;
4; Message file for Internationalized messages. There is
5; only one message here available for translation.
6;
7;
8; Revision history
9; A000 version 4.00 Jan. 1988
10;
11
12IFNDEF KANJI
13KANJI EQU FALSE
14ENDIF
15
16IFNDEF Rainbow
17Rainbow EQU FALSE
18ENDIF
19
20include dossym.inc
21include dosmac.inc
22include doscntry.inc
23
24CONSTANTS SEGMENT WORD PUBLIC 'CONST'
25
26 PUBLIC UserNum, OEMNum
27 Public DMES001S,DMES001E
28DMES001S Label byte
29USERNUM DW ? ; 24 bit user number
30 DB ?
31IF IBM
32 IF IBMCOPYRIGHT
33 OEMNUM DB 0 ; 8 bit OEM number
34 ELSE
35 OEMNUM DB 0FFH ; 8 bit OEM number
36 ENDIF
37ELSE
38OEMNUM DB 0FFH
39ENDIF
40
41
42DMES001E label byte
43CONSTANTS ENDS
44
45TABLE SEGMENT BYTE PUBLIC 'TABLE'
46Public DMES002S
47DMES002S label byte
48
49
50; The following table is used for DOS 3.3
51;DOS country and code page information is defined here for DOS 3.3.
52;The initial value for ccDosCountry is 1 (USA).
53;The initial value for ccDosCodepage is 850.
54;
55;
56 PUBLIC COUNTRY_CDPG,UCASE_TAB,FILE_UCASE_TAB
57 PUBLIC FILE_CHAR_TAB
58;
59; country and code page infomation
60;
61COUNTRY_CDPG label byte
62
63 db 0,0,0,0,0,0,0,0 ; reserved words
64 db '\COUNTRY.SYS',0 ; path name of country.sys
65 db 51 dup (?)
66 dw 437 ; system code page id
67 dw 6 ; number of entries
68 db SetUcase ; Ucase type
69 dw OFFSET DOSGROUP:UCASE_TAB ;pointer to upper case table
70 dw 0 ; segment of poiter
71 db SetUcaseFile ; Ucase file char type
72 dw OFFSET DOSGROUP:FILE_UCASE_TAB ;pointer to file upper case table
73 dw 0 ; segment of poiter
74 db SetFileList ; valid file chars type
75 dw OFFSET DOSGROUP:FILE_CHAR_TAB ;pointer to valid file char tab
76 dw 0 ; segment of poiter
77 db SetCollate ; collate type
78 dw OFFSET DOSGROUP:COLLATE_TAB ;pointer to collate table
79 dw 0 ; segment of poiter
80 db SetDBCS ;AN000; DBCS Ev 2/12/KK
81 dw OFFSET DOSGROUP:DBCS_TAB ;AN000;;pointer to DBCS Ev table 2/12/KK
82 dw 0 ;AN000; segment of poiter 2/12/KK
83 db SetCountryInfo ; country info type
84 dw NEW_COUNTRY_SIZE ; extended country info size
85 dw 1 ; USA country id
86 dw 437 ; USA system code page id
87 dw 0 ; date format
88 db '$',0,0,0,0 ; currency symbol
89 db ',',0 ; thousand separator
90 db '.',0 ; decimal separator
91 db '-',0 ; date separator
92 db ':',0 ; time separator
93 db 0 ; currency format flag
94 db 2 ; # of disgit in currency
95 db 0 ; time format
96 dw OFFSET DOSGROUP:MAP_CASE ;mono case routine entry point
97 dw 0 ; segment of entry point
98 db ',',0 ; data list separator
99 dw 0,0,0,0,0 ; reserved
100
101
102
103;
104;
105;
106;
107;
108; upper case table
109;
110UCASE_TAB label byte
111 dw 128
112 db 128,154,069,065,142,065,143,128
113 db 069,069,069,073,073,073,142,143
114 db 144,146,146,079,153,079,085,085
115 db 089,153,154,155,156,157,158,159
116 db 065,073,079,085,165,165,166,167
117 db 168,169,170,171,172,173,174,175
118 db 176,177,178,179,180,181,182,183
119 db 184,185,186,187,188,189,190,191
120 db 192,193,194,195,196,197,198,199
121 db 200,201,202,203,204,205,206,207
122 db 208,209,210,211,212,213,214,215
123 db 216,217,218,219,220,221,222,223
124 db 224,225,226,227,228,229,230,231
125 db 232,233,234,235,236,237,238,239
126 db 240,241,242,243,244,245,246,247
127 db 248,249,250,251,252,253,254,255
128
129;
130; file upper case table
131;
132FILE_UCASE_TAB label byte
133 dw 128
134 db 128,154,069,065,142,065,143,128
135 db 069,069,069,073,073,073,142,143
136 db 144,146,146,079,153,079,085,085
137 db 089,153,154,155,156,157,158,159
138 db 065,073,079,085,165,165,166,167
139 db 168,169,170,171,172,173,174,175
140 db 176,177,178,179,180,181,182,183
141 db 184,185,186,187,188,189,190,191
142 db 192,193,194,195,196,197,198,199
143 db 200,201,202,203,204,205,206,207
144 db 208,209,210,211,212,213,214,215
145 db 216,217,218,219,220,221,222,223
146 db 224,225,226,227,228,229,230,231
147 db 232,233,234,235,236,237,238,239
148 db 240,241,242,243,244,245,246,247
149 db 248,249,250,251,252,253,254,255
150
151;
152; file char list
153;
154FILE_CHAR_TAB label byte
155 dw 22 ; length
156 db 1,0,255 ; include all
157 db 0,0,20h ; exclude 0 - 20h
158 db 2,14,'."/\[]:|<>+=;,' ; exclude 14 special
159 db 24 dup (?) ; reserved
160;
161; collate table
162;
163COLLATE_TAB label byte
164 dw 256
165 db 0,1,2,3,4,5,6,7
166 db 8,9,10,11,12,13,14,15
167 db 16,17,18,19,20,21,22,23
168 db 24,25,26,27,28,29,30,31
169 db " ","!",'"',"#","$","%","&","'"
170 db "(",")","*","+",",","-",".","/"
171 db "0","1","2","3","4","5","6","7"
172 db "8","9",":",";","<","=",">","?"
173 db "@","A","B","C","D","E","F","G"
174 db "H","I","J","K","L","M","N","O"
175 db "P","Q","R","S","T","U","V","W"
176 db "X","Y","Z","[","\","]","^","_"
177 db "`","A","B","C","D","E","F","G"
178 db "H","I","J","K","L","M","N","O"
179 db "P","Q","R","S","T","U","V","W"
180 db "X","Y","Z","{","|","}","~",127
181 db "C","U","E","A","A","A","A","C"
182 db "E","E","E","I","I","I","A","A"
183 db "E","A","A","O","O","O","U","U"
184 db "Y","O","U","$","$","$","$","$"
185 db "A","I","O","U","N","N",166,167
186 db "?",169,170,171,172,"!",'"','"'
187 db 176,177,178,179,180,181,182,183
188 db 184,185,186,187,188,189,190,191
189 db 192,193,194,195,196,197,198,199
190 db 200,201,202,203,204,205,206,207
191 db 208,209,210,211,212,213,214,215
192 db 216,217,218,219,220,221,222,223
193 db 224,"S"
194 db 226,227,228,229,230,231
195 db 232,233,234,235,236,237,238,239
196 db 240,241,242,243,244,245,246,247
197 db 248,249,250,251,252,253,254,255
198;
199; dbcs is not supported in DOS 3.3
200; DBCS_TAB CC_DBCS <>
201;
202; DBCS for DOS 4.00 2/12/KK
203 PUBLIC DBCS_TAB
204DBCS_TAB label byte ;AN000; 2/12/KK
205 dw 0 ;AN000; 2/12/KK max number
206 db 16 dup(0) ;AN000; 2/12/KK
207
208; dw 6 ; 2/12/KK
209; db 081h,09fh ; 2/12/KK
210; db 0e0h,0fch ; 2/12/KK
211; db 0,0 ; 2/12/KK
212;
213;
214include divmes.asm
215include yesno.asm
216
217TABLE ENDS
218
219CODE SEGMENT BYTE PUBLIC 'CODE'
220ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
221
222;CASE MAPPER ROUTINE FOR 80H-FFH character range, DOS 3.3
223; ENTRY: AL = Character to map
224; EXIT: AL = The converted character
225; Alters no registers except AL and flags.
226; The routine should do nothing to chars below 80H.
227;
228; Example:
229
230Procedure MAP_CASE,FAR
231 CMP AL,80H
232 JAE Map1 ;Map no chars below 80H ever
233 RET
234Map1:
235 SUB AL,80H ;Turn into index value
236 PUSH DS
237 PUSH BX
238 MOV BX,OFFSET DOSGROUP:UCASE_TAB + 2
239FINISH:
240 PUSH CS ;Move to DS
241 POP DS
242 XLAT ds:[bx] ;Get upper case character
243 POP BX
244 POP DS
245L_RET: RET
246EndProc MAP_CASE
247
248SUBTTL EDIT FUNCTION ASSIGNMENTS AND HEADERS
249PAGE
250; The following two tables implement the current buffered input editing
251; routines. The tables are pairwise associated in reverse order for ease
252; in indexing. That is; The first entry in ESCTAB corresponds to the last
253; entry in ESCFUNC, and the last entry in ESCTAB to the first entry in ESCFUNC.
254
255
256TABLE SEGMENT
257 PUBLIC CANCHAR
258CANCHAR DB CANCEL ;Cancel line character
259 PUBLIC ESCCHAR
260ESCCHAR DB ESCCH ;Lead-in character for escape sequences
261 IF NOT Rainbow
262ESCTAB LABEL BYTE
263 IF NOT IBM
264 IF WANG
265 DB 0C0h ; ^Z inserter
266 DB 0C1H ; Copy one char
267 DB 0C1H ; Copy one char
268 DB 0C7H ; Skip one char
269 DB 08AH ; Copy to char
270 DB 088H ; Skip to char
271 DB 09AH ; Copy line
272 DB 0CBH ; Kill line (no change in template)
273 DB 08BH ; Reedit line (new template)
274 DB 0C3H ; Backspace
275 DB 0C6H ; Enter insert mode
276 DB 0D6H ; Exit insert mode
277 DB 0C6H ; Escape character
278 DB 0C6H ; End of table
279 ELSE
280 ; VT52 equivalences
281 DB "Z" ; ^Z inserter
282 DB "S" ; F1 Copy one char
283 DB "S" ; F1 Copy one char
284 DB "V" ; F4 Skip one char
285 DB "T" ; F2 Copy to char
286 DB "W" ; F5 Skip to char
287 DB "U" ; F3 Copy line
288 DB "E" ; SHIFT ERASE Kill line (no change in template)
289 DB "J" ; ERASE Reedit line (new template)
290 DB "D" ; LEFT Backspace
291 DB "P" ; BLUE Enter insert mode
292 DB "Q" ; RED Exit insert mode
293 DB "R" ; GRAY Escape character
294 DB "R" ; End of table
295 ENDIF
296 ENDIF
297 IF IBM
298 DB 64 ; Ctrl-Z - F6
299 DB 77 ; Copy one char - -->
300 DB 59 ; Copy one char - F1
301 DB 83 ; Skip one char - DEL
302 DB 60 ; Copy to char - F2
303 DB 62 ; Skip to char - F4
304 DB 61 ; Copy line - F3
305 DB 61 ; Kill line (no change to template ) - Not used
306 DB 63 ; Reedit line (new template) - F5
307 DB 75 ; Backspace - <--
308 DB 82 ; Enter insert mode - INS (toggle)
309 DB 82 ; Exit insert mode - INS (toggle)
310 DB 65 ; Escape character - F7
311 DB 65 ; End of table
312 ENDIF
313ESCEND LABEL BYTE
314ESCTABLEN EQU ESCEND-ESCTAB
315
316ESCFUNC LABEL WORD
317 short_addr GETCH ; Ignore the escape sequence
318 short_addr TWOESC
319 short_addr EXITINS
320 short_addr ENTERINS
321 short_addr BACKSP
322 short_addr REEDIT
323 short_addr KILNEW
324 short_addr COPYLIN
325 short_addr SKIPSTR
326 short_addr COPYSTR
327 short_addr SKIPONE
328 short_addr COPYONE
329 short_addr COPYONE
330 short_addr CTRLZ
331 ENDIF
332TABLE ENDS
333
334;
335; OEMFunction key is expected to process a single function
336; key input from a device and dispatch to the proper
337; routines leaving all registers UNTOUCHED.
338;
339; Inputs: CS, SS are DOSGROUP
340; Outputs: None. This function is expected to JMP to one of
341; the following labels:
342;
343; GetCh - ignore the sequence
344; TwoEsc - insert an ESCChar in the buffer
345; ExitIns - toggle insert mode
346; EnterIns - toggle insert mode
347; BackSp - move backwards one space
348; ReEdit - reedit the line with a new template
349; KilNew - discard the current line and start from scratch
350; CopyLin - copy the rest of the template into the line
351; SkipStr - read the next character and skip to it in the template
352; CopyStr - read next char and copy from template to line until char
353; SkipOne - advance position in template one character
354; CopyOne - copy next character in template into line
355; CtrlZ - place a ^Z into the template
356; Registers that are allowed to be modified by this function are:
357; AX, CX, BP
358
359Procedure OEMFunctionKey,NEAR
360 ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
361 IF DBCS ;AN000;
362extrn intCNE0:near ;AN000; 2/17/KK
363 CALL intCNE0 ;AN000; 2/17/KK
364 ELSE ;AN000;
365 invoke $std_con_input_no_echo ; Get the second byte of the sequence
366 ENDIF ;AN000;
367 IF NOT Rainbow
368 MOV CL,ESCTABLEN ; length of table for scan
369 PUSH DI ; save DI (cannot change it!)
370 MOV DI,OFFSET DOSGROUP:ESCTAB ; offset of second byte table
371 REPNE SCASB ; Look it up in the table
372 POP DI ; restore DI
373 SHL CX,1 ; convert byte offset to word
374 MOV BP,CX ; move to indexable register
375 JMP [BP+OFFSET DOSGROUP:ESCFUNC] ; Go to the right routine
376 ENDIF
377 IF Rainbow
378
379TransferIf MACRO value,address
380 local a
381 CMP AL,value
382 JNZ a
383 transfer address
384a:
385ENDM
386
387 CMP AL,'[' ; is it second lead char
388 JZ EatParm ; yes, go walk tree
389GoGetCh:
390 transfer GetCh ; no, ignore sequence
391EatParm:
392 invoke $std_con_input_no_echo ; get argument
393 CMP AL,'A' ; is it alphabetic arg?
394 JAE EatAlpha ; yes, go snarf one up
395 XOR BP,BP ; init digit counter
396 JMP InDigit ; jump into internal eat digit routine
397EatNum:
398 invoke $std_con_input_no_echo ; get next digit
399InDigit:
400 CMP AL,'9' ; still a digit?
401 JA CheckNumEnd ; no, go check for end char
402 SUB AL,'0' ; turn into potential digit
403 JL GoGetCh ; oops, not a digit, ignore
404 MOV CX,BP ; save BP for 10 multiply
405 CBW ; make AL into AX
406 SHL BP,1 ; 2*BP
407 SHL BP,1 ; 4*BP
408 ADD BP,CX ; 5*BP
409 SHL BP,1 ; 10*BP
410 ADD BP,AX ; 10*BP + digit
411 JMP EatNum ; continue with number
412CheckNumEnd:
413 CMP AL,7Eh ; is it end char ~
414 JNZ GoGetCh ; nope, ignore key sequence
415 MOV AX,BP
416 transferIf 1,SkipStr ; FIND key
417 transferIf 2,EnterIns ; INSERT HERE key
418 transferIf 3,SkipOne ; REMOVE
419 transferIf 4,CopyStr ; SELECT
420 transferIf 17,TwoEsc ; INTERRUPT
421 transferIf 18,ReEdit ; RESUME
422 transferIf 19,KilNew ; CANCEL
423 transferIf 21,CtrlZ ; EXIT
424 transferIf 29,CopyLin ; DO
425 JMP GoGetCh
426EatAlpha:
427 CMP AL,'O' ; is it O?
428 JA GoGetCh ; no, after assume bogus
429 JZ EatPQRS ; eat the rest of the bogus key
430 transferIf 'C',CopyOne ; RIGHT
431 transferIf 'D',BackSp ; LEFT
432 JMP GoGetCh
433EatPQRS:
434 invoke $std_con_input_no_echo ; eat char after O
435 JMP GoGetCh
436 ENDIF
437
438EndProc OEMFunctionKey
439
440CODE ENDS
441
442 END
diff --git a/v4.0/src/DOS/DOSPRINT.ASM b/v4.0/src/DOS/DOSPRINT.ASM
new file mode 100644
index 0000000..92789cf
--- /dev/null
+++ b/v4.0/src/DOS/DOSPRINT.ASM
@@ -0,0 +1,36 @@
1; SCCSID = @(#)dosprint.asm 1.1 85/04/10
2; SCCSID = @(#)dosprint.asm 1.1 85/04/10
3TITLE DOSPRINT - PRINTF at DOS level
4NAME DOSPRINT
5;
6;
7; Modification history:
8;
9; Created: MZ 16 June 1984
10;
11
12.xlist
13;
14; get the appropriate segment definitions
15;
16include dosseg.asm
17
18CODE SEGMENT BYTE PUBLIC 'CODE'
19 ASSUME SS:DOSGroup,CS:DOSGroup
20
21.xcref
22INCLUDE DOSSYM.INC
23INCLUDE DEVSYM.INC
24.cref
25.list
26.sall
27
28 I_Need Proc_ID,WORD
29 I_Need User_ID,WORD
30
31BREAK <debugging output>
32
33include print.asm
34
35CODE ENDS
36END
diff --git a/v4.0/src/DOS/DUP.ASM b/v4.0/src/DOS/DUP.ASM
new file mode 100644
index 0000000..0f8c768
--- /dev/null
+++ b/v4.0/src/DOS/DUP.ASM
@@ -0,0 +1,68 @@
1; SCCSID = @(#)dup.asm 1.1 85/04/10
2; SCCSID = @(#)dup.asm 1.1 85/04/10
3TITLE DOS_DUP - Internal SFT DUP (for network SFTs)
4NAME DOS_DUP
5; Low level DUP routine for use by EXEC when creating a new process. Exports
6; the DUP to the server machine and increments the SFT ref count
7;
8; DOS_DUP
9;
10; Modification history:
11;
12; Created: ARR 30 March 1983
13;
14
15;
16; get the appropriate segment definitions
17;
18.xlist
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xcref
25INCLUDE DOSSYM.INC
26INCLUDE DEVSYM.INC
27.cref
28.list
29
30 i_need THISSFT,DWORD
31
32BREAK <DOS_DUP -- DUP SFT across network>
33
34; Inputs:
35; [THISSFT] set to the SFT for the file being DUPed
36; (a non net SFT is OK, in this case the ref
37; count is simply incremented)
38; Function:
39; Signal to the devices that alogical open is occurring
40; Returns:
41; ES:DI point to SFT
42; Carry clear
43; SFT ref_count is incremented
44; Registers modified: None.
45; NOTE:
46; This routine is called from $CREATE_PROCESS_DATA_BLOCK at DOSINIT
47; time with SS NOT DOSGROUP. There will be no Network handles at
48; that time.
49
50 procedure DOS_DUP,NEAR
51 ASSUME ES:NOTHING,SS:NOTHING
52
53 LES DI,ThisSFT
54 Entry Dos_Dup_Direct
55 Assert ISSFT,<ES,DI>,"DOSDup"
56 invoke IsSFTNet
57 JNZ DO_INC
58 invoke DEV_OPEN_SFT
59DO_INC:
60 Assert ISSFT,<ES,DI>,"DOSDup/DoInc"
61 INC ES:[DI.sf_ref_count] ; Clears carry (if this ever wraps
62 ; we're in big trouble anyway)
63 return
64
65EndProc DOS_DUP
66
67CODE ENDS
68 END
diff --git a/v4.0/src/DOS/EXEC.ASM b/v4.0/src/DOS/EXEC.ASM
new file mode 100644
index 0000000..aa120c2
--- /dev/null
+++ b/v4.0/src/DOS/EXEC.ASM
@@ -0,0 +1,931 @@
1; SCCSID = @(#)exec.asm 1.3 85/08/13
2; SCCSID = @(#)exec.asm 1.3 85/08/13
3; AN000 version 4.0 jan. 1988
4; A007 PTM 3957 - fake vesrion for IBMCACHE.COM
5; A008 PTM 4070 - fake version for MS WINDOWS
6
7SUBTTL $exec - load/go a program
8PAGE
9;
10; Assembler usage:
11; LDS DX, name
12; LES BX, blk
13; MOV AH, Exec
14; MOV AL, func
15; INT int_command
16;
17; AL Function
18; -- --------
19; 0 Load and execute the program.
20; 1 Load, create the program header but do not
21; begin execution.
22; 3 Load overlay. No header created.
23;
24; AL = 0 -> load/execute program
25;
26; +---------------------------+
27; | WORD segment address of |
28; | environment. |
29; +---------------------------+
30; | DWORD pointer to ASCIZ |
31; | command line at 80h |
32; +---------------------------+
33; | DWORD pointer to default |
34; | FCB to be passed at 5Ch |
35; +---------------------------+
36; | DWORD pointer to default |
37; | FCB to be passed at 6Ch |
38; +---------------------------+
39;
40; AL = 1 -> load program
41;
42; +---------------------------+
43; | WORD segment address of |
44; | environment. |
45; +---------------------------+
46; | DWORD pointer to ASCIZ |
47; | command line at 80h |
48; +---------------------------+
49; | DWORD pointer to default |
50; | FCB to be passed at 5Ch |
51; +---------------------------+
52; | DWORD pointer to default |
53; | FCB to be passed at 6Ch |
54; +---------------------------+
55; | DWORD returned value of |
56; | CS:IP |
57; +---------------------------+
58; | DWORD returned value of |
59; | SS:IP |
60; +---------------------------+
61;
62; AL = 3 -> load overlay
63;
64; +---------------------------+
65; | WORD segment address where|
66; | file will be loaded. |
67; +---------------------------+
68; | WORD relocation factor to |
69; | be applied to the image. |
70; +---------------------------+
71;
72; Returns:
73; AX = error_invalid_function
74; = error_bad_format
75; = error_bad_environment
76; = error_not_enough_memory
77; = error_file_not_found
78;
79; Revision history:
80;
81; A000 version 4.00 Jan. 1988
82;
83include EA.INC
84include version.inc
85
86 I_Need Temp_Var2,WORD ;AN000;file type from $open
87 I_Need Special_Entries,WORD ;AN007;address of special entries
88 I_Need Special_Version,WORD ;AN007;special version number
89 I_Need Fake_Count,BYTE ;AN008;fake version count
90
91IF BUFFERFLAG
92 extrn restore_user_map:near
93ENDIF
94
95TABLE SEGMENT
96
97exec_init_SP DW ?
98exec_init_SS DW ?
99exec_init_IP DW ?
100exec_init_CS DW ?
101
102exec_internal_buffer EQU OpenBuf
103
104exec_signature DW ? ; must contain 4D5A (yay zibo!)
105exec_len_mod_512 DW ? ; low 9 bits of length
106exec_pages DW ? ; number of 512b pages in file
107exec_rle_count DW ? ; count of reloc entries
108exec_par_dir DW ? ; number of paragraphs before image
109exec_min_BSS DW ? ; minimum number of para of BSS
110exec_max_BSS DW ? ; max number of para of BSS
111exec_SS DW ? ; stack of image
112exec_SP DW ? ; SP of image
113exec_chksum DW ? ; checksum of file (ignored)
114exec_IP DW ? ; IP of entry
115exec_CS DW ? ; CS of entry
116exec_rle_table DW ? ; byte offset of reloc table
117Exec_header_len EQU $-Exec_Signature
118
119exec_internal_buffer_size EQU (128+128+53+curdirLEN)
120%out Please make sure that the following are contiguous and of the
121%out following sizes:
122%out
123%out OpenBuf 128
124%out RenBuf 128
125%out SearchBuf 53
126%out DummyCDS CurDirLen
127
128TABLE ENDS
129
130.sall
131
132procedure $Exec,NEAR
133 ASSUME DS:NOTHING, ES:NOTHING
134PUBLIC EXEC001S,EXEC001E
135EXEC001S:
136 LocalVar exec_blk,DWORD
137 LocalVar exec_func,BYTE
138 LocalVar exec_load_high,BYTE
139 LocalVar exec_fh,WORD
140 LocalVar exec_rel_fac,WORD
141 LocalVar exec_res_len_para,WORD
142 LocalVar exec_environ,WORD
143 LocalVar exec_size,WORD
144 LocalVar exec_load_block,WORD
145 LocalVar exec_dma,WORD
146 LocalVar execNameLen,WORD
147 LocalVar execName,DWORD
148EXEC001E:
149 Enter
150;
151; validate function
152;
153
154 CMP AL,3 ; only 0, 1 or 3 are allowed
155 JNA exec_check_2
156
157exec_bad_fun:
158 MOV EXTERR_LOCUS,errLOC_Unk ; Extended Error Locus
159 mov al,error_invalid_function
160
161exec_ret_err:
162 Leave
163 transfer SYS_RET_ERR
164
165exec_check_2:
166 CMP AL,2
167 JZ exec_bad_fun
168
169 MOV exec_blkL,BX ; stash args
170 MOV exec_blkH,ES
171 MOV exec_func,AL
172 MOV exec_load_high,0
173;
174; set up length of exec name
175;
176 MOV execNameL,DX
177 MOV execNameH,DS
178 MOV SI,DX ; move pointer to convenient place
179 invoke DStrLen
180 MOV ExecNameLen,CX ; save length
181
182 XOR AL,AL ; open for reading
183 PUSH BP
184 invoke $OPEN ; is the file there?
185 POP BP
186 JC exec_ret_err
187;File Type Checking
188; CMP BYTE PTR [Temp_Var2],EAEXISTING ;AN000;;FT. old file ?
189; JZ oldexf ;AN000;;FT. yes
190; TEST BYTE PTR EXEC_FUNC,EXEC_FUNC_OVERLAY ;AN000;;FT. exec overlay?
191; JNZ exovrly ;AN000;;FT. yes
192; CMP BYTE PTR [Temp_Var2],EAEXECUTABLE ;AN000;;FT. only file type
193; JZ oldexf ;AN000;;FT. 3 & 4 will pass
194; CMP BYTE PTR [Temp_Var2],EAINSTALLABLE ;AN000;;FT.
195; JZ oldexf ;AN000;;FT.
196;exerr: ;AN000;;FT.
197; MOV AL,error_access_denied ;AN000;;FT. error
198; JMP exec_ret_err ;AN000;;FT.
199;exovrly: ;AN000;;FT.
200; CMP BYTE PTR [Temp_Var2],EAOVERLAY ;AN000;;FT. only 5,6,7 pass
201; JZ oldexf ;AN000;;FT.
202; CMP BYTE PTR [Temp_Var2],EADEV_DRIVER ;AN000;;FT.
203; JZ oldexf ;AN000;;FT.
204; CMP BYTE PTR [Temp_Var2],EAIFS_DRIVER ;AN000;;FT.
205; JNZ exerr ;AN000;;FT.
206;
207;oldexf: ;AN000;
208;File Type Checking
209
210 MOV exec_fh,AX
211 MOV BX,AX
212 XOR AL,AL
213 invoke $IOCTL
214 JC Exec_bombJ
215 TEST DL,devid_ISDEV
216 JZ exec_check_environ
217 MOV AL,error_file_not_found
218Exec_bombJ:
219 JMP Exec_Bomb
220
221BadEnv:
222 MOV AL,error_bad_environment
223 JMP exec_bomb
224
225exec_check_environ:
226 MOV exec_load_block,0
227 MOV exec_environ,0
228
229 TEST BYTE PTR exec_func,exec_func_overlay ; overlays... no environment
230 JNZ exec_read_header
231 LDS SI,exec_blk ; get block
232 MOV AX,[SI].Exec1_environ ; address of environ
233 OR AX,AX
234 JNZ exec_scan_env
235 MOV DS,CurrentPDB
236 MOV AX,DS:[PDB_environ]
237 MOV exec_environ,AX
238 OR AX,AX
239 JZ exec_read_header
240
241exec_scan_env:
242 MOV ES,AX
243 XOR DI,DI
244 MOV CX,07FFFh ; at most 32k of environment
245 XOR AL,AL
246
247exec_get_environ_len:
248 REPNZ SCASB ; find that nul byte
249 JNZ BadEnv
250 DEC CX ; Dec CX for the next nul byte test
251 JB BadEnv ; gone beyond the end of the environment
252 SCASB ; is there another nul byte?
253 JNZ exec_get_environ_len ; no, scan some more
254 PUSH DI
255 LEA BX,[DI+0Fh+2]
256 ADD BX,ExecNameLen ; BX <- length of environment
257 ; remember argv[0] length
258 ; round up and remember argc
259 MOV CL,4
260 SHR BX,CL ; number of paragraphs needed
261 PUSH ES
262 invoke $ALLOC ; can we get the space?
263 POP DS
264 POP CX
265 JNC exec_save_environ
266 JMP exec_no_mem ; nope... cry and sob
267
268exec_save_environ:
269 MOV ES,AX
270 MOV exec_environ,AX ; save him for a rainy day
271 XOR SI,SI
272 MOV DI,SI
273 REP MOVSB ; copy the environment
274 MOV AX,1
275 STOSW
276 LDS SI,execName
277 MOV CX,execNameLen
278 REP MOVSB
279
280exec_read_header:
281;
282; We read in the program header into the above data area and determine
283; where in this memory the image will be located.
284;
285 Context DS
286 MOV CX,exec_header_len ; header size
287 MOV DX,OFFSET DOSGROUP:exec_signature
288 PUSH ES
289 PUSH DS
290 CALL ExecRead
291 POP DS
292 POP ES
293 JC exec_bad_file
294 OR AX,AX
295 JZ exec_bad_file
296 CMP AX,exec_header_len ; did we read the right number?
297 JNZ exec_com_filej ; yep... continue
298 TEST exec_max_BSS,-1 ; indicate load high?
299 JNZ exec_check_sig
300 MOV exec_load_high,-1
301exec_check_sig:
302 MOV AX,exec_signature
303 CMP AX,exe_valid_signature ; zibo arises!
304 JZ exec_save_start ; assume com file if no signature
305 CMP AX,exe_valid_old_signature ; zibo arises!
306 JZ exec_save_start ; assume com file if no signature
307
308exec_com_filej:
309 JMP exec_com_file
310
311;
312; We have the program header... determine memory requirements
313;
314exec_save_start:
315 MOV AX,exec_pages ; get 512-byte pages
316 MOV CL,5 ; convert to paragraphs
317 SHL AX,CL
318 SUB AX,exec_par_dir ; AX = size in paragraphs
319 MOV exec_res_len_para,AX
320
321;
322; Do we need to allocate memory? Yes if function is not load-overlay
323;
324 TEST BYTE PTR exec_func,exec_func_overlay
325 JZ exec_allocate ; allocation of space
326;
327; get load address from block
328;
329 LES DI,exec_blk
330 MOV AX,ES:[DI].exec3_load_addr
331 MOV exec_dma,AX
332 MOV AX,ES:[DI].exec3_reloc_fac
333 MOV exec_rel_fac,AX
334IF DEBUG
335 JMP exec_find_res
336ELSE
337 JMP SHORT exec_find_res
338ENDIF
339
340exec_no_mem:
341 MOV AL,error_not_enough_memory
342 JMP SHORT exec_bomb
343
344exec_bad_file:
345 MOV AL,error_bad_format
346
347exec_bomb:
348 ASSUME DS:NOTHING,ES:NOTHING
349 MOV BX,exec_fh
350 CALL exec_dealloc
351 LeaveCrit CritMem
352 SaveReg <AX,BP>
353 invoke $CLOSE
354 RestoreReg <BP,AX>
355 JMP Exec_Ret_Err
356
357exec_allocate:
358 DOSAssume CS,<DS>,"EXEC/exec_allocate"
359 PUSH AX
360 MOV BX,0FFFFh ; see how much room in arena
361 PUSH DS
362 invoke $ALLOC ; should have carry set and BX has max
363 POP DS
364 POP AX
365 ADD AX,10h ; room for header
366 CMP BX,11h ; enough room for a header
367 JB exec_no_mem
368 CMP AX,BX ; is there enough for bare image?
369 JA exec_no_mem
370 TEST exec_load_high,-1 ; if load high, use max
371 JNZ exec_BX_max ; use max
372 ADD AX,exec_min_BSS ; go for min allocation
373 JC exec_no_mem ; oops! carry
374 CMP AX,BX ; enough space?
375 JA exec_no_mem ; nope...
376 SUB AX,exec_min_BSS
377 ADD AX,exec_max_BSS ; go for the MAX
378 JC exec_BX_max
379 CMP AX,BX
380 JBE exec_got_block
381
382exec_BX_max:
383 MOV AX,BX
384
385exec_got_block:
386 PUSH DS
387 MOV BX,AX
388 MOV exec_size,BX
389 invoke $ALLOC ; get the space
390 POP DS
391 JC exec_no_mem
392 MOV exec_load_block,AX
393 ADD AX,10h
394 TEST exec_load_high,-1
395 JZ exec_use_ax ; use ax for load info
396 ADD AX,exec_size ; go to end
397 SUB AX,exec_res_len_para ; drop off header
398 SUB AX,10h ; drop off pdb
399exec_use_ax:
400 MOV exec_rel_fac,AX ; new segment
401 MOV exec_dma,AX ; beginning of dma
402
403;
404; Determine the location in the file of the beginning of the resident
405;
406exec_find_res:
407 MOV DX,exec_par_dir
408 PUSH DX
409 MOV CL,4
410 SHL DX,CL ; low word of location
411 POP AX
412 MOV CL,12
413 SHR AX,CL ; high word of location
414 MOV CX,AX ; CX <- high
415
416;
417; Read in the resident image (first, seek to it)
418;
419 MOV BX,exec_fh
420 PUSH DS
421 XOR AL,AL
422 invoke $LSEEK ; seek to resident
423 POP DS
424 jnc exec_big_read
425 jmp exec_bomb
426
427exec_big_read: ; Read resident into memory
428 MOV BX,exec_res_len_para
429 CMP BX,1000h ; too many bytes to read?
430 JB exec_read_ok
431 MOV BX,0FE0h ; max in one chunk FE00 bytes
432
433exec_read_ok:
434 SUB exec_res_len_para,BX ; we read (soon) this many
435 PUSH BX
436 MOV CL,4
437 SHL BX,CL ; get count in bytes from paras
438 MOV CX,BX ; count in correct register
439 PUSH DS
440 MOV DS,exec_dma ; Set up read buffer
441 ASSUME DS:NOTHING
442 XOR DX,DX
443 PUSH CX ; save our count
444 CALL ExecRead
445 POP CX ; get old count to verify
446 POP DS
447 JC exec_bad_fileJ
448 DOSAssume CS,<DS>,"EXEC/exec_read_ok"
449 CMP CX,AX ; did we read enough?
450 POP BX ; get paragraph count back
451 JZ execCheckEnd ; and do reloc if no more to read
452;
453; The read did not match the request. If we are off by 512 bytes or more
454; then the header lied and we have an error.
455;
456 SUB CX,AX
457 CMP CX,512
458 JAE Exec_Bad_fileJ
459;
460; We've read in CX bytes... bump DTA location
461;
462ExecCheckEnd:
463 ADD exec_dma,BX ; bump dma address
464 TEST exec_res_len_para,-1
465 JNZ exec_big_read
466;
467; The image has now been read in. We must perform relocation to
468; the current location.
469;
470exec_do_reloc:
471 MOV CX,exec_rel_fac
472 MOV AX,exec_SS ; get initial SS
473 ADD AX,CX ; and relocate him
474 MOV exec_init_SS,AX
475
476 MOV AX,exec_SP ; initial SP
477 MOV exec_init_SP,AX
478
479 LES AX,DWORD PTR exec_IP
480 MOV exec_init_IP,AX
481 MOV AX,ES
482 ADD AX,CX ; relocated...
483 MOV exec_init_CS,AX
484
485 XOR CX,CX
486 MOV DX,exec_rle_table
487 MOV BX,exec_fh
488 PUSH DS
489 XOR AX,AX
490 invoke $LSEEK
491 POP DS
492
493 JNC exec_get_entries
494exec_bad_filej:
495 JMP exec_bad_file
496
497exec_get_entries:
498 MOV DX,exec_rle_count ; Number of entries left
499
500exec_read_reloc:
501 ASSUME DS:NOTHING
502 PUSH DX
503 MOV DX,OFFSET DOSGROUP:exec_internal_buffer
504 MOV CX,((exec_internal_buffer_size)/4)*4
505 PUSH DS
506 CALL ExecRead
507 POP ES
508 POP DX
509 JC exec_bad_filej
510 MOV CX,(exec_internal_buffer_size)/4
511 MOV DI,OFFSET DOSGROUP:exec_internal_buffer ; Pointer to byte location in header
512;
513; Relocate a single address
514;
515 MOV SI,exec_rel_fac
516
517exec_reloc_one:
518 OR DX,DX ; Any more entries?
519 JE exec_set_PDBJ
520
521exec_get_addr:
522 LDS BX,DWORD PTR ES:[DI] ; Get ra/sa of entry
523 MOV AX,DS ; Relocate address of item
524 ADD AX,SI
525 MOV DS,AX
526 ADD [BX],SI
527 ADD DI,4
528 DEC DX
529 LOOP exec_reloc_one ; End of internal buffer?
530
531;
532; We've exhausted a single buffer's worth. Read in the next piece
533; of the relocation table.
534;
535
536 PUSH ES
537 POP DS
538 JMP exec_read_reloc
539
540exec_set_PDBJ:
541 JMP exec_set_PDB
542
543exec_no_memj:
544 JMP exec_no_mem
545
546;
547; we have a .COM file. First, determine if we are merely loading an overlay.
548;
549exec_com_file:
550 TEST BYTE PTR exec_func,exec_func_overlay
551 JZ exec_alloc_com_file
552 LDS SI,exec_blk ; get arg block
553 LODSW ; get load address
554 MOV exec_dma,AX
555 MOV AX,0FFFFh
556 JMP SHORT exec_read_block ; read it all!
557
558; We must allocate the max possible size block (ick!) and set up
559; CS=DS=ES=SS=PDB pointer, IP=100, SP=max size of block.
560;
561exec_alloc_com_file:
562 MOV BX,0FFFFh
563 invoke $ALLOC ; largest piece available as error
564 OR BX,BX
565 JZ exec_no_memj
566 MOV exec_size,BX ; save size of allocation block
567 PUSH BX
568 invoke $ALLOC ; largest piece available as error
569 POP BX ; get size of block...
570 MOV exec_load_block,AX
571 ADD AX,10h ; increment for header
572 MOV exec_dma,AX
573 XOR AX,AX ; presume 64K read...
574 CMP BX,1000h ; 64k or more in block?
575 JAE exec_read_com ; yes, read only 64k
576 MOV AX,BX ; convert size to bytes
577 MOV CL,4
578 SHL AX,CL
579exec_read_com:
580 SUB AX,100h ; remember size of psp
581exec_read_block:
582 PUSH AX ; save number to read
583 MOV BX,exec_fh ; of com file
584 XOR CX,CX ; but seek to 0:0
585 MOV DX,CX
586 XOR AX,AX ; seek relative to beginning
587 invoke $LSEEK ; back to beginning of file
588 POP CX ; number to read
589 MOV DS,exec_dma
590 XOR DX,DX
591 PUSH CX
592 CALL ExecRead
593 POP SI ; get number of bytes to read
594 jnc OkRead
595 jmp exec_bad_file
596OkRead:
597 CMP AX,SI ; did we read them all?
598 JZ exec_no_memj ; exactly the wrong number... no memory
599 TEST BYTE PTR exec_func,exec_func_overlay
600 JNZ exec_set_PDB ; no starto, chumo!
601 MOV AX,exec_DMA
602 SUB AX,10h
603 MOV exec_init_CS,AX
604 MOV exec_init_IP,100h ; initial IP is 100
605;
606; SI is at most FF00h. Add FE to account for PSP - word of 0 on stack.
607;
608 ADD SI,0FEh ; make room for stack
609 MOV exec_init_SP,SI ; max value for read is also SP!
610 MOV exec_init_SS,AX
611 MOV DS,AX
612 MOV WORD PTR [SI],0 ; 0 for return
613
614exec_set_PDB:
615 MOV BX,exec_fh ; we are finished with the file.
616 CALL exec_dealloc
617 PUSH BP
618 invoke $CLOSE ; release the jfn
619 POP BP
620 CALL exec_alloc
621 TEST BYTE PTR exec_func,exec_func_overlay
622 JZ exec_build_header
623 CALL Scan_Execname ;MS.;AN007;
624 CALL Scan_Special_Entries ;MS.;AN007;
625 Leave
626 transfer SYS_RET_OK ; overlay load -> done
627
628exec_build_header:
629 MOV DX,exec_load_block
630;
631; assign the space to the process
632;
633
634 MOV SI,arena_owner ; pointer to owner field
635
636 MOV AX,exec_environ ; get environ pointer
637 OR AX,AX
638 JZ NO_OWNER ; no environment
639 DEC AX ; point to header
640 MOV DS,AX
641 MOV [SI],DX ; assign ownership
642NO_OWNER:
643 MOV AX,exec_load_block ; get load block pointer
644 DEC AX
645 MOV DS,AX ; point to header
646 MOV [SI],DX ; assign ownership
647
648 PUSH DS ;AN000;MS. make ES=DS
649 POP ES ;AN000;MS.
650 MOV DI,ARENA_NAME ;AN000;MS. ES:DI points to destination
651 CALL Scan_Execname ;AN007;MS. parse execname
652 ; ds:si->name, cx=name length
653 PUSH CX ;AN007;;MS. save for fake version
654 PUSH SI ;AN007;;MS. save for fake version
655
656movename: ;AN000;
657 LODSB ;AN000;;MS. get char
658 CMP AL,'.' ;AN000;;MS. is '.' ,may be name.exe
659 JZ mem_done ;AN000;;MS. no, move to header
660 ;AN000;
661 STOSB ;AN000;;MS. move char
662 LOOP movename ;AN000;;MS. continue
663mem_done: ;AN000;
664 XOR AL,AL ;AN000;;MS. make ASCIIZ
665 CMP DI,SIZE ARENA ;AN000;MS. if not all filled
666 JAE fill8 ;AN000;MS.
667 STOSB ;AN000;MS.
668fill8: ;AN000;
669 POP SI ;AN007;MS. ds:si -> file name
670 POP CX ;AN007;MS.
671
672 CALL Scan_Special_Entries ;AN007;MS.
673
674 PUSH DX
675 MOV SI,exec_size
676 ADD SI,DX
677 invoke $Dup_PDB ; ES is now PDB
678 POP DX
679
680 PUSH exec_environ
681 POP ES:[PDB_environ]
682;
683; set up proper command line stuff
684;
685 LDS SI,exec_blk ; get the block
686 PUSH DS ; save its location
687 PUSH SI
688 LDS SI,[SI.exec0_5C_FCB] ; get the 5c fcb
689;
690; DS points to user space 5C FCB
691;
692 MOV CX,12 ; copy drive, name and ext
693 PUSH CX
694 MOV DI,5Ch
695 MOV BL,[SI]
696 REP MOVSB
697;
698; DI = 5Ch + 12 = 5Ch + 0Ch = 68h
699;
700 XOR AX,AX ; zero extent, etc for CPM
701 STOSW
702 STOSW
703;
704; DI = 5Ch + 12 + 4 = 5Ch + 10h = 6Ch
705;
706 POP CX
707 POP SI ; get block
708 POP DS
709 PUSH DS ; save (again)
710 PUSH SI
711 LDS SI,[SI.exec0_6C_FCB] ; get 6C FCB
712;
713; DS points to user space 6C FCB
714;
715 MOV BH,[SI] ; do same as above
716 REP MOVSB
717 STOSW
718 STOSW
719 POP SI ; get block (last time)
720 POP DS
721 LDS SI,[SI.exec0_com_line] ; command line
722;
723; DS points to user space 80 command line
724;
725 OR CL,80h
726 MOV DI,CX
727 REP MOVSB ; Wham!
728;
729; Process BX into default AX (validity of drive specs on args). We no longer
730; care about DS:SI.
731;
732 DEC CL ; get 0FFh in CL
733 MOV AL,BH
734 XOR BH,BH
735 invoke GetVisDrv
736 JNC exec_BL
737 MOV BH,CL
738exec_BL:
739 MOV AL,BL
740 XOR BL,BL
741 invoke GetVisDrv
742 JNC exec_Set_Return
743 MOV BL,CL
744exec_set_return:
745 invoke get_user_stack ; get his return address
746 PUSH [SI.user_CS] ; suck out the CS and IP
747 PUSH [SI.user_IP]
748 PUSH [SI.user_CS] ; suck out the CS and IP
749 PUSH [SI.user_IP]
750 POP WORD PTR ES:[PDB_Exit]
751 POP WORD PTR ES:[PDB_Exit+2]
752 XOR AX,AX
753 MOV DS,AX
754 POP DS:[addr_int_terminate] ; save them where we can get them later
755 POP DS:[addr_int_terminate+2] ; when the child exits.
756 MOV WORD PTR DMAADD,80h
757 MOV DS,CurrentPDB
758 MOV WORD PTR DMAADD+2,DS
759 TEST BYTE PTR exec_func,exec_func_no_execute
760 JZ exec_go
761
762 LDS SI,DWORD PTR exec_init_SP ; get stack
763 LES DI,exec_blk ; and block for return
764 MOV ES:[DI].exec1_SS,DS ; return SS
765
766 DEC SI ; 'push' default AX
767 DEC SI
768 MOV [SI],BX ; save default AX reg
769 MOV ES:[DI].exec1_SP,SI ; return 'SP'
770
771 LDS AX,DWORD PTR exec_init_IP
772 MOV ES:[DI].exec1_CS,DS ; initial entry stuff
773
774 MOV ES:[DI].exec1_IP,AX
775 Leave
776 transfer SYS_RET_OK
777
778exec_go:
779 LDS SI,DWORD PTR exec_init_IP ; get entry point
780 LES DI,DWORD PTR exec_init_SP ; new stack
781 MOV AX,ES
782;
783; DS:SI points to entry point
784; AX:DI points to initial stack
785; DX has PDB pointer
786; BX has initial AX value
787;
788 CLI
789 MOV BYTE PTR INDOS,0
790 ASSUME SS:NOTHING
791 MOV SS,AX ; set up user's stack
792 MOV SP,DI ; and SP
793 STI
794 PUSH DS ; fake long call to entry
795 PUSH SI
796 MOV ES,DX ; set up proper seg registers
797 MOV DS,DX
798 MOV AX,BX ; set up proper AX
799procedure exec_long_ret,FAR
800
801IF BUFFERFLAG
802 invoke restore_user_map
803ENDIF
804
805 RET
806EndProc exec_long_ret
807
808EndProc $Exec
809
810Procedure ExecRead,NEAR
811 CALL exec_dealloc
812 MOV bx,exec_fh
813 PUSH BP
814 invoke $READ
815 POP BP
816 CALL exec_alloc
817 return
818EndProc ExecRead
819
820procedure exec_dealloc,near
821 ASSUME DS:NOTHING,ES:NOTHING
822 PUSH BX
823 MOV BX,arena_owner_system
824 EnterCrit CritMEM
825 CALL ChangeOwners
826 POP BX
827 return
828EndProc exec_dealloc
829
830procedure exec_alloc,near
831 PUSH BX
832 MOV BX,CurrentPDB
833 CALL ChangeOwners
834 LeaveCrit CritMEM
835 POP BX
836 return
837EndProc exec_alloc
838
839procedure ChangeOwners,NEAR
840 pushf
841 PUSH AX
842 MOV AX,exec_environ
843 CALL ChangeOwner
844 MOV AX,exec_load_block
845 Call ChangeOwner
846 POP AX
847 popf
848 return
849EndProc ChangeOwners
850
851Procedure ChangeOwner,near
852 OR AX,AX ; is area allocated?
853 retz ; no, do nothing
854 DEC AX
855 PUSH DS
856 MOV DS,AX
857 MOV DS:[arena_owner],BX
858 POP DS
859 return
860EndProc ChangeOwner
861
862Procedure Scan_Execname,near ;AN000;MS.
863
864 LDS SI,execName ;AN000;MS. DS:SI points to name
865save_begin: ;AN000;
866 MOV CX,SI ;AN000;MS. CX= starting addr
867scan0: ;AN000;
868 LODSB ;AN000;MS. get char
869 CMP AL,':' ;AN000;;MS. is ':' , may be A:name
870 JZ save_begin ;AN000;;MS. yes, save si
871 CMP AL,'\' ;AN000;;MS. is '\', may be A:\name
872 JZ save_begin ;AN000;;MS. yes, save si
873 CMP AL,0 ;AN000;;MS. is end of name
874 JNZ scan0 ;AN000;;MS. no, continue scanning
875 SUB SI,CX ;AN000;;MS. get name's length
876 XCHG SI,CX ;AN000;;MS. cx= length, si= starting addr
877
878 return ;AN000;;MS.
879EndProc Scan_Execname ;AN000;;MS.
880
881
882Procedure Scan_Special_Entries,near ;AN000;MS.
883
884 DEC CX ;AN007;MS. cx= name length
885 MOV DI,CS:[Special_Entries] ;AN007;MS. es:di -> addr of special entries
886 CALL Reset_Version ;AN008;MS.
887 PUSH CS ;AN007;MS.
888 POP ES ;AN007;MS.
889Getentries: ;AN007;MS.
890 MOV AL,ES:[DI] ;AN007;MS. end of list
891 OR AL,AL ;AN007;MS.
892 JZ end_list ;AN007;MS. yes
893 MOV CS:[Temp_Var2],DI ;AN007;MS. save di
894 CMP AL,CL ;AN007;MS. same length ?
895 JNZ skipone ;AN007;MS. no
896 INC DI ;AN007;MS. es:di -> special name
897 PUSH CX ;AN007;MS. save length and name addr
898 PUSH SI ;AN007;MS.
899 REPZ CMPSB ;AN007;MS. same name ?
900 JNZ not_matched ;AN007;MS. no
901 MOV AX,ES:[DI] ;AN007;MS. get special version
902 MOV CS:[Special_Version],AX ;AN007;MS. save it
903 MOV AL,ES:[DI+2] ;AN008;MS. get fake count
904 MOV CS:[Fake_Count],AL ;AN007;MS. save it
905 POP SI ;AN007;MS.
906 POP CX ;AN007;MS.
907 JMP SHORT end_list ;AN007;MS.
908not_matched: ;AN007;MS.
909 POP SI ;AN007;MS. restore si,cx
910 POP CX ;AN007;MS.
911skipone: ;AN007;MS.
912 MOV DI,CS:[Temp_Var2] ;AN007;MS. restore old di
913 XOR AH,AH ;AN007;MS. position to next entry
914 ADD DI,AX ;AN007;MS.
915 ADD DI,4 ;AN007;MS.
916 JMP Getentries ;AN007;MS.
917
918
919end_list: ;AN007;MS.
920 return
921EndProc Scan_Special_Entries ;AN000;;MS.
922
923Procedure Reset_Version,near ;AN008;MS.
924
925 CMP CS:[Fake_Count],0FFH ;AN008;MS.
926 JNZ dont_reset ;AN008;MS.
927 MOV CS:[Special_Version],0 ;AN008;MS. reset to current version
928dont_reset:
929 return
930EndProc Reset_Version,near ;AN008;;MS.
931 \ No newline at end of file
diff --git a/v4.0/src/DOS/EXTATTR.ASM b/v4.0/src/DOS/EXTATTR.ASM
new file mode 100644
index 0000000..1cc1d32
--- /dev/null
+++ b/v4.0/src/DOS/EXTATTR.ASM
@@ -0,0 +1,679 @@
1TITLE EXTATTR- Extended Attributes
2NAME EXTATTR
3;
4; Get or Set Extended Attributes by handle
5;
6;
7; GetSetEA
8; Set_Output
9; Search_EA
10; Copy_QEA
11; Set_one_EA
12; Get_one_EA
13; Get_Value
14; GSetDevCdpg
15; Get_max_EA_size
16;
17; Revision history
18;
19; A000 version 4.00 Jan. 1988
20;
21;
22;
23;
24;
25;
26;
27
28.xlist
29;
30;
31; get the appropriate segment definitions
32;
33include dosseg.asm ;AN000;
34
35CODE SEGMENT BYTE PUBLIC 'CODE' ;AN000;
36 ASSUME SS:DOSGROUP,CS:DOSGROUP ;AN000;
37
38.xcref
39INCLUDE DOSSYM.INC ;AN000;
40INCLUDE DEVSYM.INC ;AN000;
41include EA.inc ;AN000;
42.cref
43.list
44.sall
45
46
47; I_need XA_from,BYTE ;AN000;
48
49; I_need XA_TABLE,BYTE ;AN000;
50; I_need XA_TEMP,WORD ;AN000;
51; I_need XA_COUNT,WORD ;AN000;
52; I_need XA_DEVICE,BYTE ;AN000;
53 I_need XA_TYPE,BYTE ;AN000;
54 I_need SAVE_ES,WORD ;AN000;
55 I_need SAVE_DI,WORD ;AN000;
56 I_need SAVE_DS,WORD ;AN000;
57 I_need SAVE_SI,WORD ;AN000;
58 I_need SAVE_CX,WORD ;AN000;
59 I_need SAVE_BX,WORD ;AN000;
60; I_need XA_handle,WORD ;AN000;
61; I_need CPSWFLAG,BYTE ;AN000;
62; I_need XA_PACKET,BYTE ;AN000;
63; I_need MAX_EA_SIZE,WORD ;AN000;
64; I_need MAX_EANAME_SIZE,WORD ;AN000;
65; I_need THISSFT,DWORD ;AN000;
66;IF DBCS ;AN000;
67; I_need DBCS_PACKET,BYTE ;AN000; ;AN000;
68;ENDIF ;AN000; ;AN000;
69 ;AN000;
70 ;AN000;
71 ;AN000;
72 ;AN000;
73 ;AN000;
74BREAK <GetSet_EA get or set extended attributes by handle> ;AN000;
75 ;AN000;
76; Input: [XA_type] = function code, (e.g., get,set) ;AN000;
77; [ThisSFT] points to SFT ;AN000;
78; ES:BP points to drive parameter block ;AN000;
79; [XA_from] = By_Create or By_EA ;AN000;
80; [SAVE_ES]:[SAVE_DI] points to get/set list ;AN000;
81; [SAVE_DS]:[SAVE_SI] points to get query list ;AN000;
82; [SAVE_CX] = size of buffer
83; [XA_device]= 1 device, 0 file ;AN000;
84; [XA_handle] for device ;AN000;
85; Function: Get or Set extended attributes by handle ;AN000;
86; Output: carry set: error ;AN000;
87; carry clear: extended attributes are successfully get/set ;AN000;
88; extended attribute cluster may be created ;AN000;
89; ;AN000;
90; ;AN000;
91; ;AN000;
92 ;AN000;
93 ;AN000;
94procedure GetSet_XA,near ;AN000;
95 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
96
97
98 LES DI,DWORD PTR [SAVE_DI] ;AN000;;FT. ES:DI -> query list
99;; MOV [SAVE_BX],2 ;AN000;;FT. size returned
100;; XOR DX,DX ;AN000;;FT. dx=0, codepage id
101
102 CMP [XA_type],2 ;AN000;;FT. get EA ?
103 JNZ eaname ;AN000;;FT. no
104getEAs: ;AN000;
105 CMP [SAVE_CX],0 ;AN000;;FT. get max data size
106 JNZ notmax ;AN000;;FT. no
107;; CALL Get_max_EA_size ;AN000;;FT.
108
109 MOV CX,2 ;AN000;;FT. FAKE FAKE..............
110 JNC set_user_cx ;AN000;;FT.
111 JMP OKexit ;AN000;;FT. error
112notmax:
113 CMP [SAVE_CX],1 ;AN000;;FT. buffer size =1 ?
114 JNZ goodsiz ;AN000;;FT. no
115errout: ;AN000;
116 JMP insuff_space ;AN000;;FT. no error
117goodsiz: ;AN000;
118 MOV WORD PTR ES:[DI],0 ;AN000;FT. FAKE FAKE ...............
119 MOV CX,2 ;AN000;FT. FAKE FAKE ...............
120 JMP set_user_cx ;AN000;FT. FAKE FAKE ...............
121
122; SUB [SAVE_CX],2 ;AN000;;FT. minus count size
123; CMP [SAVE_SI],-1 ;AN000;;FT. get all ?
124; JNZ getsome ;AN000;;FT. no
125; PUSH CS ;AN000;;FT. ds:si-> EA entry addr
126; POP DS ;AN000;;FT.
127; INC DI ;AN000;;FT.
128; INC DI ;AN000;;FT. es:di -> address after count
129; MOV SI,OFFSET DOSGROUP:XA_TABLE ;AN000;FT.
130; MOV CX,XA_COUNT ;AN000;;FT. cx= number of EA entries
131;;;;;;
132;getone:
133; CALL GET_ONE_EA ;AN000;;FT. get EA
134; JC setout ;AN000;;FT. insufficient memory
135; INC DX ;AN000;;FT. next EA ID
136; LOOP getone ;AN000;;FT. next one
137;setout: ;AN000;
138; CALL Set_Output ;AN000;;FT.
139; OR CX,CX ;AN000;;FT.
140; JNZ errout ;AN000;;FT.
141;
142; JMP OKexit ;AN000;;FT.
143eaname:
144 CMP [XA_type],3 ;AN000;;FT. get EA name?`
145 JZ geteaname ;AN000;;FT. yes
146 JMP setea ;AN000;;FT.
147geteaname:
148; MOV [SAVE_SI],-1 ;AN000;;FT. make get all
149 CMP [SAVE_CX],0 ;AN000;;FT. get max data size
150 JNZ notmax ;AN000;;FT. no
151 MOV CX,2 ;AN000;;FT. FAKE FAKE ......................
152;; MOV CX,[MAX_EANAME_SIZE] ;AN000;;FT. get name size
153set_user_cx: ;AN000;
154 invoke get_user_stack ;AN000;;FT. get user stack
155 MOV [SI.user_CX],CX ;AN000;;FT.
156 JMP OKexit ;AN000;;FT. exit
157
158getsome: ;AN000;
159; LDS SI,DWORD PTR [SAVE_SI] ;AN000;;FT.
160; LODSW ;AN000;;FT.
161; MOV CX,AX ;AN000;;FT. cx=number of query entries
162; JCXZ setout ;AN000;;FT. yes
163; STOSW ;AN000;;FT. es:di -> EA
164;get_next_EA: ;AN000;
165; PUSH DS ;AN000;;FT. save ds:si
166; PUSH SI ;AN000;;FT. es:di
167; PUSH ES ;AN000;;FT.
168; PUSH DI ;AN000;;FT.
169; CALL Search_EA ;AN000;;FT. search query EA from table
170; JC EAnotFound ;AN000;;FT. EA not found
171; PUSH ES ;AN000;;FT.
172; POP DS ;AN000;;FT.
173; MOV SI,DI ;AN000;;FT. ds:si -> found EA
174; POP DI ;AN000;;FT. es:di -> buffer
175; POP ES ;AN000;;FT.
176; CALL GET_ONE_EA ;AN000;;FT. copy to buffer
177; POP SI ;AN000;;FT.
178; POP DS ;AN000;;FT.
179; JC setfinal ;AN000;;FT. memory not enough
180; MOV AL,[SI.QEA_NAMELEN] ;AN000;;FT.
181; XOR AH,AH ;AN000;;FT.
182; ADD AX,QEA_NAME ;AN000;;FT.
183; ADD SI,AX ;AN000;;FT. ds:si -> next query entry
184;testend: ;AN000;
185; LOOP get_next_EA ;AN000;;FT. do next
186;setfinal: ;AN000;
187; LDS SI,DWORD PTR [SAVE_SI] ;AN000;;FT.
188; MOV DX,[SI] ;AN000;;FT.
189; SUB DX,CX ;AN000;;FT. dx= returned count
190; JMP setout ;AN000;;FT.
191;EAnotFound: ;AN000;
192; POP DI ;AN000;;FT. restore regs
193; POP ES ;AN000;;FT.
194; POP SI ;AN000;;FT.
195; POP DS ;AN000;;FT.
196;
197; CALL COPY_QEA ;AN000;;FT. copy query EA to buffer
198; JC setfinal ;AN000;;FT. not enough memory
199; JMP testend ;AN000;;FT.
200setea: ;AN000;
201 JMP OKexit ;AN000;;FT. FAKE FAKE ..........
202; LDS SI,DWORD PTR [SAVE_DI] ;AN000;;FT.
203; LODSW ;AN000;;FT.
204; MOV CX,AX ;AN000;;FT. cx=number of query entries
205; OR CX,CX ;AN000;;FT. cx=0 ?
206; JZ OKexit ;AN000;;FT. yes
207;set_next: ;AN000;
208; CALL Search_EA ;AN000;;FT.
209; JNC toset ;AN000;;FT.
210;set_reason: ;AN000;
211; CLC ;AN000;;FT. clear acrry
212; MOV [SI.EA_RC],AL ;AN000;;FT. set reason code
213; DEC CX ;AN000;;FT. end of set ?
214; JZ OKexit ;AN000;;FT. yes
215
216; MOV AL,[SI.EA_NAMELEN] ;AN000;;FT.
217; XOR AH,AH ;AN000;;FT.
218; ADD AX,[SI.EA_VALLEN] ;AN000;;FT.
219; ADD SI,EA_NAME ;AN000;;FT.
220; ADD SI,AX ;AN000;;FT. es:di -> next EA entry
221; JMP set_next ;AN000;;FT.
222;toset: ;AN000;
223; CALL SET_ONE_EA ;AN000;;FT. set it
224; JMP set_reason ;AN000;;FT.
225 insuff_space: ;AN000;;FT.
226; MOV AX,error_not_enough_memory ;AN000;FT. insufficient memory err
227; STC ;AN000;
228OKexit: ;AN000;
229 return ;AN000;
230
231EndProc GetSet_XA ;AN000;
232
233
234; Input: [SAVE_ES]:[SAVE_DI] points to buffer
235; [SAVE_BX]= returned size
236; DX= returned count
237; Function: set returned size and count ;AN000;
238; Output: none
239 ;AN000;
240;procedure Set_Output,NEAR ;AN000;
241; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
242; ;AN000;
243; LES DI,DWORD PTR [SAVE_DI] ;FT. es:di -> count ;AN000;
244; MOV ES:[DI],DX ;FT. ;AN000;
245; MOV BX,[SAVE_BX] ;FT. cx=size returned ;AN000;
246; invoke get_user_stack ;FT. get user stack ;AN000;
247; MOV [SI.user_CX],BX ;FT. ;AN000;
248; return ;FT. ;AN000;
249; ;AN000;
250;EndProc Set_Output ;AN000;
251
252
253; Input: DS:SI= query EA addr ;AN000;
254; Function: search the EA ;AN000;
255; Output: carry clear
256; DX= EA ID (0 codpage, 1 Filetype, etc.)
257; ES:DI points to found entry
258; carry set, not found, AL= reason code ;AN000;
259 ;AN000;
260;procedure Search_EA,NEAR ;AN000;
261; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
262; ;AN000;
263; PUSH CX ;FT. save entry count ;AN000;
264; MOV AL,EARCNOTFOUND ;FT. preset error code ;AN000;
265; MOV BL,[SI.QEA_NAMELEN] ;FT. ? ;AN000;
266; CMP [XA_TYPE],4 ;FT. set ? ;AN000;
267; JNZ gettyp ;FT. no ;AN000;
268; MOV BL,[SI.EA_NAMELEN] ;FT. ? ;AN000;
269;gettyp:
270; OR BL,BL ;FT. ;AN000;
271; JZ not_found ;FT. ;AN000;
272; PUSH CS ;FT. ds:si-> EA entry addr ;AN000;
273; POP ES ;FT. ;AN000;
274; MOV DI,OFFSET DOSGROUP:XA_TABLE ;FT. ;AN000;
275; MOV CX,XA_COUNT ;FT. cx= number of EA entries ;AN000;
276; XOR DX,DX ;FT. dx=0, codepage id ;AN000;
277;
278;start_find:
279; PUSH CX ;FT. save entry count ;AN000;
280; MOV CL,BL ;FT. ;AN000;
281; XOR CH,CH ;FT. get name len ;AN000;
282; PUSH SI ;FT. ;AN000;
283; PUSH DI ;FT. ;AN000;
284; CMP [XA_TYPE],4 ;FT. set ? ;AN000;
285; JNZ gettyp2 ;FT. no ;AN000;
286; ADD SI,EA_NAME ;FT. ;AN000;
287; JMP short updi ;FT. ;AN000;
288;gettyp2:
289; ADD SI,QEA_NAME ;FT. compare EA names ;AN000;
290;updi:
291; ADD DI,EA_NAME ;FT. ;AN000;
292; REP CMPSB ;FT. ;AN000;
293; POP DI ;FT. ;AN000;
294; POP SI ;FT. ;AN000;
295; POP CX ;FT. ;AN000;
296; JNZ not_matched ;FT. name not matched ;AN000;
297; MOV AL,EARCDEFBAD ;FT. preset error code ;AN000;
298; PUSH SI ;FT. ;AN000;
299; PUSH DI ;FT. ;AN000;
300; CMPSB ;FT. compare type ;AN000;
301; JNZ not_matched2 ;FT. type not matched ;AN000;
302; CMPSW ;FT. compare flags ;AN000;
303; JNZ not_matched2 ;FT. flag not matched ;AN000;
304; POP DI ;FT. ;AN000;
305; POP SI ;FT. found one ;AN000;
306; JMP SHORT found_one ;FT. ;AN000;
307;not_matched:
308; DEC CX ;FT. end of table ;AN000;
309; JZ not_found ;FT. yes ;AN000;
310; MOV AL,ES:[DI.EA_NAMELEN] ;FT. ;AN000;
311; XOR AH,AH ;FT. ;AN000;
312;
313; ADD DI,EA_NAME ;FT. ;AN000;
314; ADD DI,AX ;FT. es:di -> next EA entry ;AN000;
315; INC DX ;FT. increment EA ID ;AN000;
316; JMP start_find ;FT. ;AN000;
317;not_matched2:
318; POP DI ;FT. ;AN000;
319; POP SI ;FT. ;AN000;
320; JMP not_matched ;FT. ;AN000;
321;not_found:
322; STC ;FT. ;AN000;
323;found_one:
324; POP CX ;FT. ;AN000;
325; return ;FT. ;AN000;
326 ;AN000;
327;EndProc Search_EA ;AN000;
328 ;AN000;
329; Input: ES:DI= buffer address ;AN000;
330; DS:SI= EA entry address
331; [SAVE_CX]= buffer size
332; AL = reason code
333; Function: move one query entry to buffer ;AN000;
334; Output: carry clear
335; DS:SI points to next entry
336; ES:DI points to next entry
337; [SAVE_CX],[SAVE_BX], updated ;AN000;
338; carry set, insufficient memory error ;AN000;
339 ;AN000;
340;procedure COPY_QEA,NEAR ;AN000;
341; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
342; ;AN000;
343; PUSH CX ;FT. ;AN000;
344; MOV DL,AL ;FT. ;AN000;
345; MOV CX,EA_NAME -EA_TYPE ;FT. ;AN000;
346;
347; MOV BL,[SI.QEA_NAMELEN] ;FT. ;AN000;
348; XOR BH,BH ;FT. ;AN000;
349; ADD CX,BX ;FT. cx= query EA size ;AN000;
350; CMP CX,[SAVE_CX] ;FT. > buffer size ;AN000;
351; JA sizeshort2 ;FT. yes ;AN000;
352; PUSH CX ;FT. ;AN000;
353; LODSB ;FT. move type ;AN000;
354; STOSB ;FT. ;AN000;
355; LODSW ;FT. ;AN000;
356; STOSW ;FT. move flag ;AN000;
357; MOV AL,DL ;FT. move RC ;AN000;
358; STOSB ;FT. ;AN000;
359;
360; LODSB ;FT. move name len ;AN000;
361; MOV CL,AL ;FT. ;AN000;
362; STOSB ;FT. ;AN000;
363; XOR AX,AX ;FT. zero value length ;AN000;
364; STOSW ;FT. ;AN000;
365; OR CL,CL ;FT. ;AN000;
366; JZ zeroname ;FT. ;AN000;
367; XOR CH,CH ;FT. ;AN000;
368;
369; REP MOVSB ;FT. move EA to buffer ;AN000;
370;zeroname:
371; POP CX ;FT. ;AN000;
372; ADD [SAVE_BX],CX ;FT. bx=bx+entry size ;AN000;
373; SUB [SAVE_CX],CX ;FT. update buffer size ;AN000;
374; CLC ;FT. ;AN000;
375; JMP SHORT okget2 ;FT. ;AN000;
376;
377;sizeshort2:
378; MOV AX,error_not_enough_memory ;FT. error ;AN000;
379; STC ;FT. ;AN000;
380;okget2:
381; POP CX ;FT. ;AN000;
382; return ;FT. ;AN000;
383; ;AN000;
384;EndProc COPY_QEA ;AN000;
385 ;AN000;
386; Input: ES:DI= found EA entry addr ;AN000;
387; DS:SI= source EA entry address
388; DX= EA ID (0 codpage, 1 Filetype, etc.)
389; Function: set one EA ;AN000;
390; Output: carry clear
391; EA set
392; carry set, AL= reason code ;AN000;
393 ;AN000;
394;procedure SET_ONE_EA,NEAR ;AN000;
395; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
396; ;AN000;
397; PUSH CX ;FT. ;AN000;
398; MOV AL,EARCDEFBAD ;FT. prseet error code ;AN000;
399; MOV BX,[SI.EA_VALLEN] ;FT. ;AN000;
400; CMP BX,ES:[DI.EA_VALLEN] ;FT. length equal ? ;AN000;
401; JNZ notset ;FT. no ;AN000;
402; PUSH DS ;FT. ;AN000;
403; PUSH SI ;FT. ;AN000;
404; MOV AL,[SI.EA_NAMELEN] ;FT. ;AN000;
405; XOR AH,AH ;FT. ;AN000;
406; ADD SI,EA_NAME ;FT. ;AN000;
407; ADD SI,AX ;FT. ;AN000;
408; CMP DX,0 ;FT. ;AN000;
409; JNZ set_filetyp ;FT. ;AN000;
410; LODSW ;FT. ;AN000;
411; CMP [XA_DEVICE],0 ;FT. device ? ;AN000;
412; JZ notdevice ;FT. no ;AN000;
413; OR AX,AX ;FT. code page 0 ? ;AN000;
414; JZ NORM0 ;FT. yes ;AN000;
415;
416; CALL GSetDevCdPg ;FT. ;AN000;
417; JNC welldone ;FT. ;AN000;
418; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000;
419; JZ NORM0 ;FT. no ;AN000;
420; invoke SAVE_WORLD ;FT. save all regs ;AN000;
421; LDS SI,[THISSFT] ;FT. ds:si -> sft ;AN000;
422; LDS SI,[SI.sf_devptr] ;FT. ds:si -> device header ;AN000;
423; MOV BP,DS ;FT. save all regs ;AN000;
424; invoke Code_Page_Mismatched_Error ;FT. ;AN000;
425; CMP AL,0 ;FT. ignore ? ;AN000;
426; JZ NORM1 ;FT. ;AN000;
427; invoke RESTORE_WORLD ;FT. save all regs ;AN000;
428;NORM0:
429; MOV AL,EARCDEVERROR ;FT. ;AN000;
430; STC ;FT. ;AN000;
431; JMP SHORT sdone ;FT. ;AN000;
432;NORM1:
433; invoke RESTORE_WORLD ;FT. save all regs ;AN000;
434; JMP SHORT welldone ;FT. ;AN000;
435;notdevice:
436; LDS SI,[THISSFT] ;FT. ;AN000;
437; MOV [SI.sf_CodePage],AX ;FT. set codepege ;AN000;
438; JMP SHORT welldone ;FT.
439;set_filetyp:
440; LODSB ;FT. ;AN000;
441; LDS SI,[THISSFT] ;FT. set filtype ;AN000;
442; MOV [SI.sf_ATTR_HI],AL ;FT. ;AN000;
443;
444;welldone:
445; XOR AL,AL ;FT. success ;AN000;
446;sdone:
447; POP SI ;FT. ;AN000;
448; POP DS ;FT. ;AN000;
449;notset:
450; POP CX ;FT. ;AN000;
451; return ;FT. ;AN000;
452 ;AN000;
453;EndProc SET_ONE_EA ;AN000;
454 ;AN000;
455; Input: ES:DI= buffer address ;AN000;
456; DS:SI= EA entry address
457; [SAVE_CX]= buffer size available
458; [SAVE_BX]= size returned
459; DX= EA ID (0 codpage, 1 Filetype, etc.)
460; Function: move one EA entry to the buffer ;AN000;
461; Output: carry clear
462; DS:SI points to next entry
463; ES:DI points to next entry
464; [SAVE_CX],BX, updated ;AN000;
465; carry set, insufficient memory error ;AN000;
466 ;AN000;
467;procedure GET_ONE_EA,NEAR ;AN000;
468; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
469; ;AN000;
470; PUSH CX ;FT. ;AN000;
471; CMP [XA_TYPE],2 ;FT. type 2 ? ;AN000;
472; JZ gtyp2 ;FT. yes ;AN000;
473; MOV CX,QEA_NAME - QEA_TYPE ;FT. ;AN000;
474; JMP SHORT addnmlen ;FT.
475;gtyp2:
476; MOV CX,EA_NAME - EA_TYPE ;FT. cx = EA entry size ;AN000;
477; ADD CX,[SI.EA_VALLEN] ;FT. ;AN000;
478;addnmlen:
479; MOV AL,[SI.EA_NAMELEN] ;FT.
480; XOR AH,AH ;FT. ;AN000;
481; ADD CX,AX ;FT. ;AN000;
482; CMP CX,[SAVE_CX] ;FT. > buffer size ;AN000;
483; JA sizeshort ;FT. yes ;AN000;
484; PUSH CX ;FT. ;AN000;
485; LODSB ;FT. move type ;AN000;
486; STOSB ;FT. ;AN000;
487; LODSW ;FT. ;AN000;
488; STOSW ;FT. move flag ;AN000;
489; LODSB ;FT. EA list need RC ;AN000;
490; CMP [XA_TYPE],2 ;FT. ;AN000;
491; JNZ norc ;FT. ;AN000;
492; STOSB ;FT. ;AN000;
493;norc:
494; LODSB ;FT. move name len ;AN000;
495; STOSB ;FT. ;AN000;
496; MOV CL,AL ;FT. ;AN000;
497; XOR CH,CH ;FT. ;AN000;
498; LODSW ;FT. EA list need value len ;AN000;
499; CMP [XA_TYPE],2 ;FT. ;AN000;
500; JNZ novalen ;FT. ;AN000;
501; STOSW ;FT. ;AN000;
502;novalen:
503;
504; REP MOVSB ;FT. move EA to buffer ;AN000;
505; CMP [XA_TYPE],2 ;FT. ;AN000;
506; JNZ novalue ;FT. ;AN000;
507; CALL GET_VALUE ;FT. get value for type 2 ;AN000;
508;novalue:
509; POP CX ;FT. ;AN000;
510; ADD [SAVE_BX],CX ;FT. add entry size ;AN000;
511; LES DI,DWORD PTR [SAVE_DI] ;FT. ;AN000;
512; ADD DI,[SAVE_BX] ;FT. es:di -> next entry ;AN000;
513; SUB [SAVE_CX],CX ;FT. update buffer size ;AN000;
514; CLC ;FT. ;AN000;
515; JMP SHORT okget ;FT. ;AN000;
516;
517;sizeshort:
518; MOV AX,error_not_enough_memory ;FT. error ;AN000;
519; STC ;FT. ;AN000;
520;okget:
521; POP CX ;FT. ;AN000;
522; return ;FT. ;AN000;
523; ;AN000;
524;EndProc GET_ONE_EA ;AN000;
525 ;AN000;
526 ;AN000;
527; Input: DX= EA ID (0 codpage, 1 Filetype, etc.)
528; [THISSFT]= points to SFT
529; ES:DI= buffer address of EA value
530; [XA_DEVICE]=0 file, 1 device
531; Function: get attribute ;AN000;
532; Output: none ;AN000;
533; ;AN000;
534 ;AN000;
535;procedure GET_VALUE,NEAR ;AN000;
536; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
537; ;AN000;
538; PUSH DS ;FT. save ds:si ;AN000;
539; PUSH SI ;FT. ;AN000;
540; LDS SI,[ThisSFT] ;FT. ds:si -> SFT ;AN000;
541;
542; CMP DX,0 ;FT. code page ? ;AN000;
543; JNZ eafiltyp ;FT. no ;AN000;
544; CMP [XA_DEVICE],0 ;FT. device ? ;AN000;
545; JZ notdev ;FT. no ;AN000;
546; CALL GSetDevCdPg ;FT. do ioctl invoke ;AN000;
547; JNC okcdpg ;FT. error ? ;AN000;
548; PUSH DI ;FT. ;AN000;
549; XOR AX,AX ;FT. make code page 0 ;AN000;
550; LES DI,DWORD PTR [SAVE_DI] ;FT. ;AN000;
551; ADD DI,[SAVE_BX] ;FT. es:di -> beginning of entry ;AN000;
552; MOV ES:[DI.EA_RC],EARCNOTFOUND ;FT. ;AN000;
553; POP DI ;FT. ;AN000;
554; JMP SHORT okcdpg ;FT. ;AN000;
555;notdev:
556; MOV AX,[SI.sf_CodePage] ;FT. get code page from sft ;AN000;
557;okcdpg:
558; STOSW ;FT. put in buffer ;AN000;
559; JMP SHORT gotea ;FT. ;AN000;
560;eafiltyp:
561; MOV AL,[SI.sf_ATTR_HI] ;FT. get high attribute ;AN000;
562; STOSB ;FT. put in buffer ;AN000;
563;
564;gotea:
565; POP SI ;FT. retore regs ;AN000;
566; POP DS ;FT. ;AN000;
567; return ;FT. ;AN000;
568;EndProc GET_VALUE ;AN000;
569 ;AN000;
570 ;AN000;
571; Input: [XA_handle] = device handle ;AN000;
572; [XA_type] = 4 , set ;AN000;
573; AX= code page (set)
574; 2,3 get ;AN000;
575; Function: get or set device code page ;AN000;
576; Output: carry clear, AX= device code page (get) ;AN000;
577; carry set, error ;AN000;
578 ;AN000;
579;procedure GSetDevCdPg,near ;AN000;
580; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
581; ;AN000;
582; invoke SAVE_WORLD ;FT. save all regs ;AN000;
583; CMP [XA_type],4 ;FT. set ? ;AN000;
584; JZ setpg ;FT. yes ;AN000;
585; MOV CX,6AH ;FT. get selected code page ;AN000;
586; JMP SHORT dogset ;FT. ;AN000;
587;setpg: ;AN000;
588; MOV CX,4AH ;FT. set code page ;AN000;
589;IF DBCS
590;
591; invoke Save_World ;FT. save all regs ;AN000;
592; MOV BX,AX ;FT. bx= code page id ;AN000;
593; MOV AL,7 ;FT. get DBCS vectors ;AN000;
594; MOV DX,-1 ;FT. get current country ;AN000;
595; MOV CX,5 ;FT. minimum size ;AN000;
596; MOV DI,OFFSET DOSGROUP:DBCS_PACKET ;FT. ;AN000;
597; PUSH CS ;FT. ;AN000;
598; POP ES ;FT. ;AN000;
599; invoke $GetExtCntry ;FT. get DBCS vectors ;AN000;
600; JC nlsfunc_err ;FT. error ;AN000;
601; LDS SI,DWORD PTR DBCS_PACKET+1 ;FT. ;AN000;
602; LODSW ;FT. get vector length ;AN000;
603; MOV CX,AX ;FT. cx=length ;AN000;
604;
605; MOV DI,OFFSET DOSGROUP:XA_PACKET+4 ;FT. ;AN000;
606; PUSH CS ;FT. ;AN000;
607; POP ES ;FT. ;AN000;
608; REP MOVSB ;FT. ;AN000;
609; CLC ;FT. ;AN000;
610;nlsfunc_err:
611; invoke RESTORE_WORLD ;FT. restore all regs ;AN000;
612; JC deverr ;FT. ;AN000;
613;
614;ENDIF
615; MOV WORD PTR [XA_PACKET+2],AX ;FT. ;AN000;
616;dogset: ;AN000;
617; MOV BX,[XA_handle] ;FT. set up handle ;AN000;
618; PUSH CS ;FT. ds:dx -> packet ;AN000;
619; POP DS ;FT. ;AN000;
620; MOV DX,OFFSET DOSGROUP:XA_PACKET ;FT. ;AN000;
621; MOV AX,440CH ;FT. IOCTL to char device by handle ;AN000;
622; invoke $IOCTL ;FT. issue get code page ;AN000;
623; JC deverr ;FT. error ;AN000;
624; invoke RESTORE_WORLD ;FT. restore all regs ;AN000;
625; MOV AX,WORD PTR [XA_PACKET+2] ;FT. get code page ;AN000;
626; return ;FT. ;AN000;
627;deverr: ;AN000;
628; invoke RESTORE_WORLD ;FT. restore all regs ;AN000;
629; return ;FT. exit ;AN000;
630; ;AN000;
631;EndProc GSetDevCdPg ;AN000;
632 ;AN000;
633
634; Input: DS:SI -> query list
635;
636; Function: get max size ;AN000;
637; Output: CX= size
638; carry set error
639 ;AN000;
640;procedure Get_max_EA_size,NEAR ;AN000;
641; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
642; ;AN000;
643; CMP [SAVE_SI],0FFFFH ;FT. get all ? ;AN000;
644; JNZ scan_query ;FT. no ;AN000;
645; MOV CX,[MAX_EA_SIZE] ;FT. get max EA size ;AN000;
646; JMP SHORT gotit ;FT.
647;scan_query:
648; LDS SI,DWORD PTR [SAVE_SI] ;FT. ds:si -> query list ;AN000;
649; LODSW ;FT. ax= number of entries ;AN000;
650; MOV [SAVE_CX],AX ;FT. ;AN000;
651; XOR CX,CX ;FT. set initial size to 0 ;AN000;
652; OR AX,AX ;FT. if no entris ;AN000;
653; JZ gotit ;FT. then return ;AN000;
654; MOV CX,2 ;FT. at lesat 2 ;AN000;
655;NEXT_QEA:
656; CALL Search_EA ;FT. search EA ;AN000;
657; JC serror ;FT. wrong EA ;AN000;
658; ADD CX,size EA ;FT. get EA size ;AN000;
659; ADD CL,ES:[DI.EA_NAMELEN] ;FT. ;AN000;
660; ADC CH,0 ;FT. ;AN000;
661; ADD CX,ES:[DI.EA_VALLEN] ;FT. ;AN000;
662; DEC CX ;FT. ;AN000;
663; DEC [SAVE_CX] ;FT. end of entris ;AN000;
664; JZ gotit ;FT. no ;AN000;
665; MOV AL,[SI.QEA_NAMELEN] ;FT. update to next QEA ;AN000;
666; XOR AH,AH ;FT. update to next QEA ;AN000;
667; ADD SI,AX ;FT. update to next QEA ;AN000;
668; ADD SI,size QEA ;FT. ;AN000;
669; DEC SI ;FT. ;AN000;
670; JMP next_QEA ;FT. do next ;AN000;
671;serror:
672; MOV AX,error_invalid_data ;FT. set initial size to 0 ;AN000;
673;gotit: ;FT. ;AN000;
674; return ;FT. exit ;AN000;;FT. exit ;AN000;
675;
676;EndProc Get_max_EA_size ;FT. exit ;AN000; ;AN000;
677 ;AN000;
678CODE ENDS ;AN000;
679END ;AN000;
diff --git a/v4.0/src/DOS/FAT.ASM b/v4.0/src/DOS/FAT.ASM
new file mode 100644
index 0000000..971c427
--- /dev/null
+++ b/v4.0/src/DOS/FAT.ASM
@@ -0,0 +1,695 @@
1; SCCSID = @(#)fat.asm 1.3 85/08/15
2; SCCSID = @(#)fat.asm 1.3 85/08/15
3TITLE FAT - FAT maintenance routines
4NAME FAT
5; Low level local device routines for performing disk change sequence,
6; setting cluster validity, and manipulating the FAT
7;
8; IsEof
9; UNPACK
10; PACK
11; MAPCLUSTER
12; FATREAD_SFT
13; FATREAD_CDS
14; FAT_operation
15;
16; Revision history:
17;
18; AN000 version Jan. 1988
19; A001 PTM -- disk changed for look ahead buffers
20;
21
22;
23; get the appropriate segment definitions
24;
25.xlist
26include dosseg.asm
27
28CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME SS:DOSGROUP,CS:DOSGROUP
30
31.xcref
32INCLUDE DOSSYM.INC
33INCLUDE DEVSYM.INC
34.cref
35.list
36
37FastDiv = TRUE
38
39 i_need CURBUF,DWORD
40 i_need CLUSSPLIT,BYTE
41 i_need CLUSSAVE,WORD
42 i_need CLUSSEC,DWORD ;F.C. >32mb ;AN000;
43 i_need THISDRV,BYTE
44 i_need THISDPB,DWORD
45 i_need DEVCALL,BYTE
46 i_need CALLMED,BYTE
47 i_need CALLRBYT,BYTE
48 i_need BUFFHEAD,DWORD
49 i_need CALLXAD,DWORD
50 i_need CALLBPB,DWORD
51 i_need CDSADDR,DWORD
52 i_need CDSCOUNT,BYTE
53 i_need EXTERR,WORD
54 i_need EXTERRPT,DWORD
55 i_need CALLVIDM,DWORD
56 i_need ReadOp,BYTE
57 i_need FAILERR,BYTE
58 i_need ALLOWED,BYTE
59 i_need VOLCHNG_FLAG,BYTE
60 i_need HIGH_SECTOR,WORD
61 i_need BUF_HASH_COUNT,WORD
62 i_need BUF_HASH_PTR,DWORD
63 i_need FIRST_BUFF_ADDR,WORD
64 i_need SC_CACHE_COUNT,WORD ;AN001;
65 i_need CURSC_DRIVE,BYTE ;AN001;
66
67
68Break <IsEOF - check the quantity in BX for EOF>
69
70;
71; IsEOF - check the fat value in BX for eof.
72;
73; Inputs: ES:BP point to DPB
74; BX has fat value
75; Outputs: JAE eof
76; Registers modified: none
77Procedure IsEof,NEAR
78 ASSUME SS:DOSGROUP,CS:DOSGROUP,DS:NOTHING,ES:NOTHING
79 Assert ISDPB,<ES,BP>,"IsEOF"
80 CMP ES:[BP.dpb_max_cluster],4096-10 ; is this 16 bit fat?
81 JAE EOF16 ; yes, check for eof there
82;J.K. 8/27/86
83;Modified to accept 0FF0h as an eof. This is to handle the diskfull case
84;of any media that has "F0"(Other) as a MediaByte.
85;Hopely, this does not create any side effect for those who may use any value
86;other than "FF8-FFF" as an Eof for their own file.
87 cmp bx,0FF0h
88 je IsEOF_other
89 CMP BX,0FF8h ; do the 12 bit compare
90IsEOF_other:
91 return
92EOF16:
93 CMP BX,0FFF8h ; 16 bit compare
94 return
95EndProc IsEof
96
97Break <UNPACK -- UNPACK FAT ENTRIES>
98
99; Inputs:
100; BX = Cluster number (may be full 16-bit quantity)
101; ES:BP = Base of drive parameters
102; Outputs:
103; DI = Contents of FAT for given cluster (may be full 16-bit quantity)
104; Zero set means DI=0 (free cluster)
105; Carry set means error (currently user FAILed to I 24)
106; SI Destroyed, No other registers affected. Fatal error if cluster too big.
107
108 procedure UNPACK,NEAR
109 DOSAssume CS,<DS>,"UnPack"
110 ASSUME ES:NOTHING
111
112 Assert ISDPB,<ES,BP>,"Unpack"
113 CMP BX,ES:[BP.dpb_max_cluster]
114 JA HURTFAT
115 CALL MAPCLUSTER
116ASSUME DS:NOTHING
117 jc DoContext
118 MOV DI,[DI]
119 JNZ High12 ; MZ if high 12 bits, go get 'em
120 MOV SI,ES:[BP.dpb_max_cluster] ; MZ is this 16-bit fat?
121 CMP SI,4096-10
122 JB Unpack12 ; MZ No, go 'AND' off bits
123 OR DI,DI ; MZ set zero condition code, clears carry
124 JMP SHORT DoContext ; MZ go do context
125
126High12:
127 SHR DI,1
128 SHR DI,1
129 SHR DI,1
130 SHR DI,1
131Unpack12:
132 AND DI,0FFFH ; Clears carry
133DoContext:
134 PUSH SS
135 POP DS
136 return
137
138HURTFAT:
139 MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace
140 PUSH AX
141 MOV AH,allowed_fail + 80h
142 MOV Allowed,allowed_fail
143;
144; Signal Bad FAT to INT int_fatal_abort handler. We have an invalid cluster.
145;
146 MOV DI,0FFFH ; In case INT int_fatal_abort returns (it shouldn't)
147 invoke FATAL
148 CMP AL,3
149 CLC
150 JNZ OKU_RET ; Try to ignore bad FAT
151 STC ; User said FAIL
152OKU_RET:
153 POP AX
154 return
155EndProc UNPACK
156
157Break <PACK -- PACK FAT ENTRIES>
158
159; Inputs:
160; BX = Cluster number
161; DX = Data
162; ES:BP = Pointer to drive DPB
163; Outputs:
164; The data is stored in the FAT at the given cluster.
165; SI,DX,DI all destroyed
166; Carry set means error (currently user FAILed to I 24)
167; No other registers affected
168
169 procedure PACK,NEAR
170 DOSAssume CS,<DS>,"Pack"
171 ASSUME ES:NOTHING
172
173 Assert ISDPB,<ES,BP>,"Pack"
174 CALL MAPCLUSTER
175ASSUME DS:NOTHING
176 JC DoContext
177 MOV SI,[DI]
178 JZ Aligned ; byte (not nibble) aligned
179 PUSH CX ; move data to upper 12 bits
180 MOV CL,4
181 SHL DX,CL
182 POP CX
183 AND SI,0FH ; leave in original low 4 bits
184 JMP SHORT PACKIN
185ALIGNED:
186 CMP ES:[BP.dpb_max_cluster],4096-10 ; MZ 16 bit fats?
187 JAE Pack16 ; MZ yes, go clobber original data
188 AND SI,0F000H ; MZ leave in upper 4 bits of original
189 AND DX,0FFFh ; MZ store only 12 bits
190 JMP SHORT PackIn ; MZ go store
191Pack16:
192 XOR SI,SI ; MZ no original data
193PACKIN:
194 OR SI,DX
195 MOV [DI],SI
196 LDS SI,[CURBUF]
197 TEST [SI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
198 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
199 invoke INC_DIRTY_COUNT ;LB. ;AN000;
200 OR [SI.buf_flags],buf_dirty ;LB. ;AN000;
201yesdirty: ;LB. ;AN000;
202 CMP BYTE PTR [CLUSSPLIT],0
203 Context DS
204 retz ; Carry clear
205 PUSH AX
206 PUSH BX
207 PUSH CX
208 MOV AX,[CLUSSAVE]
209 MOV DS,WORD PTR [CURBUF+2]
210ASSUME DS:NOTHING
211 ADD SI,BUFINSIZ
212 MOV [SI],AH
213 Context DS
214 PUSH AX
215 MOV DX,WORD PTR [CLUSSEC+2] ;F.C. >32mb ;AN000;
216 MOV WORD PTR [HIGH_SECTOR],DX ;F.C. >32mb ;AN000;
217
218 MOV DX,WORD PTR [CLUSSEC]
219 MOV SI,1
220 XOR AL,AL
221 invoke GETBUFFRB
222 POP AX
223 JC POPP_RET
224 LDS DI,[CURBUF]
225ASSUME DS:NOTHING
226 TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
227 JNZ yesdirty2 ;LB. don't increment dirty count ;AN000;
228 invoke INC_DIRTY_COUNT ;LB. ;AN000;
229 OR [DI.buf_flags],buf_dirty
230yesdirty2:
231 ADD DI,BUFINSIZ
232 DEC DI
233 ADD DI,ES:[BP.dpb_sector_size]
234 MOV [DI],AL
235 CLC
236POPP_RET:
237 PUSH SS
238 POP DS
239 POP CX
240 POP BX
241 POP AX
242 return
243
244EndProc PACK
245
246Break <MAPCLUSTER - BUFFER A FAT SECTOR>
247
248; Inputs:
249; ES:BP Points to DPB
250; BX Is cluster number
251; Function:
252; Get a pointer to the cluster
253; Outputs:
254; DS:DI Points to contents of FAT for given cluster
255; DS:SI Points to start of buffer
256; Zero Not set if cluster data is in high 12 bits of word
257; Zero set if cluster data is in low 12 or 16 bits
258; Carry set if failed.
259; SI is destroyed.
260
261 procedure MAPCLUSTER,NEAR
262 DOSAssume CS,<DS>,"MapCluster"
263 ASSUME ES:NOTHING
264
265 Assert ISDPB,<ES,BP>,"MapCluster"
266 MOV BYTE PTR [CLUSSPLIT],0
267 SaveReg <AX,BX,CX,DX>
268 MOV AX,BX ; AX = BX
269 MOV CX,4096-10
270 CMP ES:[BP.dpb_max_cluster],CX ; MZ 16 bit fat?
271 JAE Map16 ; MZ yes, do 16 bit algorithm
272 SHR AX,1 ; AX = BX/2
273Map16: ; MZ skip prev => AX=2*BX
274 XOR DI,DI ; >32mb fat ;AN000;
275 ADD AX,BX ; AX = 1.5*fat = byte offset in fat
276 ADC DI,0 ; >32mb fat ;AN000;
277DoConvert:
278 MOV CX,ES:[BP.dpb_sector_size]
279IF FastDiv
280;
281; Gross hack: 99% of all disks have 512 bytes per sector. We test for this
282; case and apply a really fast algorithm to get the desired results
283;
284; Divide method takes 158 (XOR and DIV)
285; Fast method takes 20
286;
287; This saves a bunch.
288;
289 CMP CX,512 ; 4 Is this 512 byte sector?
290 JZ Nodiv ;F.C. >32mb ;AN000;
291 JMP DoDiv ; 4/16 No, go do divide
292Nodiv: ;F.C. >32mb ;AN000;
293 MOV DX,AX ; 2 get set for remainder
294 AND DX,512-1 ; 4 Form remainder
295 MOV AL,AH ; 2
296 SHR AL,1 ; 2
297 CBW ; 2 Fast divide by 512
298 OR DI,DI ;>32mb >64k ? ;AN000;
299 JZ g64k ;>32mb no ;AN000;
300 OR AX,80H ;>32mb ;AN000;
301g64k:
302ELSE
303 XOR DX,DX ; 3
304 DIV CX ; 155 AX is FAT sector # DX is sector index
305ENDIF
306DivDone:
307 ADD AX,ES:[BP.dpb_first_FAT]
308 DEC CX ; CX is sector size - 1
309 SaveReg <AX,DX,CX>
310 MOV DX,AX
311 MOV [HIGH_SECTOR],0 ;F.C. >32mb low sector #
312 XOR AL,AL
313 MOV SI,1
314 invoke GETBUFFRB
315 RestoreReg <CX,AX,DX> ; CX is sec siz-1, AX is offset in sec
316 JC MAP_POP
317 LDS SI,[CURBUF]
318ASSUME DS:NOTHING
319 LEA DI,[SI.BufInSiz]
320 ADD DI,AX
321 CMP AX,CX
322 JNZ MAPRET
323 MOV AL,[DI]
324 Context DS
325 INC BYTE PTR [CLUSSPLIT]
326 MOV BYTE PTR [CLUSSAVE],AL
327 MOV WORD PTR [CLUSSEC],DX
328 MOV WORD PTR [CLUSSEC+2],0 ;F.C. >32mb ;AN000;
329 INC DX
330 MOV [HIGH_SECTOR],0 ;F.C. >32mb FAT sector <32mb ;AN000;
331 XOR AL,AL
332 MOV SI,1
333 invoke GETBUFFRB
334 JC MAP_POP
335 LDS SI,[CURBUF]
336ASSUME DS:NOTHING
337 LEA DI,[SI.BufInSiz]
338 MOV AL,[DI]
339 Context DS
340 MOV BYTE PTR [CLUSSAVE+1],AL
341 MOV DI,OFFSET DOSGROUP:CLUSSAVE
342MAPRET:
343 RestoreReg <DX,CX,BX>
344 XOR AX,AX ; MZ allow shift to clear carry
345 CMP ES:[BP.dpb_max_cluster],4096-10 ; MZ is this 16-bit fat?
346 JAE MapSet ; MZ no, set flags
347 MOV AX,BX
348MapSet:
349 TEST AL,1 ; set zero flag if not on boundary
350 RestoreReg <AX>
351 return
352
353MAP_POP:
354 RestoreReg <DX,CX,BX,AX>
355 return
356IF FastDiv
357DoDiv:
358 XOR DX,DX ; 3
359 DIV CX ; 155 AX is FAT sector # DX is sector index
360 JMP DivDone ;15 total=35
361ENDIF
362
363EndProc MAPCLUSTER
364
365Break <FATREAD_SFT/FATREAD_CDS -- CHECK DRIVE GET FAT>
366
367; Inputs:
368; ES:DI points to an SFT for the drive of intrest (local only,
369; giving a NET SFT will produce system crashing results).
370; DS DOSGROUP
371; Function:
372; Can be used by an SFT routine (like CLOSE) to invalidate buffers
373; if disk changed.
374; In other respects, same as FATREAD_CDS.
375; (note ES:DI destroyed!)
376; Outputs:
377; Carry set if error (currently user FAILed to I 24)
378; NOTE: This routine may cause FATREAD_CDS to "miss" a disk change
379; as far as invalidating curdir_ID is concerned.
380; Since getting a true disk changed on this call is a screw up
381; anyway, that's the way it goes.
382
383 procedure FATREAD_SFT,NEAR
384 DOSAssume CS,<DS>,"FATRead_SFT"
385 ASSUME ES:NOTHING
386
387 LES BP,ES:[DI.sf_devptr]
388 Assert ISDPB,<ES,BP>,"FatReadSFT"
389 MOV AL,ES:[BP.dpb_drive]
390 MOV [THISDRV],AL
391 invoke GOTDPB ;Set THISDPB
392 CALL FAT_GOT_DPB
393 return
394EndProc FATREAD_SFT
395
396; Inputs:
397; DS:DOSGROUP
398; ES:DI points to an CDS for the drive of intrest (local only,
399; giving a NET or NUL CDS will produce system crashing results).
400; Function:
401; If disk may have been changed, media is determined and buffers are
402; flagged invalid. If not, no action is taken.
403; Outputs:
404; ES:BP = Drive parameter block
405; [THISDPB] = ES:BP
406; [THISDRV] set
407; Carry set if error (currently user FAILed to I 24)
408; DS preserved , all other registers destroyed
409
410 procedure FATREAD_CDS,NEAR
411 DOSAssume CS,<DS>,"FATRead_CDS"
412 ASSUME ES:NOTHING
413
414 PUSH ES
415 PUSH DI
416 LES BP,ES:[DI.curdir_devptr]
417 Assert ISDPB,<ES,BP>,"FatReadCDS"
418 MOV AL,ES:[BP.dpb_drive]
419 MOV [THISDRV],AL
420 invoke GOTDPB ;Set THISDPB
421 CALL FAT_GOT_DPB
422 POP DI ;Get back CDS pointer
423 POP ES
424 retc
425 JNZ NO_CHANGE ;Media NOT changed
426; Media changed. We now need to find all CDS structures which use this
427; DPB and invalidate their ID pointers.
428MED_CHANGE:
429 XOR AX,AX
430 DEC AX ;AX = -1
431 PUSH DS
432 MOV CL,[CDSCOUNT]
433 XOR CH,CH ; CX is number of structures
434 LDS SI,ES:[DI.curdir_devptr] ; Find all CDS with this devptr
435ASSUME DS:NOTHING
436 LES DI,[CDSADDR] ; Start here
437CHECK_CDS:
438 TEST ES:[DI.curdir_flags],curdir_isnet
439 JNZ NEXTCDS ; Leave NET guys alone!!
440 PUSH ES
441 PUSH DI
442 LES DI,ES:[DI.curdir_devptr]
443 invoke POINTCOMP
444 POP DI
445 POP ES
446 JNZ NEXTCDS ; CDS not for this drive
447 TEST ES:[DI.curdir_ID],AX
448 JZ NEXTCDS ; If root, leave root
449 MOV ES:[DI.curdir_ID],AX ; else invalid
450NEXTCDS:
451 ADD DI,SIZE curdir_list ; Point to next CDS
452 LOOP CHECK_CDS
453 POP DS
454 DOSAssume CS,<DS>,"FAT/NextCDS"
455NO_CHANGE:
456 LES BP,[THISDPB]
457 CLC
458 return
459EndProc FATREAD_CDS
460
461Break <Fat_Operation - miscellaneous fat stuff>
462
463 procedure FAT_operation,NEAR
464FATERR:
465 DOSAssume CS,<DS>,"FATERR"
466 MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace
467 AND DI,STECODE ; Put error code in DI
468 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
469 MOV AH,2 + allowed_FAIL + allowed_RETRY ; While trying to read FAT
470 MOV AL,BYTE PTR [THISDRV] ; Tell which drive
471 invoke FATAL1
472 LES BP,[THISDPB]
473 CMP AL,3
474 JNZ FAT_GOT_DPB ; User said retry
475 STC ; User said FAIL
476 return
477
478FAT_GOT_DPB:
479 Context DS
480 MOV AL,DMEDHL
481 MOV AH,ES:[BP.dpb_UNIT]
482 MOV WORD PTR [DEVCALL],AX
483 MOV BYTE PTR [DEVCALL.REQFUNC],DEVMDCH
484 MOV [DEVCALL.REQSTAT],0
485 MOV AL,ES:[BP.dpb_media]
486 MOV BYTE PTR [CALLMED],AL
487 PUSH ES
488 PUSH DS
489 MOV BX,OFFSET DOSGROUP:DEVCALL
490 LDS SI,ES:[BP.dpb_driver_addr] ; DS:SI Points to device header
491ASSUME DS:NOTHING
492 POP ES ; ES:BX Points to call header
493 invoke DEVIOCALL2
494 Context DS
495 POP ES ; Restore ES:BP
496 MOV DI,[DEVCALL.REQSTAT]
497 TEST DI,STERR
498 JNZ FATERR
499 XOR AH,AH
500 XCHG AH,ES:[BP.dpb_first_access] ; Reset dpb_first_access
501 MOV AL,BYTE PTR [THISDRV] ; Use physical unit number
502; See if we had changed volume id by creating one on the diskette
503 cmp [VOLCHNG_FLAG],AL
504 jnz CHECK_BYT
505 mov [VOLCHNG_FLAG],-1
506 jmp GOGETBPB ; Need to get device driver to read in
507 ; new volume label.
508CHECK_BYT:
509 OR AH,BYTE PTR [CALLRBYT]
510 JNS CHECK_ZR ; ns = 0 or 1
511 JMP NEWDSK
512
513CHECK_ZR:
514 JZ CHKBUFFDIRT ; jump if I don't know
515 CLC
516 return ; If Media not changed (NZ)
517
518DISK_CHNG_ERR:
519ASSUME DS:NOTHING
520 PUSH ES
521 PUSH BP
522 LES BP,ES:[BP.dpb_driver_addr] ; Get device pointer
523 TEST ES:[BP.SDEVATT],DEVOPCL ; Did it set vol id?
524 POP BP
525 POP ES
526 JZ FAIL_OPJ2 ; Nope, FAIL
527 PUSH DS ; Save buffer pointer for ignore
528 PUSH DI
529 Context DS
530 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
531 PUSH ES
532 LES DI,[CALLVIDM] ; Get volume ID pointer
533 MOV WORD PTR [EXTERRPT+2],ES
534 POP ES
535 MOV WORD PTR [EXTERRPT],DI
536 MOV AX,error_I24_wrong_disk
537 MOV [READOP],1 ; Write
538 invoke HARDERR
539 POP DI ; Get back buffer for ignore
540 POP DS
541ASSUME DS:NOTHING
542 CMP AL,3
543FAIL_OPJ2:
544 JZ FAIL_OP
545 JMP FAT_GOT_DPB ; Retry
546
547CHKBUFFDIRT:
548 DOSAssume CS,<DS>,"FAT/ChkBuffDirt"
549; LDS DI,[BUFFHEAD]
550ASSUME DS:NOTHING
551 XOR DX,DX ;LB. ;AN000;
552 LDS DI,[BUF_HASH_PTR] ;LB. scan from 1st entry ;AN000;
553 MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000;
554
555scan_dirty:
556 CMP [DI.Dirty_Count],0 ;LB. if not dirty ;AN000;
557 JZ GETNEXT ;LB. get next hash entry ;AN000;
558 PUSH DS ;LB. save hash entry addr ;AN000;
559 PUSH DI ;LB. ;AN000;
560 invoke Map_Entry ;LB. ;AN000;
561NBUFFER: ; Look for dirty buffers
562 CMP AL,[DI.buf_ID]
563 JNZ LFNXT ; Not for this unit
564 TEST [DI.buf_flags],buf_dirty
565 JZ LFNXT
566 POP DI ;LB. restore regs ;AN000;
567 POP DS ;LB. ;AN000;
568 Context DS
569 CLC
570 return ; There is a dirty buffer, assume Media OK (NZ)
571
572FAIL_OP:
573 Context DS
574 STC
575 return
576
577ASSUME DS:NOTHING
578LFNXT:
579 mov DI,[DI.buf_next] ;; 1/19/88
580 CMP DI,[FIRST_BUFF_ADDR] ;; 1/19/88
581 JNZ NBUFFER
582 POP DI ;LB. restore regs ;AN000;
583 POP DS ;LB. ;AN000;
584GETNEXT:
585 ADD DI,size BUFFER_HASH_ENTRY ;LB. next entry ;AN000;
586 LOOP scan_dirty ;LB. scan next entry ;AN000;
587; If no dirty buffers, assume Media changed
588NEWDSK:
589 MOV ES:[BP.dpb_free_cnt],-1 ; Media changed, must re-compute
590 ; NOTE: It is TECHNICALLY more correct
591ASSUME DS:NOTHING
592 XOR DX,DX ;LB. ;AN000;
593 MOV [HIGH_SECTOR],DX ;LB. scan from 1st entry ;AN000;
594 MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000;
595
596NxtHash:
597 invoke GETCURHEAD ;LB. get Hash entry buffer header ;AN000;
598 ; to do this AFTER the check for
599ASSUME DS:NOTHING
600NXBUFFER:
601 CMP AL,[DI.buf_ID] ; For this drive?
602 JZ OLDDRV2 ;LB. yes ;AN000;
603 mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000;
604 JMP SHORT SKPBUFF ;LB. ;AN000;
605OLDDRV2:
606 TEST [DI.buf_flags],buf_dirty
607 JZ OldDrv
608 JMP Disk_Chng_Err ; Disk changed but dirty buffers
609OLDDRV:
610 MOV WORD PTR [DI.buf_ID],(buf_visit SHL 8) OR 0FFH ; Free up buffer
611 invoke SCANPLACE
612SKPBUFF:
613 CMP DI,[FIRST_BUFF_ADDR] ;LB. end of chain 1/19/88 ;AN000;
614 JNZ NXBUFFER ;LB. no ;AN000;
615 INC DX ;LB. ;AN000;
616 LOOP NxtHash ;LB. ;AN000;
617 CMP [SC_CACHE_COUNT],0 ;LB. look ahead buffers ? ;AN001;
618 JZ GOGETBPB ;LB. no ;AN001;
619 CMP AL,[CURSC_DRIVE] ;LB. same as changed drive ;AN001;
620 JNZ GOGETBPB ;LB. no ;AN001;
621 MOV [CURSC_DRIVE],-1 ;LB. invalidate look ahead buffers ;AN000;
622GOGETBPB:
623 LDS DI,ES:[BP.dpb_driver_addr]
624 TEST [DI.SDEVATT],ISFATBYDEV
625 JNZ GETFREEBUF
626 context DS
627 MOV BX,2
628 CALL UNPACK ; Read the first FAT sector into CURBUF
629FAIL_OPJ:
630 JC FAIL_OP
631 LDS DI,[CURBUF]
632ASSUME DS:NOTHING
633 JMP SHORT GOTGETBUF
634
635GETFREEBUF:
636ASSUME DS:NOTHING
637 PUSH ES ; Get a free buffer for BIOS to use
638 PUSH BP
639; LDS DI,[BUFFHEAD]
640 XOR DX,DX ;LB. fake to get 1st ;AN000;
641 MOV [HIGH_SECTOR],DX ;LB. buffer addr ;AN000;
642 invoke GETCURHEAD ;LB. ;AN000;
643
644 invoke BUFWRITE
645 POP BP
646 POP ES
647 JC FAIL_OPJ
648GOTGETBUF:
649 ADD DI,BUFINSIZ
650 MOV WORD PTR [CALLXAD+2],DS
651 Context DS
652 MOV WORD PTR [CALLXAD],DI
653 MOV AL,DBPBHL
654 MOV AH,BYTE PTR ES:[BP.dpb_UNIT]
655 MOV WORD PTR [DEVCALL],AX
656 MOV BYTE PTR [DEVCALL.REQFUNC],DEVBPB
657 MOV [DEVCALL.REQSTAT],0
658 MOV AL,BYTE PTR ES:[BP.dpb_media]
659 MOV [CALLMED],AL
660 PUSH ES
661 PUSH DS
662 PUSH WORD PTR ES:[BP.dpb_driver_addr+2]
663 PUSH WORD PTR ES:[BP.dpb_driver_addr]
664 MOV BX,OFFSET DOSGROUP:DEVCALL
665 POP SI
666 POP DS ; DS:SI Points to device header
667ASSUME DS:NOTHING
668 POP ES ; ES:BX Points to call header
669 invoke DEVIOCALL2
670 POP ES ; Restore ES:BP
671 Context DS
672 MOV DI,[DEVCALL.REQSTAT]
673 TEST DI,STERR
674 JNZ FATERRJ
675 MOV AL,BYTE PTR ES:[BP.dpb_media]
676 LDS SI,[CALLBPB]
677ASSUME DS:NOTHING
678 MOV ES:[BP].DPB_next_free,0 ; recycle scanning pointer
679 invoke $SETDPB
680 LDS DI,[CALLXAD] ; Get back buffer pointer
681 MOV AL,BYTE PTR ES:[BP.dpb_FAT_count]
682 MOV [DI.buf_wrtcnt-BUFINSIZ],AL ;>32mb ;AN000;
683 MOV AX,ES:[BP.dpb_FAT_size] ;>32mb ;AC000;
684 MOV [DI.buf_wrtcntinc-BUFINSIZ],AX ;>32mb Correct buffer info ;AC000;
685
686 Context DS
687 XOR AL,AL ;Media changed (Z), Carry clear
688 return
689
690FATERRJ: JMP FATERR
691
692EndProc FAT_operation
693
694CODE ENDS
695 END
diff --git a/v4.0/src/DOS/FCB.ASM b/v4.0/src/DOS/FCB.ASM
new file mode 100644
index 0000000..2b51da6
--- /dev/null
+++ b/v4.0/src/DOS/FCB.ASM
@@ -0,0 +1,504 @@
1; SCCSID = @(#)fcb.asm 1.2 85/07/23
2; SCCSID = @(#)fcb.asm 1.2 85/07/23
3TITLE FCB - FCB parse calls for MSDOS
4NAME FCB
5; Low level routines for parsing names into FCBs and analyzing
6; filename characters
7;
8; MakeFcb
9; NameTrans
10; PATHCHRCMP
11; GetLet
12; TESTKANJ
13; NORMSCAN
14; DELIM
15;
16; Revision history:
17;
18; A000 version 4.00 Jan. 1988
19;
20
21;
22; get the appropriate segment definitions
23;
24.xlist
25include dosseg.asm
26
27
28TableLook equ -1
29
30Table Segment
31Zero label byte
32Table ENDS
33
34CODE SEGMENT BYTE PUBLIC 'CODE'
35 ASSUME SS:DOSGROUP,CS:DOSGROUP
36
37.xcref
38include dossym.inc
39include devsym.inc
40include doscntry.inc ;AN000; 2/12/KK
41.cref
42.list
43
44 i_need Name1,BYTE
45 i_need Creating,BYTE
46 i_need Attrib,BYTE
47 i_need SpaceFlag,BYTE
48 i_need FILE_UCASE_TAB,byte ;DOS 3.3
49 i_need COUNTRY_CDPG,byte ;AN000; 2/12/KK
50 i_need DrvErr,BYTE ;AN000; 2/12/KK
51 i_need DOS34_FLAG,WORD ;AN000; 2/12/KK
52
53 procedure MakeFcb,NEAR
54ScanSeparator = 1
55DRVBIT EQU 2
56NAMBIT EQU 4
57EXTBIT EQU 8
58 MOV BYTE PTR [SpaceFlag],0
59 XOR DL,DL ; Flag--not ambiguous file name
60 TEST AL,DRVBIT ; Use current drive field if default?
61 JNZ DEFDRV
62 MOV BYTE PTR ES:[DI],0 ; No - use default drive
63DEFDRV:
64 INC DI
65 MOV CX,8
66 TEST AL,NAMBIT ; Use current name fields as defualt?
67 XCHG AX,BX ; Save bits in BX
68 MOV AL," "
69 JZ FILLB ; If not, go fill with blanks
70 ADD DI,CX
71 XOR CX,CX ; Don't fill any
72FILLB:
73 REP STOSB
74 MOV CL,3
75 TEST BL,EXTBIT ; Use current extension as default
76 JZ FILLB2
77 ADD DI,CX
78 XOR CX,CX
79FILLB2:
80 REP STOSB
81 XCHG AX,CX ; Put zero in AX
82 STOSW
83 STOSW ; Initialize two words after to zero
84 SUB DI,16 ; Point back at start
85 TEST BL,ScanSeparator; Scan off separators if not zero
86 JZ SKPSPC
87 CALL SCANB ; Peel off blanks and tabs
88 CALL DELIM ; Is it a one-time-only delimiter?
89 JNZ NOSCAN
90 INC SI ; Skip over the delimiter
91SKPSPC:
92 CALL SCANB ; Always kill preceding blanks and tabs
93NOSCAN:
94 CALL GETLET
95 JBE NODRV ; Quit if termination character
96 IF DBCS ;AN000;
97 CALL TESTKANJ ;AN000;; 2/18/KK
98 JNE NODRV ;AN000;; 2/18/KK
99 ENDIF ;AN000;
100 CMP BYTE PTR[SI],":" ; Check for potential drive specifier
101 JNZ NODRV
102 INC SI ; Skip over colon
103 SUB AL,"@" ; Convert drive letter to drive number (A=1)
104 JBE BADDRV ; Drive letter out of range
105
106 PUSH AX
107 Invoke GetVisDrv
108 POP AX
109 JNC HavDrv
110 CMP [DrvErr],error_not_DOS_disk ; if not FAt drive ;AN000;
111 JZ HavDrv ; assume ok ;AN000;
112BADDRV:
113 MOV DL,-1
114HAVDRV:
115 STOSB ; Put drive specifier in first byte
116 INC SI
117 DEC DI ; Counteract next two instructions
118NODRV:
119 DEC SI ; Back up
120 INC DI ; Skip drive byte
121
122 entry NORMSCAN
123
124 MOV CX,8
125 CALL GETWORD ; Get 8-letter file name
126 CMP BYTE PTR [SI],"."
127 JNZ NODOT
128 INC SI ; Skip over dot if present
129 TEST [DOS34_FLAG],DBCS_VOLID2 ;AN000;
130 JZ VOLOK ;AN000;
131 MOVSB ; 2nd byte of DBCS ;AN000;
132 MOV CX,2 ;AN000;
133 JMP SHORT contvol ;AN000;
134VOLOK:
135 MOV CX,3 ; Get 3-letter extension
136contvol:
137 CALL MUSTGETWORD
138NODOT:
139 MOV AL,DL
140 return
141
142NONAM:
143 ADD DI,CX
144 DEC SI
145 return
146
147GETWORD:
148 CALL GETLET
149 JBE NONAM ; Exit if invalid character
150 DEC SI
151;
152; UGH!!! Horrible bug here that should be fixed at some point:
153; If the name we are scanning is longer than CX, we keep on reading!
154;
155MUSTGETWORD:
156 CALL GETLET
157;
158; If spaceFlag is set then we allow spaces in a pathname
159;
160 JB FILLNAM
161 JNZ MustCheckCX
162 TEST BYTE PTR [SpaceFlag],0FFh
163 JZ FILLNAM
164 CMP AL," "
165 JNZ FILLNAM
166
167MustCheckCX:
168 JCXZ MUSTGETWORD
169 DEC CX
170 CMP AL,"*" ; Check for ambiguous file specifier
171 JNZ NOSTAR
172 MOV AL,"?"
173 REP STOSB
174NOSTAR:
175 STOSB
176
177 IF DBCS ;AN000;
178 CALL TESTKANJ ;AN000;
179 JZ NOTDUAL3 ;AN000;
180 JCXZ BNDERR ; Attempt to straddle boundry ;AN000;
181 MOVSB ; Transfer second byte ;AN000;
182 DEC CX ;AN000;
183 JMP MUSTGETWORD ;AN000;
184BNDERR: ;AN000;
185 TEST [DOS34_FLAG],DBCS_VOLID ;AN000;
186 JZ notvolumeid ;AN000;
187 TEST [DOS34_FLAG],DBCS_VOLID2 ;AN000;
188 JNZ notvolumeid ;AN000;
189 OR [DOS34_FLAG],DBCS_VOLID2 ;AN000;
190 JMP MUSTGETWORD ;AN000;
191
192notvolumeid:
193;; INC CX ; Undo the store of the first byte
194 DEC DI
195 MOV AL," " ;PTM. ;AN000;
196 STOSB ;PTM. ;AN000;
197 INC SI ;PTM. ;AN000;
198 JMP MUSTGETWORD ;PTM. ;AN000;
199
200NOTDUAL3: ;AN000;
201 ENDIF ;AN000;
202
203 CMP AL,"?"
204 JNZ MUSTGETWORD
205 OR DL,1 ; Flag ambiguous file name
206 JMP MUSTGETWORD
207FILLNAM:
208 MOV AL," "
209 REP STOSB
210 DEC SI
211 return
212
213SCANB:
214 LODSB
215 CALL SPCHK
216 JZ SCANB
217 IF DBCS ;AN000; ;AN000;
218 CMP AL,81H ;AN000;; 1ST BYTE OF DBCS BLANK 2/18/KK ;AN000;
219 JNE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
220 CALL TESTKANJ ;AN000;; 2/23/KK 3/31/KK revoved ;AN000;
221 JE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
222 CMP BYTE PTR [SI],40H;AN000;H ; 2ND BYTE OF DBCS BLANK 2/18/KK 3/31/KK revove;AN000;
223 JNE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
224 INC SI ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
225 JMP SCANB ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
226 SCANB_EXIT: ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
227 ENDIF ;AN000;
228 DEC SI
229 return
230EndProc MakeFCB
231
232;
233; NameTrans is used by FindPath to scan off an element of a path. We must
234; allow spaces in pathnames
235;
236; Inputs: DS:SI points to start of path element
237; Outputs: Name1 has unpacked name, uppercased
238; ES = DOSGroup
239; DS:SI advanced after name
240; Registers modified: DI,AX,DX,CX
241procedure NameTrans,near
242 ASSUME DS:NOTHING,ES:NOTHING
243 MOV BYTE PTR [SpaceFlag],1
244 context ES
245 MOV DI,OFFSET DOSGROUP:NAME1
246 PUSH DI
247 MOV AX,' '
248 MOV CX,5
249 STOSB
250 REP STOSW ; Fill "FCB" at NAME1 with spaces
251 XOR AL,AL ; Set stuff for NORMSCAN
252 MOV DL,AL
253 STOSB
254 POP DI
255
256 CALL NORMSCAN
257IF DBCS ;AN000;;KK.
258 MOV AL,[NAME1] ;AN000;;KK. check 1st char
259 invoke testkanj ;AN000;;KK. dbcs ?
260 JZ notdbcs ;AN000;;KK. no
261 return ;AN000;;KK. yes
262notdbcs: ;AN000;
263ENDIF ;AN000;
264 CMP [NAME1],0E5H
265 retnz
266 MOV [NAME1],5 ; Magic name translation
267 return
268
269EndProc nametrans
270
271Break <GETLET, DELIM -- CHECK CHARACTERS AND CONVERT>
272
273If TableLook
274ChType Macro ch,bits
275 ORG CharType-Zero+ch
276 db bits
277 ENDM
278
279Table SEGMENT
280 PUBLIC CharType
281Public FCB001S,FCB001E
282FCB001S label byte
283CharType DB 256 dup (-1)
284 ChType ".", <LOW (NOT ( fChk))>
285 ChType '"', <LOW (NOT (fFCB+fChk))>
286 ChType "/", <LOW (NOT (fFCB+fChk))>
287 ChType "\", <LOW (NOT (fFCB+fChk))>
288 ChType "[", <LOW (NOT (fFCB+fChk))>
289 ChType "]", <LOW (NOT (fFCB+fChk))>
290 ChType ":", <LOW (NOT (fFCB+fChk+fDelim))>
291 ChType "<", <LOW (NOT (fFCB+fChk+fDelim))>
292 ChType "|", <LOW (NOT (fFCB+fChk+fDelim))>
293 ChType ">", <LOW (NOT (fFCB+fChk+fDelim))>
294 ChType "+", <LOW (NOT (fFCB+fChk+fDelim))>
295 ChType "=", <LOW (NOT (fFCB+fChk+fDelim))>
296 ChType ";", <LOW (NOT (fFCB+fChk+fDelim))>
297 ChType ",", <LOW (NOT (fFCB+fChk+fDelim))>
298 ChType 0, <LOW (NOT (fFCB+fChk))> ; NUL
299 ChType 1, <LOW (NOT (fFCB+fChk))> ; ^A
300 ChType 2, <LOW (NOT (fFCB+fChk))> ; ^b
301 ChType 3, <LOW (NOT (fFCB+fChk))> ; ^c
302 ChType 4, <LOW (NOT (fFCB+fChk))> ; ^d
303 ChType 5, <LOW (NOT (fFCB+fChk))> ; ^e
304 ChType 6, <LOW (NOT (fFCB+fChk))> ; ^f
305 ChType 7, <LOW (NOT (fFCB+fChk))> ; ^g
306 ChType 8, <LOW (NOT (fFCB+fChk))> ; ^h
307 ChType 9, <LOW (NOT (fFCB+fChk+fDelim+fSpChk))> ; Tab
308 ChType 10, <LOW (NOT (fFCB+fChk))> ; ^j
309 ChType 11, <LOW (NOT (fFCB+fChk))> ; ^k
310 ChType 12, <LOW (NOT (fFCB+fChk))> ; ^l
311 ChType 13, <LOW (NOT (fFCB+fChk))> ; ^m
312 ChType 14, <LOW (NOT (fFCB+fChk))> ; ^n
313 ChType 15, <LOW (NOT (fFCB+fChk))> ; ^o
314 ChType 16, <LOW (NOT (fFCB+fChk))> ; ^p
315 ChType 17, <LOW (NOT (fFCB+fChk))> ; ^q
316 ChType 18, <LOW (NOT (fFCB+fChk))> ; ^r
317 ChType 19, <LOW (NOT (fFCB+fChk))> ; ^s
318 ChType 20, <LOW (NOT (fFCB+fChk))> ; ^t
319 ChType 21, <LOW (NOT (fFCB+fChk))> ; ^u
320 ChType 22, <LOW (NOT (fFCB+fChk))> ; ^v
321 ChType 23, <LOW (NOT (fFCB+fChk))> ; ^w
322 ChType 24, <LOW (NOT (fFCB+fChk))> ; ^x
323 ChType 25, <LOW (NOT (fFCB+fChk))> ; ^y
324 ChType 26, <LOW (NOT (fFCB+fChk))> ; ^z
325 ChType 27, <LOW (NOT (fFCB+fChk))> ; ^[
326 ChType 28, <LOW (NOT (fFCB+fChk))> ; ^\
327 ChType 29, <LOW (NOT (fFCB+fChk))> ; ^]
328 ChType 30, <LOW (NOT (fFCB+fChk))> ; ^^
329 ChType 31, <LOW (NOT (fFCB+fChk))> ; ^_
330 ChType " ", <LOW (NOT ( fChk+fDelim+fSpChk))>
331 ChType 255, -1
332FCB001E label byte
333Table ENDS
334ENDIF
335;
336; Get a byte from [SI], convert it to upper case, and compare for delimiter.
337; ZF set if a delimiter, CY set if a control character (other than TAB).
338;
339; DOS 3.3 modification for file char upper case. F.C. 5/29/86
340 procedure GetLet,NEAR
341 LODSB
342 entry GetLet2 ;AN000;; called by uCase
343 PUSH BX
344 MOV BX,OFFSET DOSGROUP:FILE_UCASE_TAB+2
345 getget:
346 CMP AL,"a"
347 JB CHK1
348 CMP AL,"z"
349 JA CHK1
350 SUB AL,20H ; Convert to upper case
351CHK1:
352 CMP AL,80H ; DOS 3.3
353 JB GOTIT ; DOS 3.3
354 SUB AL,80H ;translate to upper case with this index
355;
356 XLAT BYTE PTR CS:[BX]
357If TableLook
358GOTIT:
359 PUSH AX
360 MOV BX,OFFSET DOSGROUP:CharType
361 XLAT BYTE PTR CS:[BX]
362
363 TEST AL,fChk
364 POP AX
365 POP BX
366 RET
367 entry GetLet3 ;AN000; called by uCase
368 PUSH BX ;AN000;
369 JMP getget ;AN000;
370
371ELSE
372GOTIT:
373 POP BX
374 CMP AL,"."
375 retz
376 CMP AL,'"'
377 retz
378 CALL PATHCHRCMP
379 retz
380 CMP AL,"["
381 retz
382 CMP AL,"]"
383 retz
384ENDIF
385
386entry DELIM
387
388IF TableLook
389 PUSH AX
390 PUSH BX
391 MOV BX,OFFSET DOSGroup:CharType
392 XLAT BYTE PTR CS:[BX]
393 TEST AL,fDelim
394 POP BX
395 POP AX
396 RET
397ELSE
398 CMP AL,":"
399 retz
400
401 CMP AL,"<"
402 retz
403 CMP AL,"|"
404 retz
405 CMP AL,">"
406 retz
407
408 CMP AL,"+"
409 retz
410 CMP AL,"="
411 retz
412 CMP AL,";"
413 retz
414 CMP AL,","
415 retz
416ENDIF
417entry SPCHK
418IF TableLook
419 PUSH AX
420 PUSH BX
421 MOV BX,OFFSET DOSGroup:CharType
422 XLAT BYTE PTR CS:[BX]
423 TEST AL,fSpChk
424 POP BX
425 POP AX
426 RET
427ELSE
428 CMP AL,9 ; Filter out tabs too
429 retz
430; WARNING! " " MUST be the last compare
431 CMP AL," "
432 return
433ENDIF
434EndProc GetLet
435
436Procedure PATHCHRCMP,NEAR
437 CMP AL,'/'
438 JBE PathRet
439 CMP AL,'\'
440 return
441GotFor:
442 MOV AL,'\'
443 return
444PathRet:
445 JZ GotFor
446 return
447EndProc PathChrCMP
448
449
450 IF DBCS
451;--------------------- 2/12/KK
452; Function: Check if an input byte is in the ranges of DBCS vectors.
453;
454; Input: AL ; Code to be examined
455;
456; Output: ZF = 1 : AL is SBCS ZF = 0 : AL is a DBCS leading byte
457;
458; Register: All registers are unchanged except FL
459;
460procedure TESTKANJ,NEAR ;AN000;
461 call Chk_DBCS ;AN000;
462 jc TK_DBCS ;AN000;
463 cmp AL,AL ; set ZF ;AN000;
464 return ;AN000;
465TK_DBCS:
466 PUSH AX ;AN000;
467 XOR AX,AX ;Set ZF ;AN000;
468 INC AX ;Reset ZF ;AN000;
469 POP AX ;AN000;
470 return ;AN000;
471EndProc TESTKANJ ;AN000;
472;
473Chk_DBCS PROC ;AN000;
474 PUSH DS ;AN000;
475 PUSH SI ;AN000;
476 PUSH BX ;AN000;
477 Context DS ;AN000;
478 MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccSetDBCS ;AN000;
479 LDS SI,[BX+1] ; set EV address to DS:SI ;AN000;
480 ADD SI,2 ; Skip length ;AN000;
481DBCS_LOOP:
482 CMP WORD PTR [SI],0 ; terminator ? ;AN000;
483 JE NON_DBCS ; if yes, no DBCS ;AN000;
484 CMP AL,[SI] ; else ;AN000;
485 JB DBCS01 ; check if AL is ;AN000;
486 CMP AL,[SI+1] ; in a range of Ev ;AN000;
487 JA DBCS01 ; if yes, DBCS ;AN000;
488 STC ; else ;AN000;
489 JMP DBCS_EXIT ; try next DBCS Ev ;AN000;
490DBCS01:
491 ADD SI,2 ;AN000;
492 JMP DBCS_LOOP ;AN000;
493NON_DBCS:
494 CLC ;AN000;
495DBCS_EXIT:
496 POP BX ;AN000;
497 POP SI ;AN000;
498 POP DS ;AN000;
499 RET ;AN000;
500Chk_DBCS ENDP ;AN000;
501 ENDIF ;AN000;
502CODE ENDS
503 END
504 ;AN000;
diff --git a/v4.0/src/DOS/FCBIO.ASM b/v4.0/src/DOS/FCBIO.ASM
new file mode 100644
index 0000000..8b27d72
--- /dev/null
+++ b/v4.0/src/DOS/FCBIO.ASM
@@ -0,0 +1,1185 @@
1; SCCSID = @(#)fcbio.asm 1.5 85/07/30
2; SCCSID = @(#)fcbio.asm 1.5 85/07/30
3TITLE FCBIO - FCB system calls
4NAME FCBIO
5
6;
7; Ancient 1.0 1.1 FCB system calls
8; regen save
9; $GET_FCB_POSITION written none none
10; $FCB_DELETE written none none
11; $GET_FCB_FILE_LENGTH written none none
12; $FCB_CLOSE written close none
13; $FCB_RENAME written none none
14; SaveFCBInfo
15; ResetLRU
16; SetOpenAge
17; LRUFCB
18; FCBRegen
19; BlastSFT
20; CheckFCB
21; SFTFromFCB
22; FCBHardErr
23;
24; Revision history:
25;
26; Created: ARR 4 April 1983
27; MZ 6 June 1983 completion of functions
28; MZ 15 Dec 1983 Brain damaged programs close FCBs multiple
29; times. Change so successive closes work by
30; always returning OK. Also, detect I/O to
31; already closed FCB and return EOF.
32; MZ 16 Jan 1984 More braindamage. Need to separate info
33; out of sft into FCB for reconnection
34;
35; A000 version 4.00 Jan. 1988
36;
37.xlist
38;
39; get the appropriate segment definitions
40;
41include dosseg.asm
42
43CODE SEGMENT BYTE PUBLIC 'CODE'
44 ASSUME SS:DOSGROUP,CS:DOSGROUP
45
46.xcref
47INCLUDE DOSSYM.INC
48INCLUDE DEVSYM.INC
49INCLUDE FASTOPEN.INC
50.cref
51.list
52
53 AsmVars <Kanji>
54
55 I_need OpenBuf,128 ; buffer for translating paths
56 I_need RenBuf,128 ; buffer for rename paths
57 i_need THISDPB,DWORD
58 i_need EXTERR,WORD
59 i_need ALLOWED,BYTE
60 I_need ThisSFT,DWORD ; SFT in use
61 I_need WFP_start,WORD ; pointer to canonical name
62 I_need Ren_WFP,WORD ; pointer to canonical name
63 I_need Attrib,BYTE ; Attribute for match attributes
64 I_need sftFCB,DWORD ; pointer to SFTs for FCB cache
65 I_need FCBLRU,WORD ; least recently used count
66 I_need Proc_ID,WORD ; current process ID
67 I_Need Name1,14 ; place for device names
68 I_need DEVPT,DWORD ; device pointer
69 I_need OpenLRU,WORD ; open age
70 I_need KeepCount,WORD ; number of fcbs to keep
71 I_need User_In_AX,WORD ; user input system call.
72 I_need JShare,DWORD ; share jump table
73 I_need FastOpenTable,BYTE ; DOS 3.3 fastopen
74if debug
75 I_need BugLev,WORD
76 I_need BugTyp,WORD
77 include bugtyp.asm
78endif
79
80
81Break <$Get_FCB_Position - set random record fields to current pos>
82
83;
84; $Get_FCB_Position - look at an FCB, retrieve the current position from the
85; extent and next record field and set the random record field to point
86; to that record
87;
88; Inputs: DS:DX point to a possible extended FCB
89; Outputs: The random record field of the FCB is set to the current record
90; Registers modified: all
91
92Procedure $Get_FCB_Position,NEAR
93 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
94 invoke GetExtended ; point to FCB
95 invoke GetExtent ; DX:AX is current record
96 MOV WORD PTR [SI.fcb_RR],AX ; drop in low order piece
97 MOV [SI+fcb_RR+2],DL ; drop in high order piece
98 CMP [SI.fcb_RECSIZ],64
99 JAE GetFCBBye
100 MOV [SI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64
101GetFCBBye:
102 transfer FCB_Ret_OK
103EndProc $GET_FCB_POSITION
104
105Break <$FCB_Delete - remove several files that match the input FCB>
106
107;
108; $FCB_delete - given an FCB, remove all directory entries in the current
109; directory that have names that match the FCB's ? marks.
110;
111; Inputs: DS:DX - point to an FCB
112; Outputs: directory entries matching the FCB are deleted
113; AL = FF if no entries were deleted.
114; Registers modified: all
115
116Procedure $FCB_Delete,NEAR
117 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
118 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate place
119 invoke TransFCB ; convert FCB to path
120 JC BadPath ; signal no deletions
121 Context DS
122 invoke DOS_Delete ; wham
123 JC BadPath
124GoodPath:
125 transfer FCB_Ret_OK ; do a good return
126BadPath:
127;
128
129; Error code is in AX
130;
131 transfer FCB_Ret_Err ; let someone else signal the error
132EndProc $FCB_DELETE
133
134Break <$Get_FCB_File_Length - return the length of a file>
135
136;
137; $Get_FCB_File_Length - set the random record field to the length of the
138; file in records (rounded up if partial).
139;
140; Inputs: DS:DX - point to a possible extended FCB
141; Outputs: Random record field updated to reflect the number of records
142; Registers modified: all
143
144Procedure $Get_FCB_File_Length,NEAR
145 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
146 invoke GetExtended ; get real FCB pointer
147 ; DX points to Input FCB
148 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
149 SaveReg <DS,SI> ; save pointer to true FCB
150 Invoke TransFCB ; Trans name DS:DX, sets SATTRIB
151 RestoreReg <SI,DS>
152 JC BadPath
153 SaveReg <DS,SI> ; save pointer
154 Context DS
155 invoke Get_File_Info ; grab the info
156 RestoreReg <SI,DS> ; get pointer back
157 JC BadPath ; invalid something
158 MOV DX,BX ; get high order size
159 MOV AX,DI ; get low order size
160 MOV BX,[SI.fcb_RECSIZ] ; get his record size
161 OR BX,BX ; empty record => 0 size for file
162 JNZ GetSize ; not empty
163 MOV BX,128
164GetSize:
165 MOV DI,AX ; save low order word
166 MOV AX,DX ; move high order for divide
167 XOR DX,DX ; clear out high
168 DIV BX ; wham
169 PUSH AX ; save dividend
170 MOV AX,DI ; get low order piece
171 DIV BX ; wham
172 MOV CX,DX ; save remainder
173 POP DX ; get high order dividend
174 JCXZ LengthStore ; no roundup
175 ADD AX,1
176 ADC DX,0 ; 32-bit increment
177LengthStore:
178 MOV WORD PTR [SI.FCB_RR],AX ; store low order
179 MOV [SI.FCB_RR+2],DL ; store high order
180 OR DH,DH
181 JZ GoodPath ; not storing insignificant zero
182 MOV [SI.FCB_RR+3],DH ; save that high piece
183GoodRet:
184 transfer FCB_Ret_OK
185EndProc $GET_FCB_FILE_LENGTH
186
187Break <$FCB_Close - close a file>
188
189;
190; $FCB_Close - given an FCB, look up the SFN and close it. Do not free it
191; as the FCB may be used for further I/O
192;
193; Inputs: DS:DX point to FCB
194; Outputs: AL = FF if file was not found on disk
195; Registers modified: all
196
197Procedure $FCB_Close,NEAR
198 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
199 XOR AL,AL ; default search attributes
200 invoke GetExtended ; DS:SI point to real FCB
201 JZ NoAttr ; not extended
202 MOV AL,[SI-1] ; get attributes
203NoAttr:
204 MOV [Attrib],AL ; stash away found attributes
205 invoke SFTFromFCB
206 JC GoodRet ; MZ 16 Jan Assume death
207;
208; If the sharer is present, then the SFT is not regenable. Thus, there is
209; no need to set the SFT's attribute.
210;
211;;; 9/8/86 F.C. save SFT attribute and restore it back when close is done
212 MOV AL,ES:[DI].sf_attr
213 XOR AH,AH
214 PUSH AX
215;;; 9/8/86 F.C. save SFT attribute and restore it back when close is done
216 invoke CheckShare
217 JNZ NoStash
218 MOV AL,Attrib
219 MOV ES:[DI].sf_attr,AL ; attempted attribute for close
220NoStash:
221 MOV AX,[SI].FCB_FDATE ; move in the time and date
222 MOV ES:[DI].sf_date,AX
223 MOV AX,[SI].FCB_FTIME
224 MOV ES:[DI].sf_time,AX
225 MOV AX,[SI].FCB_FilSiz
226 MOV WORD PTR ES:[DI].sf_size,AX
227 MOV AX,[SI].FCB_FilSiz+2
228 MOV WORD PTR ES:[DI].sf_size+2,AX
229 OR ES:[DI].sf_Flags,sf_close_nodate
230 Context DS ; let Close see variables
231 invoke DOS_Close ; wham
232 LES DI,ThisSFT
233;;; 9/8/86 F.C. restore SFT attribute
234 POP CX
235 MOV ES:[DI].sf_attr,CL
236;;; 9/8/86 F.C. restore SFT attribute
237 PUSHF
238 TEST ES:[DI.sf_ref_count],-1 ; zero ref count gets blasted
239 JNZ CloseOK
240 PUSH AX
241 MOV AL,'M'
242 invoke BlastSFT
243 POP AX
244CloseOK:
245 POPF
246 JNC GoodRet
247 CMP AL,error_invalid_handle
248 JZ GoodRet
249 MOV AL,error_file_not_found
250 transfer FCB_Ret_Err
251EndProc $FCB_CLOSE
252
253Break <$FCB_Rename - change names in place>
254
255;
256; $FCB_Rename - rename a file in place within a directory. Renames multiple
257; files copying from the meta characters.
258;
259; Inputs: DS:DX point to an FCB. The normal name field is the source
260; name of the files to be renamed. Starting at offset 11h
261; in the FCB is the destination name.
262; Outputs: AL = 0 -> no error occurred and all files were renamed
263; AL = FF -> some files may have been renamed but:
264; rename to existing file or source file not found
265; Registers modified: all
266
267Procedure $FCB_Rename,NEAR
268 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
269 invoke GetExtended ; get pointer to real FCB
270 SaveReg <DX>
271 MOV AL,[SI] ; get drive byte
272 ADD SI,10h ; point to destination
273 MOV DI,OFFSET DOSGroup:RenBuf ; point to destination buffer
274 SaveReg <<WORD PTR DS:[SI]>,DS,SI> ; save source pointer for TransFCB
275 MOV DS:[SI],AL ; drop in real drive
276 MOV DX,SI ; let TransFCB know where the FCB is
277 invoke TransFCB ; munch this pathname
278 RestoreReg <SI,DS,<WORD PTR DS:[SI]>> ; get path back
279 RestoreReg <DX> ; Original FCB pointer
280 JC BadRen ; bad path -> error
281 MOV SI,WFP_Start ; get pointer
282 MOV Ren_WFP,SI ; stash it
283 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate spot
284 invoke TransFCB ; wham
285 ; NOTE that this call is pointing
286 ; back to the ORIGINAL FCB so
287 ; SATTRIB gets set correctly
288 JC BadRen ; error
289 invoke DOS_Rename
290 JC BadRen
291 transfer FCB_Ret_OK
292BadRen:
293;
294; AL has error code
295;
296 transfer FCB_Ret_Err
297
298EndProc $FCB_RENAME
299
300Break <Misbehavior fixers>
301
302;
303; FCBs suffer from several problems. First, they are maintained in the
304; user's space so he may move them at will. Second, they have a small
305; reserved area that may be used for system information. Third, there was
306; never any "rules for behavior" for FCBs; there was no protocol for their
307; usage.
308;
309; This results in the following misbehavior:
310;
311; infinite opens of the same file:
312;
313; While (TRUE) { While (TRUE) {
314; FCBOpen (FCB); FCBOpen (FCB);
315; Read (FCB); Write (FCB);
316; } }
317;
318; infinite opens of different files:
319;
320; While (TRUE) { While (TRUE) {
321; FCBOpen (FCB[i++]); FCBOpen (FCB[i++]);
322; Read (FCB); Write (FCB);
323; } }
324;
325; multiple closes of the same file:
326;
327; FCBOpen (FCB);
328; while (TRUE)
329; FCBClose (FCB);
330;
331; I/O after closing file:
332;
333; FCBOpen (FCB);
334; while (TRUE) {
335; FCBWrite (FCB);
336; FCBClose (FCB);
337; }
338;
339; The following is am implementation of a methodology for emulating the
340; above with the exception of I/O after close. We are NOT attempting to
341; resolve that particular misbehavior. We will enforce correct behaviour in
342; FCBs when they refer to a network file or when there is file sharing on
343; the local machine.
344;
345; The reserved fields of the FCB (10 bytes worth) is divided up into various
346; structures depending on the file itself and the state of operations of the
347; OS. The information contained in this reserved field is enough to
348; regenerate the SFT for the local non-shared file. It is assumed that this
349; regeneration procedure may be expensive. The SFT for the FCB is
350; maintained in a LRU cache as the ONLY performance inprovement.
351;
352; No regeneration of SFTs is attempted for network FCBs.
353;
354; To regenerate the SFT for a local FCB, it is necessary to determine if the
355; file sharer is working. If the file sharer is present then the SFT is not
356; regenerated.
357;
358; Finally, if there is no local sharing, the full name of the file is no
359; longer available. We can make up for this by using the following
360; information:
361;
362; The Drive number (from the DPB).
363; The physical sector of the directory that contains the entry.
364; The relative position of the entry in the sector.
365; The first cluster field.
366; The last used SFT.
367; OR In the case of a device FCB
368; The low 6 bits of sf_flags (indicating device type)
369; The pointer to the device header
370;
371;
372; We read in the particular directory sector and examine the indicated
373; directory entry. If it matches, then we are kosher; otherwise, we fail.
374;
375; Some key items need to be remembered:
376;
377; Even though we are caching SFTs, they may contain useful sharing
378; information. We enforce good behavior on the FCBs.
379;
380; Network support must not treat FCBs as impacting the ref counts on
381; open VCs. The VCs may be closed only at process termination.
382;
383; If this is not an installed version of the DOS, file sharing will
384; always be present.
385;
386; We MUST always initialize lstclus to = firclus when regenerating a
387; file. Otherwise we start allocating clusters up the wazoo.
388;
389; Always initialize, during regeneration, the mode field to both isFCB
390; and open_for_both. This is so the FCB code in the sharer can find the
391; proper OI record.
392;
393; The test bits are:
394;
395; 00 -> local file
396; 40 -> sharing local
397; 80 -> network
398; C0 -> local device
399
400Break <SaveFCBInfo - store pertinent information from an SFT into the FCB>
401
402;
403; SaveFCBInfo - given an FCB and its associated SFT, copy the relevant
404; pieces of information into the FCB to allow for subsequent
405; regeneration. Poke LRU also.
406;
407; Inputs: ThisSFT points to a complete SFT.
408; DS:SI point to the FCB (not an extended one)
409; Outputs: The relevant reserved fields in the FCB are filled in.
410; DS:SI preserved
411; ES:DI point to sft
412; Registers modified: All
413;
414
415Procedure SaveFCBInfo,NEAR
416 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
417 LES DI,ThisSFT
418 Assert ISSFT,<ES,DI>,"SaveFCBInfo"
419 invoke IsSFTNet
420 JZ SaveLocal ; if not network then save local info
421;
422;----- In net support -----
423;
424 MOV AX,WORD PTR ES:[DI].sf_serial_ID ;AN000;;IFS. save IFS ID
425 MOV WORD PTR [SI].FCB_netID,ax ;AN000;;IFS.
426; SaveReg <ES,DI>
427; LES DI,DWORD PTR ES:[DI].sf_netid
428; MOV WORD PTR [SI].FCB_netID,DI ; save net ID
429; MOV WORD PTR [SI].FCB_netID+2,ES
430; RestoreReg <DI,ES>
431 MOV BL,FCBNETWORK
432;
433;----- END In net support -----
434;
435IF debug
436 JMP SaveSFN
437ELSE
438 JMP SHORT SaveSFN
439ENDIF
440SaveLocal:
441 IF Installed
442 Invoke CheckShare
443 JZ SaveNoShare ; no sharer
444 JMP SaveShare ; sharer present
445
446SaveNoShare:
447 TEST ES:[DI].sf_flags,devid_device
448 JNZ SaveNoShareDev ; Device
449;
450; Save no sharing local file information
451;
452 MOV AX,WORD PTR ES:[DI].sf_dirsec ; get directory sector F.C.
453 MOV [SI].fcb_nsl_dirsec,AX
454 MOV AL,ES:[DI].sf_dirpos ; location in sector
455 MOV [SI].fcb_nsl_dirpos,AL
456 MOV AX,ES:[DI].sf_firclus ; first cluster
457 MOV [SI].fcb_nsl_firclus,AX
458 MOV BL,00
459;
460; Create the bits field from the dirty/device bits of the flags word and the
461; mode byte
462;
463SetFCBBits:
464 MOV AX,ES:[DI].sf_flags
465 AND AL,0C0h ; mask off drive bits
466 OR AL,BYTE PTR ES:[DI].sf_mode ; stick in open mode
467 MOV [SI].fcb_nsl_bits,AL ; save dirty info
468 JMP SaveSFN ; go and save SFN
469
470;
471; Save no sharing local device information
472;
473SaveNoShareDev:
474 MOV AX,WORD PTR ES:[DI].sf_devptr
475 MOV WORD PTR [SI].FCB_nsld_drvptr,AX
476 MOV AX,WORD PTR ES:[DI].sf_devptr + 2
477 MOV WORD PTR [SI].FCB_nsld_drvptr + 2,AX
478 MOV BL,FCBDEVICE
479 JMP SetFCBBits ; go and save SFN
480
481SaveShare:
482 ENDIF
483;
484;----- In share support -----
485;
486if installed
487 Call JShare + 10 * 4
488else
489 Call ShSave
490endif
491;
492;----- end in share support -----
493;
494SaveSFN:
495 MOV AX,ES:[DI].sf_flags
496 AND AL,3Fh ; get real drive
497 OR AL,BL
498 MOV [SI].fcb_l_drive,AL
499 LEA AX,[DI-SFTable]
500;
501; Adjust for offset to table.
502;
503 SUB AX,WORD PTR SftFCB
504 MOV BL,SIZE sf_entry
505 DIV BL
506 MOV [SI].FCB_sfn,AL ; last used SFN
507 MOV AX,FCBLRU ; get lru count
508 INC AX
509 MOV WORD PTR ES:[DI].sf_LRU,AX
510 JNZ SimpleStuff
511;
512; lru flag overflowed. Run through all FCB sfts and adjust: LRU < 8000h
513; get set to 0. Others -= 8000h. This LRU = 8000h
514;
515 MOV BX,sf_position
516 invoke ResetLRU
517;
518; Set new LRU to AX
519;
520SimpleStuff:
521 MOV FCBLRU,AX
522 return
523EndProc SaveFCBInfo
524
525Break <ResetLRU - reset overflowed lru counts>
526
527;
528; ResetLRU - during lru updates, we may wrap at 64K. We must walk the
529; entire set of SFTs and subtract 8000h from their lru counts and truncate
530; at 0.
531;
532; Inputs: BX is offset into SFT field where lru firld is kept
533; ES:DI point to SFT currently being updated
534; Outputs: All FCB SFTs have their lru fields truncated
535; AX has 8000h
536; Registers modified: none
537
538Procedure ResetLRU,NEAR
539 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
540 Assert ISSFT,<ES,DI>,"ResetLRU"
541 MOV AX,8000h
542 SaveReg <ES,DI>
543 LES DI,sftFCB ; get pointer to head
544 MOV CX,ES:[DI].sfCount
545 LEA DI,[DI].sfTable ; point at table
546ovScan:
547 SUB WORD PTR ES:[DI+BX],AX ; decrement lru count
548 JA ovLoop
549 MOV WORD PTR ES:[DI.BX],AX ; truncate at 0
550ovLoop:
551 ADD DI,SIZE SF_Entry ; advance to next
552 LOOP ovScan
553 RestoreReg <DI,ES>
554 MOV ES:[DI+BX],AX
555 return
556EndProc ResetLRU
557
558Break <SetOpenAge - update the open age of a SFT>
559
560;
561; SetOpenAge - In order to maintain the first N open files in the FCB cache,
562; we keep the 'open age' or an LRU count based on opens. We update the
563; count here and fill in the appropriate field.
564;
565; Inputs: ES:DI point to SFT
566; Outputs: ES:DI has the open age field filled in.
567; If open age has wraparound, we will have subtracted 8000h
568; from all open ages.
569; Registers modified: AX
570;
571
572Procedure SetOpenAge,NEAR
573 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
574 Assert ISSFT,<ES,DI>,"SetOpenAge"
575 MOV AX,OpenLRU
576 INC AX
577 MOV ES:[DI].sf_OpenAge,AX
578 JNZ SetDone
579 MOV BX,sf_Position+2
580 invoke ResetLRU
581SetDone:
582 MOV OpenLRU,AX
583 return
584EndProc SetOpenAge
585
586Break <LRUFCB - perform LRU on FCB sfts>
587
588;
589; LRUFCB - find LRU fcb in cache. Set ThisSFT and return it. We preserve
590; the first keepcount sfts if they are network sfts or if sharing is
591; loaded. If carry is set then NO BLASTING is NECESSARY.
592;
593; Inputs: none
594; Outputs: ES:DI point to SFT
595; ThisSFT points to SFT
596; SFT is zeroed
597; Carry set of closes failed
598; Registers modified: none
599;
600
601Procedure LRUFCB,NEAR
602 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
603 Invoke Save_World
604;
605; Find nth oldest NET/SHARE FCB. We want to find its age for the second scan
606; to find the lease recently used one that is younger than the open age. We
607; operate be scanning the list n times finding the least age that is greater
608; or equal to the previous minimum age.
609;
610; BP is the count of times we need to go through this loop.
611; AX is the current acceptable minimum age to consider
612;
613 mov bp,KeepCount ; k = keepcount;
614 XOR AX,AX ; low = 0;
615;
616; If we've scanned the table n times, then we are done.
617;
618lru1:
619 CMP bp,0 ; while (k--) {
620 JZ lru75
621 DEC bp
622;
623; Set up for scan.
624;
625; AX is the minimum age for consideration
626; BX is the minimum age found during the scan
627; SI is the position of the entry that corresponds to BX
628;
629 MOV BX,-1 ; min = 0xffff;
630 MOV si,BX ; pos = 0xffff;
631 LES DI,SFTFCB ; for (CX=FCBCount; CX>0; CX--)
632 MOV CX,ES:[DI].sfCount
633 LEA DI,[DI].sfTable
634;
635; Innermost loop. If the current entry is free, then we are done. Or, if the
636; current entry is busy (indicating a previous aborted allocation), then we
637; are done. In both cases, we use the found entry.
638;
639lru2:
640 cmp es:[di].sf_ref_count,0
641 jz lru25
642 cmp es:[di].sf_ref_count,sf_busy
643 jnz lru3
644;
645; The entry is usable without further scan. Go and use it.
646;
647lru25:
648 MOV si,DI ; pos = i;
649 JMP lru11 ; goto got;
650;
651; See if the entry is for the network or for the sharer.
652;
653; If for the sharer or network then
654; if the age < current minimum AND >= allowed minimum then
655; this entry becomes current minimum
656;
657lru3:
658 TEST ES:[DI].sf_flags,sf_isnet ; if (!net[i]
659 JNZ lru35
660if installed
661 Invoke CheckShare ; && !sharing)
662 JZ lru5 ; else
663ENDIF
664;
665; This SFT is for the net or is for the sharer. See if it less than the
666; current minimum.
667;
668lru35:
669 MOV DX,ES:[DI].sf_OpenAge
670 CMP DX,AX ; if (age[i] >= low &&
671 JB lru5
672 CMP DX,BX
673 JAE lru5 ; age[i] < min) {
674;
675; entry is new minimum. Remember his age.
676;
677 mov bx,DX ; min = age[i];
678 mov si,di ; pos = i;
679;
680; End of loop. gp back for more
681;
682lru5:
683add di,size sf_entry
684 loop lru2 ; }
685;
686; The scan is complete. If we have successfully found a new minimum (pos != -1)
687; set then threshold value to this new minimum + 1. Otherwise, the scan is
688; complete. Go find LRU.
689;
690lru6: cmp si,-1 ; position not -1?
691 jz lru75 ; no, done with everything
692 lea ax,[bx+1] ; set new threshold age
693 jmp lru1 ; go and loop for more
694lru65: stc
695 jmp short lruDead ; return -1;
696;
697; Main loop is done. We have AX being the age+1 of the nth oldest sharer or
698; network entry. We now make a second pass through to find the LRU entry
699; that is local-no-share or has age >= AX
700;
701lru75:
702 mov bx,-1 ; min = 0xffff;
703 mov si,bx ; pos = 0xffff;
704 LES DI,SFTFCB ; for (CX=FCBCount; CX>0; CX--)
705 MOV CX,ES:[DI].sfCount
706 LEA DI,[DI].sfTable
707;
708; If this is is local-no-share then go check for LRU else if age >= threshold
709; then check for lru.
710;
711lru8:
712 TEST ES:[DI].sf_flags,sf_isnet
713 jnz lru85 ; is for network, go check age
714 invoke CheckShare ; sharer here?
715 jz lru86 ; no, go check lru
716;
717; Network or sharer. Check age
718;
719lru85:
720 cmp es:[di].sf_OpenAge,ax
721 jb lru9 ; age is before threshold, skip it
722;
723; Check LRU
724;
725lru86:
726 cmp es:[di].sf_LRU,bx ; is LRU less than current LRU?
727 jae lru9 ; no, skip this
728 mov si,di ; remember position
729 mov bx,es:[di].sf_LRU ; remember new minimum LRU
730;
731; Done with this entry, go back for more.
732;
733lru9:
734 add di,size sf_entry
735 loop lru8
736;
737; Scan is complete. If we found NOTHING that satisfied us then we bomb
738; out. The conditions here are:
739;
740; No local-no-shares AND all net/share entries are older than threshold
741;
742lru10:
743 cmp si,-1 ; if no one f
744 jz lru65 ; return -1;
745lru11:
746 mov di,si
747 MOV WORD PTR ThisSFT,DI ; set thissft
748 MOV WORD PTR ThisSFT+2,ES
749;
750; If we have sharing or thisSFT is a net sft, then close it until ref count
751; is 0.
752;
753 TEST ES:[DI].sf_flags,sf_isNet
754 JNZ LRUClose
755IF INSTALLED
756 Invoke CheckShare
757 JZ LRUDone
758ENDIF
759;
760; Repeat close until ref count is 0
761;
762LRUClose:
763 Context DS
764 LES DI,ThisSFT
765 CMP ES:[DI].sf_ref_count,0 ; is ref count still <> 0?
766 JZ LRUDone ; nope, all done
767
768; Message 1,"LRUFCB: closing "
769; MessageNum <WORD PTR THISSFT+2>
770; Message 1,":"
771; MessageNum <WORD PTR THISSFT>
772
773 Invoke DOS_Close
774 jnc LRUClose ; no error => clean up
775 cmp al,error_invalid_handle
776 jz LRUClose
777 stc
778 JMP short LRUDead
779LRUDone:
780 XOR AL,AL
781 invoke BlastSFT ; fill SFT with 0 (AL)
782LRUDead:
783 Invoke Restore_World
784 ASSUME DS:NOTHING
785 LES DI,ThisSFT
786 Assert ISSFT,<ES,DI>,"LRUFCB return"
787 retnc
788 MOV AL,error_FCB_unavailable
789 return
790EndProc LRUFCB
791
792Break <FCBRegen - regenerate a sft from the info in the FCB>
793
794;
795; FCBRegen - examine reserved field of FCB and attempt to generate the SFT
796; from it.
797;
798; Inputs: DS:SI point to FCB
799; Outputs: carry clear Filled in SFT
800; Carry set unrecoverable error
801; Registers modified: all
802
803Procedure FCBRegen,NEAR
804 ASSUME DS:NOTHING,ES:NOTHING
805;
806; General data filling. Mode is sf_isFCB + open_for_both, date/time we do
807; not fill, size we do no fill, position we do not fill,
808; bit 14 of flags = TRUE, other bits = FALSE
809;
810 MOV AL,[SI].fcb_l_drive
811;
812; We discriminate based on the first two bits in the reserved field.
813;
814 TEST AL,FCBSPECIAL ; check for no sharing test
815 JZ RegenNoSharing ; yes, go regen from no sharing
816;
817; The FCB is for a network or a sharing based system. At this point we have
818; already closed the SFT for this guy and reconnection is impossible.
819;
820; Remember that he may have given us a FCB with bogus information in it.
821; Check to see if sharing is present or if the redir is present. If either is
822; around, presume that we have cycled out the FCB and give the hard error.
823; Otherwise, just return with carry set.
824;
825 invoke CheckShare ; test for sharer
826 JNZ RegenFail ; yep, fail this.
827 MOV AX,multNet SHL 8 ; install check on multnet
828 INT 2FH
829 OR AL,AL ; is it there?
830 JZ RegenDead ; no, just fail the operation
831RegenFail:
832 MOV AX,User_In_AX
833 cmp AH,fcb_close
834 jz RegenDead
835 invoke FCBHardErr ; massive hard error.
836RegenDead:
837 STC
838 return ; carry set
839;
840; Local FCB without sharing. Check to see if sharing is loaded. If so
841; fail the operation.
842;
843RegenNoSharing:
844 invoke CheckShare ; Sharing around?
845 JNZ RegenFail
846;
847; Find an SFT for this guy.
848;
849 invoke LRUFcb
850 retc
851 MOV ES:[DI].sf_mode,SF_IsFCB + open_for_both + sharing_compat
852 AND AL,3Fh ; get drive number for flags
853 CBW
854 OR AX,sf_close_noDate ; normal FCB operation
855;
856; The bits field consists of the upper two bits (dirty and device) from the
857; SFT and the low 4 bits from the open mode.
858;
859 MOV CL,[SI].FCB_nsl_bits ; stick in dirty bits.
860 MOV CH,CL
861 AND CH,0C0h ; mask off the dirty/device bits
862 OR AL,CH
863 AND CL,access_mask ; get the mode bits
864 MOV BYTE PTR ES:[DI].sf_mode,CL
865 MOV ES:[DI].sf_flags,AX ; initial flags
866 MOV AX,Proc_ID
867 MOV ES:[DI].sf_PID,AX
868 SaveReg <DS,SI,ES,DI>
869 Context ES
870 MOV DI,OFFSET DOSGroup:Name1
871 MOV CX,8
872 INC SI ; Skip past drive byte to name in FCB
873RegenCopyName2:
874 LODSB
875
876 IF DBCS ;AN000;
877 invoke testkanj ;AN000;
878 jz notkanj9 ;AN000;
879 STOSB ;AN000;
880 DEC CX ;AN000;
881 JCXZ DoneNam2 ;AN000; ; Ignore split kanji char error
882 LODSB ;AN000;
883 jmp short StuffChar2 ;AN000;
884 ;AN000;
885notkanj9: ;AN000;
886 ENDIF ;AN000;
887
888 Invoke UCase
889StuffChar2:
890 STOSB
891 LOOP RegenCopyName2
892DoneNam2:
893 Context DS
894 MOV [ATTRIB],attr_hidden + attr_system + attr_directory
895 ; Must set this to something interesting
896 ; to call DEVNAME.
897 Invoke DevName ; check for device
898 ASSUME DS:NOTHING,ES:NOTHING
899 RestoreReg <DI,ES,SI,DS>
900 JC RegenFileNoSharing ; not found on device list => file
901;
902; Device found. We can ignore disk-specific info
903;
904 MOV BYTE PTR ES:[DI].sf_flags,BH ; device parms
905 MOV ES:[DI].sf_attr,0 ; attribute
906 LDS SI,DEVPT ; get device driver
907 MOV WORD PTR ES:[DI].sf_devptr,SI
908 MOV WORD PTR ES:[DI].sf_devptr+2,DS
909 return ; carry is clear
910
911RegenDeadJ:
912 JMP RegenDead
913;
914; File found. Just copy in the remaining pieces.
915;
916RegenFileNoSharing:
917 MOV AX,ES:[DI].sf_flags
918 AND AX,03Fh
919 SaveReg <DS,SI>
920 Invoke Find_DPB
921 MOV WORD PTR ES:[DI].sf_devptr,SI
922 MOV WORD PTR ES:[DI].sf_devptr+2,DS
923 RestoreReg <SI,DS>
924 jc RegenDeadJ ; if find DPB fails, then drive
925 ; indicator was bogus
926 MOV AX,[SI].FCB_nsl_dirsec
927 MOV WORD PTR ES:[DI].sf_dirsec,AX
928 MOV WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;>32mb
929 MOV AX,[SI].FCB_nsl_firclus
930 MOV ES:[DI].sf_firclus,AX
931 MOV ES:[DI].sf_lstclus,AX
932 MOV AL,[SI].FCB_nsl_dirpos
933 MOV ES:[DI].sf_dirpos,AL
934 INC ES:[DI].sf_ref_count ; Increment reference count.
935 ; Existing FCB entries would be
936 ; flushed unnecessarily because of
937 ; check in CheckFCB of the ref_count.
938 ; July 22/85 - BAS
939 LEA SI,[SI].FCB_name
940 LEA DI,[DI].sf_name
941 MOV CX,fcb_extent-fcb_name
942RegenCopyName:
943 LODSB
944
945 IF DBCS ;AN000;
946 invoke testkanj
947 jz notkanj1
948 STOSB
949 DEC CX
950 JCXZ DoneNam ; Ignore split kanji char error
951 LODSB
952 jmp short StuffChar
953
954notkanj1:
955 ENDIF ;AN000;
956
957 Invoke UCase
958StuffChar:
959 STOSB
960 LOOP RegenCopyName
961DoneNam:
962 clc
963 return
964EndProc FCBRegen
965
966;
967; BlastSFT - fill SFT with garbage
968;
969; Inputs: ES:DI point to SFT
970; AL has fill
971; Outputs: SFT is filled with nonsense
972; *FLAGS PRESERVED*
973; Registers modified: CX
974
975Procedure BlastSFT,NEAR
976 SaveReg <DI>
977 MOV CX,SIZE sf_entry
978 REP STOSB
979 RestoreReg <DI>
980 MOV ES:[DI].sf_ref_count,0 ; set ref count
981 MOV ES:[DI].sf_LRU,0 ; set lru
982 MOV ES:[DI].sf_OpenAge,-1 ; Set open age
983 return
984EndProc BlastSFT
985
986Break <CheckFCB - see if the SFT pointed to by the FCB is still OK>
987
988; CheckFCB - examine an FCB and its contents to see if it needs to be
989; regenerated.
990;
991; Inputs: DS:SI point to FCB (not extended)
992; AL is SFT index
993; Outputs: Carry Set - FCB needs to be regened
994; Carry clear - FCB is OK. ES:DI point to SFT
995; Registers modified: AX and BX
996
997Procedure CheckFCB,NEAR
998 ASSUME DS:NOTHING,ES:NOTHING
999 LES DI,sftFCB
1000 CMP BYTE PTR ES:[DI].SFCount,AL
1001 JC BadSFT
1002 MOV BL,SIZE sf_entry
1003 MUL BL
1004 LEA DI,[DI].sftable
1005 ADD DI,AX
1006 MOV AX,Proc_ID
1007 CMP ES:[DI].sf_PID,AX
1008 JNZ BadSFT ; must match process
1009 CMP ES:[DI].sf_ref_count,0
1010 JZ BadSFT ; must also be in use
1011 MOV AL,[SI].FCB_l_Drive
1012 TEST AL,FCBSPECIAL ; a special FCB?
1013 JZ CheckNoShare ; No. try local or device
1014;
1015; Since we are a special FCB, try NOT to use a bogus test instruction.
1016; FCBSHARE is a superset of FCBNETWORK.
1017;
1018 PUSH AX
1019 AND AL,FCBMASK
1020 CMP AL,FCBSHARE ; net FCB?
1021 POP AX
1022 JNZ CheckNet ; yes
1023;
1024;----- In share support -----
1025;
1026if installed
1027 Call JShare + 11 * 4
1028else
1029 Call ShChk
1030endif
1031 JC BadSFT
1032 JMP SHORT CheckD
1033;
1034;----- End in share support -----
1035;
1036CheckFirClus:
1037 CMP BX,ES:[DI].sf_firclus
1038 JNZ BadSFT
1039CheckD: AND AL,3Fh
1040 MOV AH,BYTE PTR ES:[DI].sf_flags
1041 AND AH,3Fh
1042 CMP AH,AL
1043 retz ; carry is clear
1044BadSFT: STC
1045 return ; carry is clear
1046CheckNet:
1047;
1048;----- In net support -----
1049;
1050; MOV AX,[SI].FCB_net_handle
1051; CMP AX,WORD PTR ES:[DI].sf_NETID+4
1052; JNZ BadSFT
1053; MOV AX,WORD PTR [SI].FCB_netID
1054; CMP AX,WORD PTR ES:[DI].sf_netid
1055; JNZ BadSFT
1056 MOV AX,WORD PTR [SI].FCB_netID ;AN000;IFS.DOS 4.00
1057 CMP AX,WORD PTR ES:[DI].sf_serial_ID ;AN000;IFS.DOS 4.00
1058 JNZ BadSFT
1059;
1060;----- END In net support -----
1061;
1062 return
1063
1064CheckNoShare:
1065 TEST AL,FCBDEVICE ; Device?
1066 JNZ CheckNoShareDev ; Yes
1067;
1068; Check no sharing local file
1069;
1070 MOV BX,[SI].FCB_nsl_Dirsec
1071 CMP WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;F.C. >32mb
1072 JNZ BadSFt ;AN000;F.C. >32mb
1073
1074 CMP BX,WORD PTR ES:[DI].sf_dirsec ;AN000;F.C. >32mb
1075 JNZ BadSFT
1076 MOV BL,[SI].FCB_nsl_Dirpos
1077 CMP BL,ES:[DI].sf_dirpos
1078 JNZ BadSFt
1079;
1080; Since the bits field comes from two different spots, compare them separately.
1081;
1082 MOV BL,[SI].FCB_nsl_bits
1083 MOV BH,BYTE PTR ES:[DI].sf_flags
1084 XOR BH,BL
1085 AND BH,0C0h
1086 JNZ BadSFT ; dirty/device bits are different
1087 XOR BL,BYTE PTR ES:[DI].sf_mode
1088 AND BL,access_mask
1089 JNZ BadSFT ; access modes are different
1090; Make sure that the names are the same in the FCB and the SFT
1091; This case can appear under the following scenario:
1092; Create FOO
1093; Rename FOO -> BAR
1094; Open BAR
1095; The SFT will still contain the name for the old file name.
1096; July 30/85 - BAS
1097 PUSH DI
1098 PUSH SI
1099 LEA DI,[DI].sf_name
1100 LEA SI,[SI].fcb_name
1101 MOV CX,11
1102 REPE CMPSB
1103 POP SI
1104 POP DI
1105 JNZ BadSFT
1106 MOV BX,[SI].FCB_nsl_firclus
1107 JMP CheckFirClus
1108
1109CheckNoShareDev:
1110 MOV BX,WORD PTR [SI].FCB_nsld_drvptr
1111 CMP BX,WORD PTR ES:[DI].sf_devptr
1112 JNZ BadSFT
1113 MOV BX,WORD PTR [SI].FCB_nsld_drvptr + 2
1114 CMP BX,WORD PTR ES:[DI].sf_devptr + 2
1115 JNZ BadSFT
1116 JMP CheckD
1117
1118EndProc CheckFCB
1119
1120Break <SFTFromFCB - take a FCB and obtain a SFT from it>
1121
1122;
1123; SFTFromFCB - the workhorse of this compatability crap. Check to see if
1124; the SFT for the FCB is Good. If so, make ThisSFT point to it. If not
1125; good, get one from the cache and regenerate it. Overlay the LRU field
1126; with PID
1127;
1128; Inputs: DS:SI point to FCB
1129; Outputs: ThisSFT point to appropriate SFT
1130; Carry clear -> OK ES:DI -> SFT
1131; Carry set -> error in ax
1132; Registers modified: ES,DI, AX
1133
1134Procedure SFTFromFCB,NEAR
1135 ASSUME DS:NOTHING,ES:NOTHING
1136 SaveReg <AX,BX>
1137 MOV AL,[SI].fcb_sfn ; set SFN for check
1138 invoke CheckFCB
1139 RestoreReg <BX,AX>
1140 MOV WORD PTR ThisSFT,DI ; set thissft
1141 MOV WORD PTR ThisSFT+2,ES
1142 JNC SetSFT ; no problems, just set thissft
1143
1144 fmt typFCB,LevCheck,<"FCB $x:$x does not match SFT $x:$x\n">,<DS,SI,ES,DI>
1145
1146 Invoke Save_World
1147 invoke FCBRegen
1148 Invoke Restore_World ; restore world
1149 MOV AX,EXTERR
1150 retc
1151
1152; Message 1,<"FCBRegen Succeeded",13,10>
1153
1154SetSFT: LES DI,ThisSFT
1155 PUSH Proc_ID ; set process id
1156 POP ES:[DI].sf_PID
1157 return ; carry is clear
1158EndProc SFTFromFCB
1159
1160Break <FCBHardErr - generate INT 24 for hard errors on FCBS>
1161
1162;
1163; FCBHardErr - signal to a user app that he is trying to use an
1164; unavailable FCB.
1165;
1166; Inputs: none.
1167; Outputs: none.
1168; Registers modified: all
1169;
1170
1171Procedure FCBHardErr,NEAR
1172 ASSUME DS:NOTHING,ES:NOTHING
1173 MOV AX,error_FCB_Unavailable
1174 MOV [ALLOWED],allowed_FAIL
1175 LES BP,[THISDPB]
1176 MOV DI,1 ; Fake some registers
1177 MOV CX,DI
1178 MOV DX,ES:[BP.dpb_first_sector]
1179 invoke HARDERR
1180 STC
1181 return
1182EndProc FCBHardErr
1183
1184CODE ENDS
1185END
diff --git a/v4.0/src/DOS/FCBIO2.ASM b/v4.0/src/DOS/FCBIO2.ASM
new file mode 100644
index 0000000..ec0ee3e
--- /dev/null
+++ b/v4.0/src/DOS/FCBIO2.ASM
@@ -0,0 +1,722 @@
1; SCCSID = @(#)fcbio2.asm 1.2 85/07/23
2; SCCSID = @(#)fcbio2.asm 1.2 85/07/23
3TITLE FCBIO2 - FCB system calls
4NAME FCBIO2
5
6;
7; Ancient 1.0 1.1 FCB system calls
8; regen save
9; GetRR
10; GetExtent
11; SetExtent
12; GetExtended
13; GetRecSize
14; FCBIO
15; $FCB_OPEN written ACC ACC
16; $FCB_CREATE written ACC ACC
17; $FCB_RANDOM_WRITE_BLOCK written fcbio fcbio
18; $FCB_RANDOM_READ_BLOCK written fcbio fcbio
19; $FCB_SEQ_READ written fcbio fcbio
20; $FCB_SEQ_WRITE written fcbio fcbio
21; $FCB_RANDOM_READ written fcbio fcbio
22; $FCB_RANDOM_WRITE written fcbio fcbio
23;
24; Revision history:
25;
26; Created: ARR 4 April 1983
27; MZ 6 June 1983 completion of functions
28; MZ 15 Dec 1983 Brain damaged programs close FCBs multiple
29; times. Change so successive closes work by
30; always returning OK. Also, detect I/O to
31; already closed FCB and return EOF.
32; MZ 16 Jan 1984 More braindamage. Need to separate info
33; out of sft into FCB for reconnection
34;
35; A000 version 4.00 Jan. 1988
36;
37.xlist
38;
39; get the appropriate segment definitions
40;
41include dosseg.asm
42
43CODE SEGMENT BYTE PUBLIC 'CODE'
44 ASSUME SS:DOSGROUP,CS:DOSGROUP
45
46.xcref
47INCLUDE DOSSYM.INC
48INCLUDE DEVSYM.INC
49include version.inc
50.cref
51.list
52
53 EXTRN DOS_Read:NEAR, DOS_Write:NEAR
54 EXTRN DOS_Open:NEAR, DOS_Create:NEAR
55
56 I_need DMAAdd,DWORD ; current user's DMA address
57 I_need OpenBuf,128 ; buffer for translating paths
58 I_need ThisSFT,DWORD ; SFT in use
59 I_need sftFCB,DWORD ; pointer to SFTs for FCB cache
60 I_need FCBLRU,WORD ; least recently used count
61 I_need DISK_FULL,BYTE ; flag for disk full
62if debug
63 I_need BugLev,WORD
64 I_need BugTyp,WORD
65 include bugtyp.asm
66endif
67
68IF BUFFERFLAG
69
70 I_need BUF_EMS_MODE,BYTE
71 I_need BUF_EMS_LAST_PAGE,DWORD
72 I_need BUF_EMS_FIRST_PAGE,DWORD
73 I_need BUF_EMS_SAFE_FLAG,BYTE
74 I_need BUF_EMS_NPA640,WORD
75 I_need BUF_EMS_PAGE_FRAME,WORD
76 I_need BUF_EMS_PFRAME,WORD
77 I_need LASTBUFFER,DWORD
78
79 extrn restore_user_map:near
80 extrn Setup_EMS_Buffers:near
81
82ENDIF
83
84
85; Defintions for FCBOp flags
86
87Random = 2 ; random operation
88FCBRead = 4 ; doing a read
89Block = 8 ; doing a block I/O
90
91Break <GetRR - return the random record field in DX:AX>
92
93;
94; GetRR - correctly load DX:AX with the random record field (3 or 4 bytes)
95; from the FCB pointed to by DS:SI
96;
97; Inputs: DS:SI point to an FCB
98; BX has record size
99; Outputs: DX:AX contain the contents of the random record field
100; Registers modified: none
101
102Procedure GetRR,NEAR
103 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
104 MOV AX,WORD PTR [SI.FCB_RR] ; get low order part
105 MOV DX,WORD PTR [SI.FCB_RR+2] ; get high order part
106 CMP BX,64 ; ignore MSB of RR if recsiz > 64
107 JB GetRRBye
108 XOR DH,DH
109GetRRBye:
110 return
111EndProc GetRR
112
113Break <GetExtent - retrieve next location for sequential IO>
114
115;
116; GetExtent - Construct the next record to perform I/O from the EXTENT and
117; NR fields in the FCB.
118;
119; Inputs: DS:SI - point to FCB
120; Outputs: DX:AX contain the contents of the random record field
121; Registers modified: none
122
123Procedure GetExtent,NEAR
124 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
125 MOV AL,[SI.fcb_NR] ; get low order piece
126 MOV DX,[SI.fcb_EXTENT] ; get high order piece
127 SHL AL,1
128 SHR DX,1
129 RCR AL,1 ; move low order bit of DL to high order of AH
130 MOV AH,DL
131 MOV DL,DH
132 XOR DH,DH
133 return
134EndProc GetExtent
135
136Break <SetExtent - update the extent/NR field>
137
138;
139; SetExtent - change the position of an FCB by filling in the extent/NR
140; fields
141;
142; Inputs: DS:SI point to FCB
143; DX:AX is a record location in file
144; Outputs: Extent/NR fields are filled in
145; Registers modified: CX
146
147Procedure SetExtent,NEAR
148 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
149 SaveReg <AX,DX>
150 MOV CX,AX
151 AND AL,7FH ; next rec field
152 MOV [SI.fcb_NR],AL
153 AND CL,80H ; save upper bit
154 SHL CX,1
155 RCL DX,1 ; move high bit of CX to low bit of DX
156 MOV AL,CH
157 MOV AH,DL
158 MOV [SI.fcb_EXTENT],AX ; all done
159 RestoreReg <DX,AX>
160 return
161EndProc SetExtent
162
163Break <GetExtended - find FCB in potential extended fcb>
164
165;
166; GetExtended - Make DS:SI point to FCB from DS:DX
167;
168; Inputs: DS:DX point to a possible extended FCB
169; Outputs: DS:SI point to the FCB part
170; zeroflag set if not extended fcb
171; Registers modified: SI
172
173Procedure GetExtended,NEAR
174 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
175 MOV SI,DX ; point to Something
176 CMP BYTE PTR DS:[SI],-1 ; look for extention
177 JNZ GetBye ; not there
178 ADD SI,7 ; point to FCB
179GetBye:
180 CMP SI,DX ; set condition codes
181 return
182EndProc GetExtended
183
184Break <GetRecSize - return in BX the FCB record size>
185
186;
187; GetRecSize - return in BX the record size from the FCB at DS:SI
188;
189; Inputs: DS:SI point to a non-extended FCB
190; Outputs: BX contains the record size
191; Registers modified: None
192
193Procedure GetRecSize,NEAR
194 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
195 MOV BX,[SI.fcb_RECSIZ] ; get his record size
196 OR BX,BX ; is it nul?
197 retnz
198 MOV BX,128 ; use default size
199 MOV [SI.fcb_RECSIZ],BX ; stuff it back
200 return
201EndProc GetRecSize
202
203BREAK <FCBIO - do internal FCB I/O>
204
205;
206; FCBIO - look at FCBOP and merge all FCB operations into a single routine.
207;
208; Inputs: FCBOP flags which operations need to be performed
209; DS:DX point to FCB
210; CX may have count of number of records to xfer
211; Outputs: AL has error code
212; Registers modified: all
213
214Procedure FCBIO,NEAR
215 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
216PUBLIC FCBIO001S,FCBIO001E
217FCBIO001S:
218 LocalVar FCBErr,BYTE
219 LocalVar cRec,WORD
220 LocalVar RecPos,DWORD
221 LocalVar RecSize,WORD
222 LocalVar bPos,DWORD
223 LocalVar cByte,WORD
224 LocalVar cResult,WORD
225 LocalVar cRecRes,WORD
226 LocalVar FCBOp,BYTE
227FCBIO001E:
228 Enter
229
230FEOF EQU 1
231FTRIM EQU 2
232 MOV FCBOp,AL
233 MOV FCBErr,0 ; FCBErr = 0;
234 invoke GetExtended ; FCB = GetExtended ();
235 TEST FCBOp,BLOCK ; if ((OP&BLOCK) == 0)
236 JNZ GetPos
237 MOV CX,1 ; cRec = 1;
238GetPos:
239 MOV cRec,CX ;*Tail coalesce
240 invoke GetExtent ; RecPos = GetExtent ();
241 invoke GetRecSize ; RecSize = GetRecSize ();
242 MOV RecSize,BX
243 TEST FCBOp,RANDOM ; if ((OP&RANDOM) <> 0)
244 JZ GetRec
245 invoke GetRR ; RecPos = GetRR ();
246GetRec:
247 MOV RecPosL,AX ;*Tail coalesce
248 MOV RecPosH,DX
249 invoke SetExtent ; SetExtent (RecPos);
250 MOV AX,RecPosH ; bPos = RecPos * RecSize;
251 MUL BX
252 MOV DI,AX
253 MOV AX,RecPosL
254 MUL BX
255 ADD DX,DI
256 MOV bPosL,AX
257 MOV bPosH,DX
258 MOV AX,cRec ; cByte = cRec * RecSize;
259 MUL BX
260 MOV cByte,AX
261 ADD AX,WORD PTR DMAAdd ; if (cByte+DMA > 64K) {
262 ADC DX,0
263 JZ DoOper
264 MOV FCBErr,FTRIM ; FCBErr = FTRIM;
265 MOV AX,WORD PTR DMAAdd ; cRec = (64K-DMA)/RecSize;
266 NEG AX
267 JNZ DoDiv
268 DEC AX
269DoDiv:
270 XOR DX,DX
271 DIV BX
272 MOV cRec,AX
273 MUL BX ; cByte = cRec * RecSize;
274 MOV cByte,AX ; }
275DoOper:
276 XOR BX,BX
277 MOV cResult,BX ; cResult = 0;
278 CMP cByte,BX ; if (cByte <> 0 ||
279 JNZ DoGetExt
280 TEST FCBErr,FTRIM ; (FCBErr&FTRIM) == 0) {
281IF debug
282 JZ DoGetExt
283 JMP SkipOp
284ELSE
285 JZ SKP_SkipOp
286 JMP SkipOp
287SKP_SkipOp:
288ENDIF
289DoGetExt:
290 invoke SFTFromFCB ; if (!SFTFromFCB (SFT,FCB))
291 JNC ContinueOp
292FCBDeath:
293 invoke FCB_Ret_Err ; signal error, map for extended
294 MOV cRecRes,0 ; no bytes transferred
295 MOV FCBErr,FEOF ; return FTRIM;
296 JMP FCBSave ; bam!
297ContinueOp:
298 Assert ISSFT,<ES,DI>,"ContinueOP"
299 MOV AX,WORD PTR [SI].fcb_filsiz
300 MOV WORD PTR ES:[DI].sf_size,AX
301 MOV AX,WORD PTR [SI].fcb_filsiz+2
302 MOV WORD PTR ES:[DI].sf_size+2,AX
303 MOV AX,bPosL
304 MOV DX,bPosH
305 MOV WORD PTR ES:[DI.sf_position],AX
306 XCHG WORD PTR ES:[DI.sf_position+2],DX
307 PUSH DX ; save away Open age.
308 MOV CX,cByte ; cResult =
309
310; int 3
311
312 MOV DI,OFFSET DOSGroup:DOS_Read ; *(OP&FCBRead ? DOS_Read
313 TEST FCBOp,FCBRead ; : DOS_Write)(cRec);
314 JNZ DoContext
315 MOV DI,OFFSET DOSGroup:DOS_Write
316DoContext:
317 SaveReg <BP,DS,SI>
318 Context DS
319;; Fix for disk full
320 CALL DI
321 RestoreReg <SI,DS,BP>
322 ASSUME DS:NOTHING
323
324IF BUFFERFLAG
325 pushf
326 push ax
327 push bx
328
329 cmp cs:[BUF_EMS_MODE], -1
330 jz dos_fcb_call_done
331 call restore_user_map
332 mov ax, word ptr cs:[BUF_EMS_LAST_PAGE]
333 cmp cs:[BUF_EMS_PFRAME], ax
334 je dos_fcb_call_done
335 mov word ptr cs:[LASTBUFFER], -1
336 mov cs:[BUF_EMS_PFRAME], ax
337 mov ax, word ptr cs:[BUF_EMS_LAST_PAGE+2]
338 mov cs:[BUF_EMS_PAGE_FRAME], ax
339 mov cs:[BUF_EMS_SAFE_FLAG], 1
340 call Setup_EMS_Buffers
341
342dos_fcb_call_done:
343 pop bx
344 pop ax
345 popf
346ENDIF
347
348 JC FCBDeath
349
350 CMP BYTE PTR [DISK_FULL],0 ; treat disk full as error
351 JZ NODSKFULL
352 MOV BYTE PTR [DISK_FULL],0 ; clear the flag
353 MOV FCBerr,FEOF ; set disk full flag
354NODSKFULL:
355;; Fix for disk full
356 MOV cResult,CX
357 invoke SaveFCBInfo ; SaveFCBInfo (FCB);
358 Assert ISSFT,<ES,DI>,"FCBIO/SaveFCBInfo"
359%out WARNING!!! Make sure sf_position+2 is OpenAGE
360 POP WORD PTR ES:[DI].sf_Position+2 ; restore open age
361 MOV AX,WORD PTR ES:[DI].sf_size
362 MOV WORD PTR [SI].fcb_filsiz,AX
363 MOV AX,WORD PTR ES:[DI].sf_size+2
364 MOV WORD PTR [SI].fcb_filsiz+2,AX
365 ; }
366SkipOp:
367 MOV AX,cResult ; cRecRes = cResult / RecSize;
368 XOR DX,DX
369 DIV RecSize
370 MOV cRecRes,AX
371 ADD RecPosL,AX ; RecPos += cRecResult;
372 ADC RecPosH,0
373;
374; If we have not gotten the expected number of records, we signal an EOF
375; condition. On input, this is EOF. On output this is usually disk full.
376; BUT... Under 2.0 and before, all device output IGNORED this condition. So
377; do we.
378;
379 CMP AX,cRec ; if (cRecRes <> cRec)
380 JZ TryBlank
381 TEST FCBOp,FCBRead ; if (OP&FCBRead || !DEVICE)
382 JNZ SetEOF
383 TEST ES:[DI].sf_flags,devid_device
384 JNZ TryBlank
385SetEOF:
386 MOV FCBErr,FEOF ; FCBErr = FEOF;
387TryBlank: ;
388 OR DX,DX ; if (cResult%RecSize <> 0) {
389 JZ SetExt
390 ADD RecPosL,1 ; RecPos++;
391 ADC RecPosH,0
392 TEST FCBOp,FCBRead ; if(OP&FCBRead) <> 0) {
393 JZ SetExt
394 INC cRecRes ; cRecRes++;
395 MOV FCBErr,FTRIM + FEOF ; FCBErr = FTRIM | FEOF;
396 MOV CX,RecSize ; Blank (RecSize-cResult%RecSize,
397 SUB CX,DX ; DMA+cResult);
398 XOR AL,AL
399 LES DI,DMAAdd
400 ADD DI,cResult
401 REP STOSB ; } }
402SetExt:
403 MOV DX,RecPosH
404 MOV AX,RecPosL
405 TEST FCBOp,RANDOM ; if ((OP&Random) == 0 ||
406 JZ DoSetExt
407 TEST FCBOp,BLOCK ; (OP&BLOCK) <> 0)
408 JZ TrySetRR
409DoSetExt:
410 invoke SetExtent ; SetExtent (RecPos, FCB);
411TrySetRR:
412 TEST FCBOp,BLOCK ; if ((op&BLOCK) <> 0)
413 JZ TryReturn
414 MOV WORD PTR [SI.FCB_RR],AX ; FCB->RR = RecPos;
415 MOV BYTE PTR [SI.FCB_RR+2],DL
416 CMP [SI.fcb_RECSIZ],64
417 JAE TryReturn
418 MOV [SI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64
419TryReturn:
420 TEST FCBOP,FCBRead ; if (!(FCBOP & FCBREAD)) {
421 JNZ FCBSave
422 SaveReg <DS> ; FCB->FDate = date;
423 Invoke Date16 ; FCB->FTime = time;
424 RestoreReg <DS>
425 MOV [SI].FCB_FDate,AX
426 MOV [SI].FCB_FTime,DX ; }
427FCBSave:
428 TEST FCBOp,BLOCK ; if ((op&BLOCK) <> 0)
429 JZ DoReturn
430 MOV CX,cRecRes ; user_CX = cRecRes;
431 invoke Get_User_Stack
432 MOV [SI.User_CX],CX
433DoReturn:
434 MOV AL,FCBErr ; return (FCBERR);
435 Leave
436 return
437EndProc FCBIO
438
439Break <$FCB_Open - open an old-style FCB>
440
441;
442; $FCB_Open - CPM compatability file open. The user has formatted an FCB
443; for us and asked to have the rest filled in.
444;
445; Inputs: DS:DX point to an unopenned FCB
446; Outputs: AL indicates status 0 is ok FF is error
447; FCB has the following fields filled in:
448; Time/Date Extent/NR Size
449
450Procedure $FCB_Open,NEAR
451 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
452 MOV AX,sharing_Compat+Open_For_Both
453 MOV CX,OFFSET DOSGroup:DOS_Open
454;
455; The following is common code for Creation and openning of FCBs. AX is
456; either attributes (for create) or open mode (for open)... DS:DX points to
457; the FCB
458;
459DoAccess:
460 SaveReg <DS,DX,CX,AX> ; save FCB pointer away
461 MOV DI,OFFSET DOSGroup:OpenBuf
462 invoke TransFCB ; crunch the fcb
463 RestoreReg <AX,CX,DX,DS> ; get fcb
464 JNC FindFCB ; everything seems ok
465FCBOpenErr:
466;
467; AL has error code
468;
469 transfer FCB_Ret_Err
470FindFCB:
471 invoke GetExtended ; DS:SI will point to FCB
472 invoke LRUFCB ; get a sft entry (no error)
473 JC HardMessage
474 ASSUME ES:NOTHING
475
476; Message 1,"Entering "
477; MessageNum ES
478; Message 1,":"
479; MessageNum DI
480; Message 1,<13,10>
481
482 MOV ES:[DI].sf_mode,sf_ISFCB
483 SaveReg <DS,SI,BX> ; save fcb pointer
484 MOV SI,CX
485 Context DS ; let DOS_Open see variables
486 CALL SI ; go open the file
487 RestoreReg <BX,SI,DS> ; get fcb
488 ASSUME DS:NOTHING
489 LES DI,ThisSFT ; get sf pointer
490 JNC FCBOK ; operation succeeded
491 Assert ISSFT,<ES,DI>,"DeadFCB"
492failopen:
493 PUSH AX
494 MOV AL,"R" ; clear out field (free sft)
495 invoke BlastSFT
496 POP AX
497 CMP AX,error_too_many_open_files
498 JZ HardMessage
499 CMP AX,error_sharing_buffer_exceeded
500 jnz DeadFCB
501HardMessage:
502 PUSH AX
503 invoke FCBHardErr
504 POP AX
505DeadFCB:
506 transfer FCB_Ret_Err
507FCBOK:
508 invoke IsSFTNet ;AN007;F.C. >32mb Non Fat file?
509 JNZ FCBOK2 ;AN007;F.C. >32mb yes
510 invoke CheckShare ;AN000;F.C. >32mb share around?
511 JNZ FCBOK2 ;AN000;F.C. >32mb yes
512 CMP WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;F.C. >32mb if dirsec >32mb
513 JZ FCBOK2 ;AN000;F.C. >32mb then error
514 MOV AX,error_sys_comp_not_loaded ;AN000;F.C. >32mb
515 JMP failopen ;AN000;F.C. >32mb
516FCBOK2:
517
518 INC ES:[DI].sf_ref_count ; increment reference count
519 invoke SaveFCBInfo
520 Assert ISSFT,<ES,DI>,"FCBOK"
521 invoke SetOpenAge
522 Assert ISSFT,<ES,DI>,"FCBOK/SetOpenAge"
523 TEST ES:[DI].sf_flags,devid_device
524 JNZ FCBNoDrive ; do not munge drive on devices
525 MOV AL,DS:[SI] ; get drive byte
526 invoke GetThisDrv ; convert
527 INC AL
528 MOV DS:[SI],AL ; stash in good drive letter
529FCBNoDrive:
530 MOV [SI].FCB_RecSiz,80h ; stuff in default record size
531 MOV AX,ES:[DI].SF_Time ; set time
532 MOV [SI].FCB_FTime,AX
533 MOV AX,ES:[DI].SF_Date ; set date
534 MOV [SI].FCB_FDate,AX
535 MOV AX,WORD PTR ES:[DI].SF_Size ; set sizes
536 MOV [SI].FCB_FILSIZ,AX
537 MOV AX,WORD PTR ES:[DI].SF_Size+2
538 MOV [SI].FCB_FILSIZ+2,AX
539 XOR AX,AX ; convenient zero
540 MOV [SI].FCB_Extent,AX ; point to beginning of file
541;
542; We must scan the set of FCB SFTs for one that appears to match the current
543; one. We cheat and use CheckFCB to match the FCBs.
544;
545 LES DI,SFTFCB ; get the pointer to head of the list
546 MOV AH,BYTE PTR ES:[DI].sfCount ; get number of SFTs to scan
547OpenScan:
548 CMP AL,[SI].fcb_sfn ; don't compare ourselves
549 JZ SkipCheck
550 SaveReg <AX> ; preserve count
551 invoke CheckFCB ; do they match
552 RestoreReg <AX> ; get count back
553 JNC OpenFound ; found a match!
554SkipCheck:
555 INC AL ; advance to next FCB
556 CMP AL,AH ; table full?
557 JNZ OpenScan ; no, go for more
558OpenDone:
559 xor al,al ; return success
560 return
561;
562; The SFT at ES:DI is the one that is already in use for this FCB. We set the
563; FCB to use this one. We increment its ref count. We do NOT close it at all.
564; Consider:
565;
566; open (foo) delete (foo) open (bar)
567;
568; This causes us to recycle (potentially) bar through the same local SFT as
569; foo even though foo is no longer needed; this is due to the server closing
570; foo for us when we delete it. Unfortunately, we cannot see this closure.
571; If we were to CLOSE bar, the server would then close the only reference to
572; bar and subsequent I/O would be lost to the redirector.
573;
574; This gets solved by NOT closing the sft, but zeroing the ref count
575; (effectively freeing the SFT) and informing the sharer (if relevant) that
576; the SFT is no longer in use. Note that the SHARER MUST keep its ref counts
577; around. This will allow us to access the same file through multiple network
578; connections and NOT prematurely terminate when the ref count on one
579; connection goes to zero.
580;
581OpenFound:
582 MOV [SI].fcb_SFN,AL ; assign with this
583 INC ES:[DI].sf_ref_count ; remember this new invocation
584 MOV AX,FCBLRU ; update LRU counts
585 MOV ES:[DI].sf_LRU,AX
586;
587; We have an FCB sft that is now of no use. We release sharing info and then
588; blast it to prevent other reuse.
589;
590 context DS
591 LES DI,ThisSFT
592 DEC ES:[DI].sf_ref_count ; free the newly allocated SFT
593 invoke ShareEnd
594 Assert ISSFT,<ES,DI>,"Open blasting"
595 MOV AL,'C'
596 invoke BlastSFT
597 JMP OpenDone
598EndProc $FCB_Open
599
600BREAK <$FCB_Create - create a new directory entry>
601
602;
603; $FCB_Create - CPM compatability file create. The user has formatted an
604; FCB for us and asked to have the rest filled in.
605;
606; Inputs: DS:DX point to an unopenned FCB
607; Outputs: AL indicates status 0 is ok FF is error
608; FCB has the following fields filled in:
609; Time/Date Extent/NR Size
610
611Procedure $FCB_Create,NEAR
612 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
613 MOV CX,OFFSET DOSGroup:DOS_Create ; routine to call
614 XOR AX,AX ; attributes to create
615 invoke GetExtended ; get extended FCB
616 JZ DoAccessJ ; not an extended FCB
617 MOV AL,[SI-1] ; get attributes
618DoAccessJ:
619 JMP DoAccess ; do dirty work
620EndProc $FCB_Create
621
622BREAK <$FCB_Random_write_Block - write a block of records to a file >
623
624;
625; $FCB_Random_Write_Block - retrieve a location from the FCB, seek to it
626; and write a number of blocks from it.
627;
628; Inputs: DS:DX point to an FCB
629; Outputs: AL = 0 write was successful and the FCB position is updated
630; AL <> 0 Not enough room on disk for the output
631;
632
633Procedure $FCB_Random_Write_Block,NEAR
634 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
635 MOV AL,Random+Block
636 JMP FCBIO
637EndProc $FCB_Random_Write_Block
638
639BREAK <$FCB_Random_Read_Block - read a block of records to a file >
640
641;
642; $FCB_Random_Read_Block - retrieve a location from the FCB, seek to it
643; and read a number of blocks from it.
644;
645; Inputs: DS:DX point to an FCB
646; Outputs: AL = error codes defined above
647;
648
649Procedure $FCB_Random_Read_Block,NEAR
650 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
651 MOV AL,Random+FCBRead+Block
652 JMP FCBIO
653EndProc $FCB_Random_Read_Block
654
655BREAK <$FCB_Seq_Read - read the next record from a file >
656
657;
658; $FCB_Seq_Read - retrieve the next record from an FCB and read it into
659; memory
660;
661; Inputs: DS:DX point to an FCB
662; Outputs: AL = error codes defined above
663;
664
665Procedure $FCB_Seq_Read,NEAR
666 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
667 MOV AL,FCBRead
668 JMP FCBIO
669EndProc $FCB_Seq_Read
670
671BREAK <$FCB_Seq_Write - write the next record to a file >
672
673;
674; $FCB_Seq_Write - retrieve the next record from an FCB and write it to the
675; file
676;
677; Inputs: DS:DX point to an FCB
678; Outputs: AL = error codes defined above
679;
680
681Procedure $FCB_Seq_Write,NEAR
682 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
683 MOV AL,0
684 jmp FCBIO
685EndProc $FCB_SEQ_WRITE
686
687BREAK <$FCB_Random_Read - Read a single record from a file >
688
689;
690; $FCB_Random_Read - retrieve a location from the FCB, seek to it and read a
691; record from it.
692;
693; Inputs: DS:DX point to an FCB
694; Outputs: AL = error codes defined above
695;
696
697Procedure $FCB_Random_Read,NEAR
698 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
699 MOV AL,Random+FCBRead
700 jmp FCBIO ; single block
701EndProc $FCB_RANDOM_READ
702
703BREAK <$FCB_Random_Write - write a single record to a file >
704
705;
706; $FCB_Random_Write - retrieve a location from the FCB, seek to it and write
707; a record to it.
708;
709; Inputs: DS:DX point to an FCB
710; Outputs: AL = error codes defined above
711;
712
713Procedure $FCB_Random_Write,NEAR
714 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup
715 MOV AL,Random
716 jmp FCBIO
717EndProc $FCB_RANDOM_WRITE
718
719CODE ENDS
720END
721
722 \ No newline at end of file
diff --git a/v4.0/src/DOS/FILE.ASM b/v4.0/src/DOS/FILE.ASM
new file mode 100644
index 0000000..9fca034
--- /dev/null
+++ b/v4.0/src/DOS/FILE.ASM
@@ -0,0 +1,909 @@
1; SCCSID = @(#)file.asm 1.2 85/07/23
2; SCCSID = @(#)file.asm 1.2 85/07/23
3TITLE FILE - Pathname related system calls
4NAME FILE
5
6;
7; Pathname related system calls. These will be passed direct text of the
8; pathname from the user. They will need to be passed through the macro
9; expander prior to being sent through the low-level stuff. I/O specs are
10; defined in DISPATCH. The system calls are:
11;
12; $Open written
13; $Creat written
14; $ChMod written
15; $Unlink written
16; $Rename written
17; $CreateTempFile written
18; $CreateNewFile written
19; $Extended_Open written DOS 4.00
20; GetIOParms written DOS 4.00
21;
22; Revision history:
23;
24; Created: MZ 4 April 1983
25; A000 version 4.00 Jan. 1988
26
27.xlist
28;
29; get the appropriate segment definitions
30;
31include dosseg.asm
32
33CODE SEGMENT BYTE PUBLIC 'CODE'
34 ASSUME SS:DOSGroup,CS:DOSGroup
35
36.xcref
37include dossym.inc
38include devsym.inc
39include fastopen.inc
40include EA.inc ;AN000;
41include version.inc
42.cref
43.list
44.sall
45
46 EXTRN DOS_OPEN:NEAR,DOS_CREATE:NEAR,DOS_Create_New:NEAR
47
48IF NOT IBMCOPYRIGHT
49 extrn Set_EXT_mode:near
50ENDIF
51
52 I_need WFP_Start,WORD ; pointer to beginning of expansion
53 I_Need ThisCDS,DWORD ; pointer to curdir in use
54 I_need ThisSft,DWORD ; SFT pointer for DOS_Open
55 I_need pJFN,DWORD ; temporary spot for pointer to JFN
56 I_need JFN,WORD ; word JFN for process
57 I_need SFN,WORD ; word SFN for process
58 I_Need OpenBuf,128 ; buffer for filename
59 I_Need RenBuf,128 ; buffer for filename in rename
60 I_need Sattrib,BYTE ; byte attribute to search for
61 I_need Ren_WFP,WORD ; pointer to real path
62 I_need cMeta,BYTE
63 I_need EXTERR,WORD ; extended error code
64 I_need EXTERR_LOCUS,BYTE ; Extended Error Locus
65 i_need JShare,DWORD ; share jump table
66 I_need fSharing,BYTE ; TRUE => via ServerDOSCall
67 I_need FastOpenTable,BYTE
68 I_need CPSWFLAG,BYTE ;AN000;FT. cpsw falg
69 I_need EXTOPEN_FLAG,WORD ;AN000;FT. extended file open flag
70 I_need EXTOPEN_ON,BYTE ;AN000;FT. extended open flag
71 I_need EXTOPEN_IO_MODE,WORD ;AN000;FT. IO mode
72 I_need XA_from,BYTE ;AN000;;FT. for get/set XA
73 I_need SAVE_ES,WORD ;AN000;;FT. for get/set XA
74 I_need SAVE_DI,WORD ;AN000;;FT. for get/set XA
75 I_need SAVE_DS,WORD ;AN000;;FT. for get/set XA
76 I_need SAVE_SI,WORD ;AN000;;FT. for get/set XA
77 I_need SAVE_DX,WORD ;AN000;;FT. for get/set XA
78 I_need SAVE_BX,WORD ;AN000;;FT. for get/set XA
79 I_need SAVE_CX,WORD ;AN000;;FT. for get/set XA
80 I_need NO_FILTER_DPATH,DWORD ;AN000;; pointer to original path of dest
81 I_need Temp_Var,WORD ;AN000;;
82 I_need DOS34_FLAG,WORD ;AN000;;
83 I_need Temp_Var2,WORD ;AN000;;
84if debug
85 I_need BugLev,WORD
86 I_need BugTyp,WORD
87include bugtyp.asm
88endif
89
90BREAK <$Open - open a file from a path string>
91
92;
93; $Open - given a path name in DS:DX and an open mode in AL, access the file
94; and return a handle
95; Inputs: DS:DX - pointer to asciz name
96; AL - open mode
97; Outputs: Carry Set - AX has error code for invalid open
98; Carry Clear - AX has per process handle number
99; Registers modified: most
100
101Procedure $Open,NEAR
102 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
103 fmt TypSysCall,LevLog,<"Open\n">
104 fmt TypSysCall,LevArgs,<" Mode = $x file = '$S'\n">,<AX,DS,DX>
105 XOR AH,AH
106Entry $Open2 ;AN000;
107 mov ch,attr_hidden+attr_system+attr_directory
108 call SetAttrib
109 MOV CX,OFFSET DOSGroup:DOS_Open ; address of routine to call
110 SaveReg <AX> ; Save mode on stack
111IF DBCS ;AN000;
112 MOV [Temp_Var],0 ;AN000;KK. set variable with 0
113ENDIF ;AN000;
114
115AccessFile:
116;
117; Grab a free SFT.
118;
119IF DBCS ;AN000;
120 TEST [Temp_Var],8 ;AN000;;KK. volume id bit set ;AN000;
121 JZ novol ;AN000;;KK. no ;AN000;
122 OR [DOS34_FLAG],DBCS_VOLID ;AN000;;KK. set bit for transpath ;AN000;
123novol: ;AN000;
124ENDIF ;AN000;
125 EnterCrit critSFT
126 invoke SFNFree ; get a free sfn
127 LeaveCrit critSFT
128 JC OpenFailJ ; oops, no free sft's
129 MOV SFN,BX ; save the SFN for later
130 fmt TypAccess,LevSFN,<"AccessFile setting SFN to $x\n">,<BX>
131 MOV WORD PTR [ThisSFT],DI ; save the SF offset
132 MOV WORD PTR [ThisSFT+2],ES ; save the SF segment
133;
134; Find a free area in the user's JFN table.
135;
136 invoke JFNFree ; get a free jfn
137 JNC SaveJFN
138OpenFailJ:
139 JMP OpenFail ; there were free JFNs... try SFN
140SaveJFN:
141 MOV WORD PTR [pJFN],DI ; save the jfn offset
142 MOV WORD PTR [pJFN+2],ES ; save the jfn segment
143 MOV [JFN],BX ; save the jfn itself
144;
145; We have been given an JFN. We lock it down to prevent other tasks from
146; reusing the same JFN.
147;
148 MOV BX,SFN
149 MOV ES:[DI],BL ; assign the JFN
150 MOV SI,DX ; get name in appropriate place
151 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
152 SaveReg <CX> ; save routine to call
153 invoke TransPath ; convert the path
154 RestoreReg <BX> ; restore routine to call
155 LDS SI,ThisSFT
156 ASSUME DS:NOTHING
157 JC OpenCleanJ ; no error, go and open file
158 CMP cMeta,-1
159 JZ SetSearch
160 MOV AL,error_file_not_found ; no meta chars allowed
161OpenCleanJ:
162 JMP OpenClean
163SetSearch:
164 RestoreReg <AX> ; Mode (Open), Attributes (Create)
165;
166; We need to get the new inheritance bits.
167;
168 xor cx,cx
169 CMP BX,OFFSET DOSGroup:DOS_OPEN
170 JNZ DoOper
171 TEST AL,sharing_no_inherit ; look for no inher
172 JZ DoOper
173 AND AL,07Fh ; mask off inherit bit
174 MOV CX,sf_no_inherit
175DoOper:
176 MOV [SI].sf_mode,0 ; initialize mode field to 0
177 MOV [SI.SF_mft],0 ; clean out sharing info
178;
179;------------------------------------------------------------HKN 8/7/88
180; Check if this is an extended open. If so you must set the
181; modes in sf_mode. Call Set_EXT_mode to do all this. See
182; Set_EXT_mode in creat.asm
183;
184IF NOT IBMCOPYRIGHT
185
186 push es ; set up es:di to point to SFT
187 push di
188 push ds
189 pop es
190 push si
191 pop di
192 call Set_EXT_mode
193 pop di
194 pop es
195
196ENDIF
197
198;-----------------------------------------------------------------------
199
200 Context DS
201 SaveReg <CX>
202 CALL BX ; blam!
203 RestoreReg <CX>
204 LDS SI,ThisSFT
205 ASSUME DS:NOTHING
206 JC OpenE2 ;AN000;FT. chek extended open hooks first
207;
208; The SFT was successfully opened. Remove busy mark.
209;
210OpenOK:
211 ASSUME DS:NOTHING
212; MOV AL,[SI].sf_attr_hi ;AN000;FT. save file type for EXEC
213; MOV BYTE PTR [Temp_Var2],AL ;AN000;FT.
214 MOV [SI].sf_ref_count,1
215 OR [SI].sf_flags,CX ; set no inherit bit if necessary
216;
217; If the open mode is 70, we scan the system for other SFT's with the same
218; contents. If we find one, then we can 'collapse' thissft onto the already
219; opened one. Otherwise we use this new one. We compare uid/pid/mode/mft
220;
221; Since this is only relevant on sharer systems, we stick this code into the
222; sharer.
223;
224 MOV AX,JFN
225if installed
226 Call JShare + 12 * 4
227else
228 Call ShCol
229endif
230 fmt TypAccess,LevSFN,<"AccessFile setting SFN to -1\n">
231 MOV SFN,-1 ; clear out sfn pointer
232 fmt TypSysCall,LevLog,<"Open/CreateXX: return $x\n">,<AX>
233 transfer Sys_Ret_OK ; bye with no errors
234;Extended Open hooks check
235OpenE2: ;AN000;;EO.
236 CMP AX,error_invalid_parameter ;AN000;;EO. IFS extended open ?
237 JNZ OpenE ;AN000;;EO. no.
238 JMP OpenCritLeave ;AN000;;EO. keep handle
239
240;Extended Open hooks check
241;
242; AL has error code. Stack has argument to dos_open/dos_create.
243;
244OpenClean:
245 fmt TypSysCall,LevLog,<"Return value from transpath $x\n">,<AX>
246 RestoreReg <bx> ; clean off stack
247OpenE:
248 MOV [SI.SF_Ref_Count],0 ; release SFT
249 LDS SI,pJFN
250 MOV BYTE PTR [SI],0FFh ; free the SFN...
251 JMP SHORT OpenCritLeave
252
253OpenFail:
254 STI
255 RestoreReg <CX> ; Clean stack
256OpenCritLeave:
257 MOV SFN,-1 ; remove mark.
258 fmt TypSysCall,LevLog,<"Open/CreateXX: error $x\n">,<AX>
259;; File Tagging DOS 4.00
260 CMP CS:[EXTERR],error_Code_Page_Mismatched ;AN000;;FT. code page mismatch
261 JNZ NORERR ;AN000;;FT. no
262 transfer From_GetSet ;AN000;;FT. yes
263NORERR: ;AN000;
264
265;; File Tagging DOS 4.00
266 transfer Sys_Ret_Err ; no free, return error
267
268EndProc $Open
269
270BREAK <$Creat - create a brand-new file>
271
272;
273; $Creat - create the directory entry specified in DS:DX and give it the
274; initial attributes contained in CX
275; Inputs: DS:DX - ASCIZ path name
276; CX - initial attributes
277; Outputs: Carry set - AX has error code
278; Carry reset - AX has handle
279; Registers modified: all
280
281Procedure $Creat,NEAR
282 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
283 fmt TypSysCall,LevLog,<"Create\n">
284 fmt TypSysCall,LevArgs,<" Att = $x file = '$S'\n">,<CX,DS,DX>
285IF DBCS ;AN000;
286 MOV [Temp_Var],CX ;AN000;KK. set variable with attribute ;AN000;
287ENDIF ;AN000;
288 SaveReg <CX> ; Save attributes on stack
289 MOV CX,OFFSET DOSGroup:DOS_Create; routine to call
290AccessSet:
291 mov SAttrib,attr_hidden+attr_system
292 JMP AccessFile ; use good ol' open
293EndProc $Creat
294
295BREAK <$CHMOD - change file attributes>
296;
297; Assembler usage:
298; LDS DX, name
299; MOV CX, attributes
300; MOV AL,func (0=get, 1=set)
301; INT 21h
302; Error returns:
303; AX = error_path_not_found
304; AX = error_access_denied
305;
306
307 procedure $CHMOD,NEAR
308 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
309 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
310 SaveReg <AX,CX> ; save function and attributes
311 MOV SI,DX ; get things in appropriate places
312 invoke TransPathSet ; get correct path
313 RestoreReg <CX,AX> ; and get function and attrs back
314 JC ChModErr ; errors get mapped to path not found
315 Context DS ; set up for later possible calls
316 CMP cMeta,-1
317 JNZ ChModErr
318 MOV [SAttrib],attr_hidden+attr_system+attr_directory
319 SUB AL,1 ; fast way to discriminate
320 JB ChModGet ; 0 -> go get value
321 JZ ChModSet ; 1 -> go set value
322 MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
323 error error_invalid_function ; bad value
324ChModGet:
325 invoke Get_File_Info ; suck out the ol' info
326 JC ChModE ; error codes are already set for ret
327 invoke Get_User_stack ; point to user saved vaiables
328 MOV [SI.User_CX],AX ; return the attributes
329 transfer Sys_Ret_OK ; say sayonara
330ChModSet:
331 MOV AX,CX ; get attrs in position
332 invoke Set_File_Attribute ; go set
333 JC ChModE ; errors are set
334 transfer Sys_Ret_OK
335ChModErr:
336 mov al,error_path_not_found
337ChmodE:
338 Transfer SYS_RET_ERR
339EndProc $ChMod
340
341BREAK <$UNLINK - delete a file entry>
342;
343; Assembler usage:
344; LDS DX, name
345; IF VIA SERVER DOS CALL
346; MOV CX,SEARCH_ATTRIB
347; MOV AH, Unlink
348; INT 21h
349;
350; Error returns:
351; AX = error_file_not_found
352; = error_access_denied
353;
354
355 procedure $UNLINK,NEAR
356 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
357 SaveReg <CX> ; Save possible CX input parm
358 MOV SI,DX ; Point at input string
359 MOV DI,OFFSET DOSGroup:OpenBuf ; temp spot for path
360 invoke TransPathSet ; go get normalized path
361 RestoreReg <CX>
362 JC ChModErr ; badly formed path
363 CMP cMeta,-1 ; meta chars?
364 JNZ NotFound
365 Context DS
366 mov ch,attr_hidden+attr_system ; unlink appropriate files
367 call SetAttrib
368 invoke DOS_Delete ; remove that file
369 JC UnlinkE ; error is there
370
371
372 transfer Sys_Ret_OK ; okey doksy
373NotFound:
374 MOV AL,error_path_not_found
375UnlinkE:
376 transfer Sys_Ret_Err ; bye
377EndProc $UnLink
378
379BREAK <$RENAME - move directory entries around>
380;
381; Assembler usage:
382; LDS DX, source
383; LES DI, dest
384; IF VIA SERVER DOS CALL
385; MOV CX,SEARCH_ATTRIB
386; MOV AH, Rename
387; INT 21h
388;
389; Error returns:
390; AX = error_file_not_found
391; = error_not_same_device
392; = error_access_denied
393
394 procedure $RENAME,NEAR
395 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
396 SaveReg <CX,DS,DX> ; save source and possible CX arg
397 PUSH ES
398 POP DS ; move dest to source
399 MOV SI,DI ; save for offsets
400 MOV DI,OFFSET DOSGroup:RenBuf
401
402 MOV WORD PTR [NO_FILTER_DPATH],SI ;AN000;;IFS. save them for IFS
403 MOV WORD PTR [NO_FILTER_DPATH+2],DS ;AN000;;IFS.
404
405 invoke TransPathSet ; munge the paths
406 PUSH WFP_Start ; get pointer
407 POP Ren_WFP ; stash it
408 RestoreReg <SI,DS,CX> ; get back source and possible CX arg
409epjc2: JC ChModErr ; get old error
410 CMP cMeta,-1
411 JNZ NotFound
412 SaveReg <CX> ; Save possible CX arg
413 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
414 invoke TransPathSet ; wham
415 RestoreReg <CX>
416 JC EPJC2
417 Context DS
418 CMP cMeta,-1
419 JB NotFound
420
421 PUSH WORD PTR [THISCDS] ;AN000;;MS.save thiscds
422 PUSH WORD PTR [THISCDS+2] ;AN000;;MS.
423 MOV DI,OFFSET DOSGROUP:OpenBuf ;AN000;;MS.
424 PUSH SS ;AN000;;MS.
425 POP ES ;AN000;;MS.es:di-> source
426 XOR AL,AL ;AN000;;MS.scan all CDS
427rnloop: ;AN000;
428 invoke GetCDSFromDrv ;AN000;;MS.
429 JC dorn ;AN000;;MS. end of CDS
430 invoke StrCmp ;AN000;;MS. current dir ?
431 JZ rnerr ;AN000;;MS. yes
432 INC AL ;AN000;;MS. next
433 JMP rnloop ;AN000;;MS.
434rnerr: ;AN000;
435 ADD SP,4 ;AN000;;MS. pop thiscds
436 error error_current_directory ;AN000;;MS.
437dorn: ;AN000;
438 POP WORD PTR SS:[THISCDS+2] ;AN000;;MS.
439 POP WORD PTR SS:[THISCDS] ;AN000;;MS.
440 Context DS
441 mov ch,attr_directory+attr_hidden+attr_system; rename appropriate files
442 call SetAttrib
443 invoke DOS_Rename ; do the deed
444 JC UnlinkE ; errors
445
446
447 transfer Sys_Ret_OK
448EndProc $Rename
449
450Break <$CreateNewFile - Create a new directory entry>
451
452;
453; CreateNew - Create a new directory entry. Return a file handle if there
454; was no previous directory entry, and fail if a directory entry with
455; the same name existed previously.
456;
457; Inputs: DS:DX point to an ASCIZ file name
458; CX contains default file attributes
459; Outputs: Carry Clear:
460; AX has file handle opened for read/write
461; Carry Set:
462; AX has error code
463; Registers modified: All
464
465 Procedure $CreateNewFile,NEAR
466 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
467 fmt TypSysCall,LevLog,<"CreateNew\n">
468 fmt TypSysCall,LevArgs,<" Att = $x file = '$S'\n">,<CX,DS,DX>
469IF DBCS ;AN000;
470 MOV [Temp_Var],CX ;AN000;KK. set variable with attribute
471ENDIF ;AN000;
472 SaveReg <CX> ; Save attributes on stack
473 MOV CX,OFFSET DOSGroup:DOS_Create_New ; routine to call
474 JMP AccessSet ; use good ol' open
475EndProc $CreateNewFile
476
477Break <HexToAsciz - convert a number to hex and store it in memory>
478
479;
480; HexToAsciz - used to convert register into a hex number.
481;
482; Inputs: AX contains the number
483; ES:DI point to destination
484; Outputs: ES:DI updated
485; Registers modified: DI,CX
486
487Procedure HexToAsciz,NEAR
488 mov cx,4 ; 4 digits in AX
489GetDigit:
490 SaveReg <CX> ; preserve count
491 mov cl,4
492 ROL AX,CL ; move leftmost nibble into rightmost
493 SaveReg <AX> ; preserve remainder of digits
494 AND AL,0Fh ; grab low nibble
495 ADD AL,'0' ; turn into digit
496 CMP AL,'9' ; bigger than 9
497 JBE DoStore ; no, stash it
498 ADD AL,'A'-'0'-10 ; convert into uppercase letter
499DoStore:
500 STOSB ; drop in the character
501 RestoreReg <AX,CX> ; regain the number and count
502 loop GetDigit ; while there's more digits, go do 'em
503 return
504EndProc HexToAsciz
505
506Break <$CreateTempFile - create a unique name>
507
508;
509; $CreateTemp - given a directory, create a unique name in that directory.
510; Method used is to get the current time, convert to a name and attempt
511; a create new. Repeat until create new succeeds.
512;
513; Inputs: DS:DX point to a null terminated directory name.
514; CX contains default attributes
515; Outputs: Unique name is appended to DS:DX directory.
516; AX has handle
517; Registers modified: all
518
519 Procedure $CreateTempFile,NEAR
520 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
521 fmt TypSysCall,LevLog,<"CreateTmp\n">
522 fmt TypSysCall,LevArgs,<" Att = $x dir = '$S'\n">,<CX,DS,DX>
523PUBLIC FILE001S,FILE001E
524FILE001S:
525 LocalVar EndPtr,DWORD
526 LocalVar FilPtr,DWORD
527 LocalVar Attr,WORD
528FILE001E:
529 Enter
530 TEST CX,NOT attr_changeable
531 JZ OKatts ; Ok if no non-changeable bits set
532;
533; We need this "hook" here to detect these cases (like user sets one both of
534; vol_id and dir bits) because of the structure of the or $CreateNewFile loop
535; below. The code loops on error_access_denied, but if one of the non
536; changeable attributes is specified, the loop COULD be infinite or WILL be
537; infinite because CreateNewFile will fail with access_denied always. Thus we
538; need to detect these cases before getting to the loop.
539;
540 MOV AX,error_access_denied
541 JMP SHORT SETTMPERR
542
543OKatts:
544 MOV attr,CX ; save attribute
545 MOV FilPtrL,DX ; pointer to file
546 MOV FilPtrH,DS
547 MOV EndPtrH,DS ; seg pointer to end of dir
548 PUSH DS
549 POP ES ; destination for nul search
550 MOV DI,DX
551 MOV CX,DI
552 NEG CX ; number of bytes remaining in segment
553 IF DBCS ;AN000;
554Kloop: ;AN000;; 2/13/KK
555 MOV AL, BYTE PTR ES:[DI] ;AN000;; 2/13/KK
556 INC DI ;AN000;; 2/13/KK
557 OR AL,AL ;AN000;; 2/13/KK
558 JZ GOTEND ;AN000;; 2/13/KK
559 invoke testkanj ;AN000;; 2/13/KK
560 jz Kloop ;AN000;; 2/13/KK
561 inc di ;AN000;; Skip over second kanji byte 2/13/KK
562 CMP BYTE PTR ES:[DI],0 ;AN000;; 2/13/KK
563 JZ STOREPTH ;AN000; When char before NUL is sec Kanji byte
564 ;AN000; do not look for path char. 2/13/KK
565 jmp Kloop ;AN000; 2/13/KK
566GOTEND: ;AN000; 2/13/KK
567 ELSE ;AN000;
568 OR CX,CX ;AN000;MS. cx=0 ? ds:dx on segment boundary
569 JNZ okok ;AN000;MS. no
570 MOV CX,-1 ;AN000;MS.
571okok: ;AN000;
572 XOR AX,AX ;AN000;
573 REPNZ SCASB ;AN000;
574 ENDIF ;AN000;
575 DEC DI ; point back to the null
576 MOV AL,ES:[DI-1] ; Get char before the NUL
577 invoke PathChrCmp ; Is it a path separator?
578 JZ SETENDPTR ; Yes
579STOREPTH:
580 MOV AL,'\'
581 STOSB ; Add a path separator (and INC DI)
582SETENDPTR:
583 MOV EndPtrL,DI ; pointer to the tail
584CreateLoop:
585 Context DS ; let ReadTime see variables
586 SaveReg <BP>
587 invoke ReadTime ; go get time
588 RestoreReg <BP>
589;
590; Time is in CX:DX. Go drop it into the string.
591;
592 les di,EndPtr ; point to the string
593 mov ax,cx
594 call HexToAsciz ; store upper word
595 mov ax,dx
596 call HexToAsciz ; store lower word
597 xor al,al
598 STOSB ; nul terminate
599 LDS DX,FilPtr ; get name
600ASSUME DS:NOTHING
601 MOV CX,Attr ; get attr
602 SaveReg <BP>
603 CALL $CreateNewFile ; try to create a new file
604 RestoreReg <BP>
605 JNC CreateDone ; failed, go try again
606;
607; The operation failed and the error has been mapped in AX. Grab the extended
608; error and figure out what to do.
609;
610 mov ax,ExtErr
611 cmp al,error_file_exists
612 jz CreateLoop ; file existed => try with new name
613 cmp al,error_access_denied
614 jz CreateLoop ; access denied (attr mismatch)
615
616; CMP AL,error_file_exists ; certain errors cause failure
617; JZ CreateLoop
618; CMP AL,error_access_denied
619; JNZ SETTMPERR ; Error out
620; CMP [EXTERR],error_cannot_make ; See if it's REALLY an att mismatch
621; JNZ CreateLoop ; It was, try again
622; MOV AL,error_cannot_make ; Return this "extended" error
623
624SETTMPERR:
625 STC
626CreateDone:
627 Leave
628 JC CreateFail
629 transfer Sys_Ret_OK ; success!
630CreateFail:
631 transfer Sys_Ret_Err
632EndProc $CreateTempFile
633
634Break <SetAttrib - set the search attrib>
635
636;
637; SetAttrib will set the search attribute (SAttrib) either to the normal
638; (CH) or to the value in CL if the current system call is through
639; serverdoscall.
640;
641; Inputs: fSharing == FALSE => set sattrib to CH
642; fSharing == TRUE => set sattrib to CL
643; Outputs: none
644; Registers changed: CX
645
646procedure SetAttrib,NEAR
647 assume ds:nothing,es:nothing
648 test fSharing,-1
649 jnz Set
650 mov cl,ch
651Set:
652 mov SAttrib,cl
653 return
654EndProc SetAttrib
655
656
657Break <Extended_Open- Extended open the file>
658
659; Input: AL= 0 reserved AH=6CH
660; BX= mode
661; CL= create attribute CH=search attribute (from server)
662; DX= flag
663; DS:SI = file name
664; ES:DI = parm list
665; DD SET EA list (-1) null
666; DW n parameters
667; DB type (TTTTTTLL)
668; DW IOMODE
669; Function: Extended Open
670; Output: carry clear
671; AX= handle
672; CX=1 file opened
673; 2 file created/opened
674; 3 file replaced/opened
675; carry set: AX has error code
676;
677
678
679procedure $Extended_Open,NEAR ;AN000;
680 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
681
682 MOV [XA_from],0 ;AN000;EO. init for set XA
683 MOV [EXTOPEN_FLAG],DX ;AN000;EO. save ext. open flag
684 MOV [EXTOPEN_IO_MODE],0 ;AN000;EO. initialize IO mode
685 TEST DX,reserved_bits_mask ;AN000;EO. reserved bits 0 ?
686 JNZ ext_inval2 ;AN000;EO. no
687 MOV AH,DL ;AN000;EO. make sure flag is right
688 CMP DL,0 ;AN000;EO. all fail ?
689 JZ ext_inval2 ;AN000;EO. yes, error
690 AND DL,exists_mask ;AN000;EO. get exists action byte
691 CMP DL,2 ;AN000;EO, > 02
692 JA ext_inval2 ;AN000;EO. yes ,error
693 AND AH,not_exists_mask ;AN000;EO. get no exists action byte
694 CMP AH,10H ;AN000;EO. > 10
695 JA ext_inval2 ;AN000;EO. yes error
696
697; CMP DI,-1 ;AN000;EO. null parm list
698; JZ no_parm ;AN000;EO. yes
699; ;AN000;EO
700; PUSH CX ;AN000;EO.
701; ;AN000;EO.
702; MOV CX,ES:[DI.EXT_NUM_OF_PARM];AN000;EO. get number of parms
703; OR CX,CX ;AN000;EO. 0 pamrs ?
704; JZ parmend ;AN000;EO. yes
705; PUSH SI ;AN000;EO.
706; PUSH DS ;AN000;EO.
707; MOV SI,DI ;AN000;EO.
708; ADD SI,size EXT_OPEN_PARM ;AN000;EO. position to 1st parm
709; PUSH ES ;AN000;EO.
710; POP DS ;AN000;EO. ds:si -> parm list
711; CALL GetIOParms ;AN000;EO.
712; POP DS ;AN000;EO.
713; POP SI ;AN000;EO.
714;parmend: ;AN000;EO
715; POP CX ;AN000;EO. restore CX
716;no_parm: ;AN000;EO.
717 MOV [SAVE_ES],ES ;AN000;EO. save API parms
718 MOV [SAVE_DI],DI ;AN000;EO.
719 PUSH [EXTOPEN_FLAG] ;AN000;EO.
720 POP [SAVE_DX] ;AN000;EO.
721 MOV [SAVE_CX],CX ;AN000;EO.
722 MOV [SAVE_BX],BX ;AN000;EO.
723 MOV [SAVE_DS],DS ;AN000;EO.
724 MOV [SAVE_SI],SI ;AN000;EO.
725 MOV DX,SI ;AN000;EO. ds:dx points to file name
726 MOV AX,BX ;AN000;EO. ax= mode
727
728; TEST [EXTOPEN_FLAG],no_code_page_check ;AN000;EO. check no code page
729; JNZ no_cdpg_chk ;AN000;;EO. no
730 JMP SHORT goopen2 ;AN000;;EO. do nromal
731ext_inval2: ;AN000;;EO.
732 error error_Invalid_Function ;AN000;EO.. invalid function
733ext_inval_parm: ;AN000;EO..
734 POP CX ;AN000;EO.. pop up satck
735 POP SI ;AN000;EO..
736 error error_Invalid_data ;AN000;EO.. invalid parms
737error_return: ;AN000;EO.
738 ret ;AN000;EO.. return with error
739;no_cdpg_chk: EO.
740; MOV [CPSWFLAG],0 ;AN000;EO.. set CPSW flag off
741goopen2: ;AN000;
742 TEST BX,int_24_error ;AN000;EO.. disable INT 24 error ?
743 JZ goopen ;AN000;EO.. no
744 OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO.. set bit to disable
745
746goopen: ;AN000;
747 OR [EXTOPEN_ON],EXT_OPEN_ON ;AN000;EO.. set Extended Open active
748 AND [EXTOPEN_FLAG],0FFH ;AN000;EO.create new ?
749 CMP [EXTOPEN_FLAG],ext_exists_fail + ext_nexists_create ;AN000;FT.
750 JNZ chknext ;AN000;;EO. no
751 invoke $CreateNewFile ;AN000;;EO. yes
752 JC error_return ;AN000;;EO. error
753 CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS does it
754 JZ ok_return2 ;AN000;;EO. yes
755 MOV [EXTOPEN_FLAG],action_created_opened ;AN000;EO. creted/opened
756 MOV [XA_from],By_Create ;AN000;;EO. for set xa
757 JMP setXAttr ;AN000;;EO. set XAs
758ok_return2:
759 transfer SYS_RET_OK ;AN000;;EO.
760chknext:
761 TEST [EXTOPEN_FLAG],ext_exists_open ;AN000;;EO. exists open
762 JNZ exist_open ;AN000;;EO. yes
763 invoke $Creat ;AN000;;EO. must be replace open
764 JC error_return ;AN000;;EO. return with error
765 CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS does it
766 JZ ok_return2 ;AN000;;EO. yes
767 MOV [EXTOPEN_FLAG],action_created_opened ;AN000;EO. prsume create/open
768 MOV [XA_from],By_Create ;AN000;EO. for set xa
769 TEST [EXTOPEN_ON],ext_file_not_exists ;AN000;;EO. file not exists ?
770 JNZ setXAttr ;AN000;;EO. no
771 MOV [EXTOPEN_FLAG],action_replaced_opened ;AN000;;EO. replaced/opened
772 MOV [XA_from],0 ;AN000;EO. for set xa
773 JMP SHORT setXAttr ;AN000;;EO. set XAs
774error_return2:
775 ret ;AN000;;EO. return with error
776 ;AN000;
777exist_open: ;AN000;
778 test fSharing,-1 ;AN000;;EO. server doscall?
779 jz noserver ;AN000;;EO. no
780 MOV CL,CH ;AN000;;EO. cl=search attribute
781
782noserver:
783 invoke $Open2 ;AN000;;EO. do open
784 JNC ext_ok ;AN000;;EO.
785 CMP [EXTOPEN_ON],0 ;AN000;;EO. error and IFS call
786 JZ error_return2 ;AN000;;EO. return with error
787local_extopen:
788
789 CMP AX,error_file_not_found ;AN000;;EO. file not found error
790 JNZ error_return2 ;AN000;;EO. no,
791 TEST [EXTOPEN_FLAG],ext_nexists_create;AN000;;EO. want to fail
792 JNZ do_creat ;AN000;;EO. yes
793 JMP extexit ;AN000;;EO. yes
794do_creat:
795 MOV [XA_from],By_Create ;AN000;;EO. for set xa
796 MOV CX,[SAVE_CX] ;AN000;;EO. get ds:dx for file name
797 LDS SI,DWORD PTR [SAVE_SI] ;AN000;;EO. cx = attribute
798 MOV DX,SI ;AN000;;EO.
799 invoke $Creat ;AN000;;EO. do create
800 JC extexit ;AN000;;EO. error
801 MOV [EXTOPEN_FLAG],action_created_opened ;AN000;;EO. is created/opened
802 JMP SHORT setXAttr ;AN000;;EO. set XAs
803
804ext_ok:
805 CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS call ?
806 JZ ok_return ;AN000;;EO. yes
807 MOV [EXTOPEN_FLAG],action_opened ;AN000;;EO. opened
808setXAttr:
809; LES DI,DWORD PTR [SAVE_DI] ;AN000;EO.
810 PUSH AX ;AN000;;EO. save handle for final
811; MOV BX,AX ;AN000;;EO. bx= handle
812; MOV AX,04H ;AN000;;EO. set extended attr by handle
813; PUSH DS ;AN000;;EO. save file name addr
814; PUSH DX ;AN000;;EO.
815; CMP DI,-1 ;AN000;;EO. null parm list
816; JZ nosetea ;AN000;;EO. yes
817; CMP WORD PTR ES:[DI],-1 ;AN000;;EO. null set list
818; JZ nosetea ;AN000;;EO. yes
819; LES DI,DWORD PTR ES:[DI] ;AN000;;EO. es:di -> set list
820; invoke $File_times ;AN000;;EO.
821;nosetea: ;AN000; EO
822; POP DX ;AN000;;EO. restore file name addr
823; POP DS ;AN000;;EO.
824; JC extexit2 ;AN000;;EO.
825 invoke get_user_stack ;AN000;;EO.
826 MOV AX,[EXTOPEN_FLAG] ;AN000;;EO.
827 MOV [SI.USER_CX],AX ;AN000;;EO. set action code for cx
828 POP AX ;AN000;;EO.
829 MOV [SI.USER_AX],AX ;AN000;;EO. set handle for ax
830
831ok_return: ;AN000;
832 transfer SYS_RET_OK ;AN000;;EO.
833
834extexit2: ;AN000; ERROR RECOVERY
835
836 POP BX ;AN000;EO. close the handle
837 PUSH AX ;AN000;EO. save error code from set XA
838 CMP [EXTOPEN_FLAG],action_created_opened ;AN000;EO. from create
839 JNZ justopen ;AN000;EO.
840 LDS SI,DWORD PTR [SAVE_SI] ;AN000;EO. cx = attribute
841 LDS DX,DWORD PTR [SI] ;AN000;EO.
842 invoke $UNLINK ;AN000;EO. delete the file
843 JMP SHORT reserror ;AN000;EO.
844
845justopen: ;AN000;
846 invoke $close ;AN000;EO. pretend never happend
847reserror: ;AN000;
848 POP AX ;AN000;EO. retore error code from set XA
849 JMP SHORT extexit ;AN000;EO.
850
851
852ext_file_unfound: ;AN000;
853 MOV AX,error_file_not_found ;AN000;EO.
854 JMP SHORT extexit ;AN000;EO.
855ext_inval: ;AN000;
856 MOV AX,error_invalid_function;AN000;EO.
857extexit:
858 transfer SYS_RET_ERR ;AN000;EO.
859
860EndProc $Extended_Open ;AN000;
861
862
863Break <GetIOParms - get IO parms form extended open parm list>
864
865;
866;
867; Inputs: DS:SI -> IO parm list
868; CX= number of parms
869; Function: get IO parms from parm list
870; Outputs: [EXT_IOMODE]= IO mode parm
871
872;procedure GetIOParms,NEAR
873; assume ds:nothing,es:nothing
874;
875; LODSB ; get parm type ;AN000;
876; CMP AL,0*100B+10B ; have IOMODE ;AN000;
877; JE SET_IOMODE ;AN000;
878; AND AL,00000011B ; decode it ;AN000;
879; JZ SKIP_ASCIIZ ;AN000;
880; DEC AL ;AN000;
881; JZ SKIP_LEN ;AN000;
882;; DEC AL ;AN000;
883; JZ SKIP_WORD ;AN000;
884;SKIP_DWORD: ; copy DWORD parm ;AN000;
885; LODSW ;AN000;
886;SKIP_WORD: ; copy WORD parm ;AN000;
887; LODSW ;AN000;
888; JMP SHORT NEXT_PARM ;AN000;
889;SET_IOMODE: ; copy IOMODE ;AN000;
890; LODSW ;AN000;
891; MOV [EXTOPEN_IO_MODE],AX ;AN000;
892; JMP SHORT NEXT_PARM ;AN000;
893;SKIP_LEN: ; copy LENGTH parm ;AN000;
894; LODSW ;AN000;
895; ADD SI,AX ;AN000;
896; JMP SHORT NEXT_PARM ;AN000;
897;SKIP_ASCIIZ: ; copy ASCIIZ parm ;AN000;
898; LODSB ;AN000;
899; OR AL,AL ;AN000;
900; JNE SKIP_ASCIIZ ;AN000;
901;NEXT_PARM: ;AN000;
902; LOOP GetIOParms ;AN000;
903; return ;AN000;
904;EndProc GetIOParms ;AN000;
905
906
907CODE ENDS
908END
909 \ No newline at end of file
diff --git a/v4.0/src/DOS/FINFO.ASM b/v4.0/src/DOS/FINFO.ASM
new file mode 100644
index 0000000..0df2bc1
--- /dev/null
+++ b/v4.0/src/DOS/FINFO.ASM
@@ -0,0 +1,286 @@
1; SCCSID = @(#)finfo.asm 1.1 85/04/11
2TITLE FILE_INFO - Internal Get/Set File Info routines
3NAME FILE_INFO
4; Low level routines for returning file information and setting file
5; attributes
6;
7; GET_FILE_INFO
8; SET_FILE_ATTRIBUTE
9;
10; Modification history:
11;
12; Created: ARR 30 March 1983
13;
14
15;
16; get the appropriate segment definitions
17;
18.xlist
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xcref
25INCLUDE DOSSYM.INC
26INCLUDE DEVSYM.INC
27include fastxxxx.inc
28include fastopen.inc
29.cref
30.list
31
32Installed = TRUE
33
34 i_need THISCDS,DWORD
35 i_need CURBUF,DWORD
36 i_need NoSetDir,BYTE
37 i_need THISDRV,BYTE
38 I_need EXTERR_CLASS,BYTE
39 I_need EXTERR_ACTION set
40 I_need EXTERR_LOCUS,BYTE
41 i_need DMAADD,DWORD
42 i_need FastOpenFlg,BYTE
43
44SUBTTL GET_FILE_INFO -- Get File Information
45PAGE
46
47; Inputs:
48; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
49; terminated)
50; [CURR_DIR_END] Points to end of Current dir part of string
51; ( = -1 if current dir not involved, else
52; Points to first char after last "/" of current dir part)
53; [THISCDS] Points to CDS being used
54; (Low word = -1 if NUL CDS (Net direct request))
55; [SATTRIB] Is attribute of search, determines what files can be found
56; Function:
57; Get Information about a file
58; Returns:
59; CARRY CLEAR
60; AX = Attribute of file
61; CX = Time stamp of file
62; DX = Date stamp of file
63; BX:DI = Size of file (32 bit)
64; CARRY SET
65; AX is error code
66; error_file_not_found
67; Last element of path not found
68; error_path_not_found
69; Bad path (not in curr dir part if present)
70; error_bad_curr_dir
71; Bad path in current directory part of path
72; DS preserved, others destroyed
73
74 procedure GET_FILE_INFO,NEAR
75 DOSAssume CS,<DS>,"Get_File_Info"
76 ASSUME ES:NOTHING
77
78 Invoke TestNet
79 JNC Local_Info
80; invoke OWN_SHARE2 ;IFS. IFS owns share ? ;AN000;
81; JZ ifsshare ;IFS. yes ;AN000;
82; PUSH WORD PTR [DMAADD+2] ;IFS. save DMAADD ;AN000;
83; PUSH WORD PTR [DMAADD] ;IFS. ;AN000;
84; invoke IFS_SEARCH_FIRST ;IFS. do search first ;AN000;
85; JC nofiles ;IFS. file not existing ;AN000;
86delete_next_file: ;IFS. ;AN000;
87; invoke IFS_REN_DEL_CHECK ;IFS. do REN_DEL_CHECK ;AN000;
88; JNC share_okok ;IFS. share ok ;AN000;
89; MOV AX,error_sharing_violation ;IFS. share violation ;AN000;
90; JMP SHORT nofiles ;IFS. ;AN000;
91share_okok:
92; POP WORD PTR [DMAADD] ;IFS. retor DMAADD ;AN000;
93; POP WORD PTR [DMAADD+2] ;IFS. ;AN000;
94ifsshare:
95IF NOT Installed
96 transfer NET_GET_FILE_INFO
97ELSE
98 MOV AX,(multNET SHL 8) OR 15
99 INT 2FH
100 return
101ENDIF
102nofiles:
103; POP WORD PTR [DMAADD] ;IFS. retor DMAADD ;AN000;
104; POP WORD PTR [DMAADD+2] ;IFS. ;AN000;
105; ret ;IFS. return
106
107LOCAL_INFO:
108 EnterCrit critDisk
109 MOV [NoSetDir],1 ; if we find a dir, don't change to it
110 invoke Get_FAST_PATH
111info_check:
112 JNC info_check_dev
113
114NO_PATH:
115 DOSAssume CS,<DS>,"FINFO/No_Path"
116 ASSUME ES:NOTHING
117
118 JNZ bad_path
119 OR CL,CL
120 JZ bad_path
121info_no_file:
122 MOV AX,error_file_not_found
123BadRet:
124 STC
125justRet:
126 LeaveCrit critDisk
127 return
128
129bad_path:
130 MOV AX,error_path_not_found
131 jmp BadRet
132
133info_check_dev:
134 OR AH,AH
135 JS info_no_file ; device
136 PUSH DS
137 MOV DS,WORD PTR [CURBUF+2]
138ASSUME DS:NOTHING
139 MOV SI,BX
140 XOR BX,BX ; Assume size=0 (dir)
141 MOV DI,BX
142 MOV CX,[SI.dir_time]
143 MOV DX,[SI.dir_date]
144 XOR AH,AH
145 MOV AL,[SI.dir_attr]
146 TEST AL,attr_directory
147 JNZ NO_SIZE
148 MOV DI,[SI.dir_size_l]
149 MOV BX,[SI.dir_size_h]
150NO_SIZE:
151 POP DS
152 CLC
153 jmp JustRet
154EndProc GET_FILE_INFO
155
156Break <SET_FILE_ATTRIBUTE -- Set File Attribute>
157
158; Inputs:
159; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
160; terminated)
161; [CURR_DIR_END] Points to end of Current dir part of string
162; ( = -1 if current dir not involved, else
163; Points to first char after last "/" of current dir part)
164; [THISCDS] Points to CDS being used
165; (Low word = -1 if NUL CDS (Net direct request))
166; [SATTRIB] is attribute of search (determines what files may be found)
167; AX is new attributes to give to file
168; Function:
169; Set File Attributes
170; Returns:
171; CARRY CLEAR
172; No error
173; CARRY SET
174; AX is error code
175; error_file_not_found
176; Last element of path not found
177; error_path_not_found
178; Bad path (not in curr dir part if present)
179; error_bad_curr_dir
180; Bad path in current directory part of path
181; error_access_denied
182; Attempt to set an attribute which cannot be set
183; (attr_directory, attr_volume_ID)
184; error_sharing_violation
185; Sharing mode of file did not allow the change
186; (this request requires exclusive write/read access)
187; (INT 24H generated)
188; DS preserved, others destroyed
189
190 procedure SET_FILE_ATTRIBUTE,NEAR
191 DOSAssume CS,<DS>,"Set_File_Attribute"
192 ASSUME ES:NOTHING
193
194 TEST AX,NOT attr_changeable
195 JZ set_look
196BAD_ACC:
197 MOV ExtErr_Locus,errLoc_UNK
198 MOV ExtErr_Class,errClass_Apperr
199 MOV ExtErr_Action,errAct_Abort
200 MOV AX,error_access_denied
201 STC
202 return
203
204set_look:
205 Invoke TestNet
206 JNC Local_Set
207
208IF NOT Installed
209 transfer NET_SEQ_SET_FILE_ATTRIBUTE
210ELSE
211 PUSH AX
212 MOV AX,(multNET SHL 8) OR 14
213 INT 2FH
214 POP BX ; clean stack
215 return
216ENDIF
217
218LOCAL_SET:
219 EnterCrit critDisk
220 PUSH AX ; Save new attributes
221 MOV [NoSetDir],1 ; if we find a dir, don't change to it
222 invoke GetPath ; get path through fastopen if there ;AC000;
223 JNC set_check_device
224 POP BX ; Clean stack (don't zap AX)
225 JMP NO_PATH
226
227set_check_device:
228 OR AH,AH
229 JNS set_check_share
230 POP AX
231 LeaveCrit critDisk
232 JMP BAD_ACC ; device
233
234set_check_share:
235 POP AX ; Get new attributes
236 invoke REN_DEL_Check
237 JNC set_do
238 MOV AX,error_sharing_violation
239 jmp short ok_bye
240
241set_do:
242 LES DI,[CURBUF]
243 AND BYTE PTR ES:[BX].dir_attr,NOT attr_changeable
244 OR BYTE PTR ES:[BX].dir_attr,AL
245
246 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
247 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
248 invoke INC_DIRTY_COUNT ;LB. ;AN000;
249 OR ES:[DI.buf_flags],buf_dirty
250yesdirty:
251 MOV AL,[THISDRV]
252;;;; 10/1/86 F.C update fastopen cache
253 PUSH DX
254 PUSH DI
255 MOV AH,0 ; dir entry update
256 MOV DL,AL ; drive number A=0,B=1,,
257 MOV DI,BX ; ES:DI -> dir entry
258 invoke FastOpen_Update
259 POP DI
260 POP DX
261;;;; 9/11/86 F.C update fastopen cache
262 invoke FlushBuf
263 JNC OK_BYE
264 MOV AX,error_file_not_found
265OK_BYE:
266 LeaveCrit critDisk
267 return
268
269EndProc SET_FILE_ATTRIBUTE
270
271
272
273 procedure GET_FAST_PATH,NEAR
274 ASSUME DS:NOTHING,ES:NOTHING
275
276 OR [FastOpenFlg],FastOpen_Set ;FO. trigger fastopen ;AN000;
277 invoke GetPath
278 PUSHF ;FO. ;AN000;
279 AND [FastOpenFlg],Fast_yes ;FO. clear all fastopen flags ;AN000;
280 POPF ;FO. ;AN000;
281 return
282
283EndProc GET_FAST_PATH
284
285CODE ENDS
286 END
diff --git a/v4.0/src/DOS/GETSET.ASM b/v4.0/src/DOS/GETSET.ASM
new file mode 100644
index 0000000..70c8cd3
--- /dev/null
+++ b/v4.0/src/DOS/GETSET.ASM
@@ -0,0 +1,912 @@
1; SCCSID = @(#)getset.asm 1.2 85/07/23
2TITLE GETSET - GETting and SETting MS-DOS system calls
3NAME GETSET
4;
5; System Calls which get and set various things
6;
7; $GET_VERSION
8; $GET_VERIFY_ON_WRITE
9; $SET_VERIFY_ON_WRITE
10; $INTERNATIONAL
11; $GET_DRIVE_FREESPACE
12; $GET_DMA
13; $SET_DMA
14; $GET_DEFAULT_DRIVE
15; $SET_DEFAULT_DRIVE
16; $GET_INTERRUPT_VECTOR
17; $SET_INTERRUPT_VECTOR
18; RECSET
19; $CHAR_OPER
20; $GetExtendedError DOS 3.3
21; Get_Global_CdPg DOS 4.0
22; $ECS_CALL DOS 4.0
23;
24; Revision history:
25;
26; Created: ARR 30 March 1983
27;
28; A000 version 4.0 Jan. 1988
29; A006 D503-- fake version for IBMCACHE
30; A008 P4070- faske version for MS WINDOWS
31
32.xlist
33;
34; get the appropriate segment definitions
35;
36include dosseg.asm
37
38IFNDEF ALTVECT
39ALTVECT EQU 0 ; FALSE
40ENDIF
41
42CODE SEGMENT BYTE PUBLIC 'CODE'
43 ASSUME SS:DOSGROUP,CS:DOSGROUP
44
45.xcref
46include dossym.inc
47include devsym.inc
48include doscntry.inc
49.cref
50.list
51
52 i_need USERNUM,WORD
53 i_need MSVERS,WORD
54 i_need VERFLG,BYTE
55 i_need CNTCFLAG,BYTE
56 i_need DMAADD,DWORD
57 i_need CURDRV,BYTE
58 i_need chSwitch,BYTE
59 i_need COUNTRY_CDPG,byte ;DOS 3.3
60 I_need CDSCount,BYTE
61 I_need ThisCDS,DWORD
62 i_need EXTERR,WORD
63 i_need EXTERR_ACTION,BYTE
64 i_need EXTERR_CLASS,BYTE
65 i_need EXTERR_LOCUS,BYTE
66 i_need EXTERRPT,DWORD
67 i_need UCASE_TAB,BYTE
68 i_need FILE_UCASE_TAB,BYTE
69 i_need InterCon,BYTE
70 i_need CURRENTPDB,WORD
71 i_need DBCS_TAB,BYTE ;AN000;
72 i_need Special_version,WORD ;AN006;
73 i_need Fake_Count,BYTE ;AN008;
74 i_need NLS_YES,BYTE ;AN000;
75 i_need NLS_yes2,BYTE ;AN000;
76 i_need NLS_NO,BYTE ;AN000;
77 i_need NLS_no2,BYTE ;AN000;
78
79
80BREAK <$Get_Version -- Return DOS version number>
81 procedure $GET_VERSION,NEAR
82ASSUME DS:NOTHING,ES:NOTHING
83
84; Inputs:
85; None
86; Function:
87; Return DOS version number
88; Outputs:
89; OEM number in BH
90; User number in BL:CX (24 bits)
91; Version number as AL.AH in binary
92; NOTE: On pre 1.28 DOSs AL will be zero
93
94 context DS
95 MOV BX,[USERNUM + 2]
96 MOV CX,[USERNUM]
97 MOV AX,[MSVERS]
98 invoke get_user_stack
99ASSUME DS:NOTHING
100 MOV [SI.user_BX],BX
101 MOV [SI.user_CX],CX
102 CMP CS:[Fake_Count],0FFH ;AN008;
103 JZ reg ;AN008;
104 CMP CS:[Fake_Count],0 ;AN008;
105 JZ usual ;AN008;
106 DEC CS:[Fake_Count] ;AN008;
107reg: ;AN008;
108 CMP CS:[Special_version],0 ;AN006;
109 JZ usual ;AN006;
110 MOV AX,CS:[Special_version] ;AN006;
111usual: ;AN006;
112 MOV [SI.user_AX],AX ; Really only sets AH
113 return
114EndProc $GET_VERSION
115
116BREAK <$Get_Verify_on_Write - return verify-after-write flag>
117 procedure $GET_VERIFY_ON_WRITE,NEAR
118ASSUME DS:NOTHING,ES:NOTHING
119
120; Inputs:
121; none.
122; Function:
123; returns flag
124; Returns:
125; AL = value of VERIFY flag
126
127 MOV AL,[VERFLG]
128 return
129EndProc $GET_VERIFY_ON_WRITE
130
131BREAK <$Set_Verify_on_Write - Toggle verify-after-write flag>
132 procedure $SET_VERIFY_ON_WRITE,NEAR
133ASSUME DS:NOTHING,ES:NOTHING
134
135; Inputs:
136; AL = desired value of VERIFY flag
137; Function:
138; Sets flag
139; Returns:
140; None
141
142 AND AL,1
143 MOV [VERFLG],AL
144 return
145EndProc $SET_VERIFY_ON_WRITE
146
147BREAK <$International - return country-dependent information>
148;
149; Inputs:
150; MOV AH,International
151; MOV AL,country (al = 0 => current country)
152; [MOV BX,country]
153; LDS DX,block
154; INT 21
155; Function:
156; give users an idea of what country the application is running
157; Outputs:
158; IF DX != -1 on input (get country)
159; AL = 0 means return current country table.
160; 0<AL<0FFH means return country table for country AL
161; AL = 0FF means return country table for country BX
162; No Carry:
163; Register BX will contain the 16-bit country code.
164; Register AL will contain the low 8 bits of the country code.
165; The block pointed to by DS:DX is filled in with the information
166; for the particular country.
167; BYTE Size of this table excluding this byte and the next
168; BYTE Country code represented by this table
169; A sequence of n bytes, where n is the number specified
170; by the first byte above and is not > internat_block_max,
171; in the correct order for being returned by the
172; INTERNATIONAL call as follows:
173; WORD Date format 0=mdy, 1=dmy, 2=ymd
174; 5 BYTE Currency symbol null terminated
175; 2 BYTE thousands separator null terminated
176; 2 BYTE Decimal point null terminated
177; 2 BYTE Date separator null terminated
178; 2 BYTE Time separator null terminated
179; 1 BYTE Bit field. Currency format.
180; Bit 0. =0 $ before # =1 $ after #
181; Bit 1. no. of spaces between # and $ (0 or 1)
182; 1 BYTE No. of significant decimal digits in currency
183; 1 BYTE Bit field. Time format.
184; Bit 0. =0 12 hour clock =1 24 hour
185; DWORD Call address of case conversion routine
186; 2 BYTE Data list separator null terminated.
187; Carry:
188; Register AX has the error code.
189; IF DX = -1 on input (set current country)
190; AL = 0 is an error
191; 0<AL<0FFH means set current country to country AL
192; AL = 0FF means set current country to country BX
193; No Carry:
194; Current country SET
195; Register AL will contain the low 8 bits of the country code.
196; Carry:
197; Register AX has the error code.
198
199
200 procedure $INTERNATIONAL,NEAR ; DOS 3.3
201ASSUME DS:NOTHING,ES:NOTHING
202 CMP AL,0FFH
203 JZ BX_HAS_CODE ; -1 means country code is in BX
204 MOV BL,AL ; Put AL country code in BX
205 XOR BH,BH
206BX_HAS_CODE:
207 PUSH DS
208 POP ES
209 PUSH DX
210 POP DI ; User buffer to ES:DI
211 context DS
212 CMP DI,-1
213 JZ international_set
214 OR BX,BX
215 JNZ international_find
216 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG
217 JMP SHORT international_copy
218
219international_find:
220 MOV BP,0 ; flag it for GetCntry only
221 CALL international_get
222 JC errtn
223 CMP BX,0 ; nlsfunc finished it ?
224 JNZ SHORT international_copy ; no, copy by myself
225 MOV BX,DX ; put country back
226 JMP SHORT international_ok3
227
228international_get:
229 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG
230 CMP BX,[SI.ccDosCountry] ; = current country id
231 retz ; return if equal
232 MOV DX,BX
233 XOR BX,BX ; bx = 0, default code page
234 CallInstall NLSInstall,NLSFUNC,0 ; check if NLSFUNC in memory
235 CMP AL,0FFH
236 JNZ interr ; not in memory
237 CMP BP,0 ; GetCntry ?
238 JNZ stcdpg
239 CallInstall GetCntry,NLSFUNC,4 ; get country info
240 JMP chkok
241stcdpg:
242 CallInstall SetCodePage,NLSFUNC,3 ; set country info
243chkok:
244 CMP AL,0 ; success ?
245 retz ; yes
246setcarry:
247 STC ; set carry
248 ret
249interr:
250 MOV AL,0FFH ; flag nlsfunc error
251 JMP setcarry
252
253international_copy:
254 MOV BX,[SI.ccDosCountry] ; = current country id
255 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG.ccDFormat
256 MOV CX,OLD_COUNTRY_SIZE
257 REP MOVSB ;copy country info
258international_ok3:
259 invoke get_user_stack
260ASSUME DS:NOTHING
261 MOV [SI.user_BX],BX
262international_ok:
263 MOV AX,BX ; Return country code in AX too.
264 transfer SYS_RET_OK
265
266international_set:
267ASSUME DS:DOSGROUP
268 MOV BP,1 ; flag it for SetCodePage only
269 CALL international_get
270 JNC international_ok
271errtn:
272 CMP AL,0FFH
273 JZ errtn2
274 transfer SYS_RET_ERR ; return what we got from NLSFUNC
275errtn2:
276 error error_Invalid_Function ; NLSFUNC not existent
277
278
279EndProc $INTERNATIONAL
280
281
282
283BREAK <$GetExtCntry - return extended country-dependent information>
284;
285; Inputs:
286; if AL >= 20H
287; AL= 20H capitalize single char, DL= char
288; 21H capitalize string ,CX= string length
289; 22H capitalize ASCIIZ string
290; 23H YES/NO check, DL=1st char DH= 2nd char (DBCS)
291; 80H bit 0 = use normal upper case table
292; 1 = use file upper case table
293; DS:DX points to string
294;
295; else
296;
297; MOV AH,GetExtCntry ; DOS 3.3
298; MOV AL,INFO_ID ( info type,-1 selects all)
299; MOV BX,CODE_PAGE ( -1 = active code page )
300; MOV DX,COUNTRY_ID ( -1 = active country )
301; MOV CX,SIZE ( amount of data to return)
302; LES DI,COUNTRY_INFO ( buffer for returned data )
303; INT 21
304; Function:
305; give users extended country dependent information
306; or capitalize chars
307; Outputs:
308; No Carry:
309; extended country info is succesfully returned
310; Carry:
311; Register AX has the error code.
312; AX=0, NO for YES/NO CHECK
313; 1, YES
314
315
316 procedure $GetExtCntry,NEAR ; DOS 3.3
317ASSUME DS:NOTHING,ES:NOTHING
318 CMP AL,CAP_ONE_CHAR ;AN000;MS. < 20H ?
319 JAE capcap ;AN000;MS.
320 JMP notcap ;AN000;MS. yes
321capcap: ;AN000;
322 TEST AL,UPPER_TABLE ;AN000;MS. which upper case table
323 JNZ fileupper ;AN000;MS. file upper case
324 MOV BX,OFFSET DOSGROUP:UCASE_TAB+2 ;AN000;MS. get normal upper case
325 JMP SHORT capit ;AN000;MS.
326fileupper: ;AN000;
327 MOV BX,OFFSET DOSGROUP:FILE_UCASE_TAB+2;AN000;MS. get file upper case
328capit: ;AN000;
329 CMP AL,CAP_ONE_CHAR ;AN000;;MS.cap one char ?
330 JNZ chkyes ;AN000;;MS. no
331 MOV AL,DL ;AN000;;MS. set up AL
332 invoke GETLET3 ;AN000;;MS. upper case it
333 invoke get_user_stack ;AN000;;MS. get user stack
334 MOV byte ptr [SI.user_DX],AL;AN000;;MS. user's DL=AL
335 JMP SHORT nono ;AN000;;MS. done
336chkyes: ;AN000;
337 CMP AL,CHECK_YES_NO ;AN000;;MS. check YES or NO ?
338 JNZ capstring ;AN000;;MS. no
339 XOR AX,AX ;AN000;;MS. presume NO
340IF DBCS ;AN000;
341 PUSH AX ;AN000;;MS.
342 MOV AL,DL ;AN000;;MS.
343 invoke TESTKANJ ;AN000;;MS. DBCS ?
344 POP AX ;AN000;;MS.
345 JNZ dbcs_char ;AN000;;MS. yes, return error
346ENDIF ;AN000;
347 ;AN000;
348 CMP DL,NLS_YES ;AN000;;MS. is 'Y' ?
349 JZ yesyes ;AN000;;MS. yes
350 CMP DL,NLS_yes2 ;AN000;;MS. is 'y' ?
351 JZ yesyes ;AN000;;MS. yes
352 CMP DL,NLS_NO ;AN000;;MS. is 'N'?
353 JZ nono ;AN000;;MS. no
354 CMP DL,NLS_no2 ;AN000;;MS. is 'n' ?
355 JZ nono ;AN000;;MS. no
356dbcs_char: ;AN000;
357 INC AX ;AN000;;MS. not YES or NO
358yesyes: ;AN000'
359 INC AX ;AN000;;MS. return 1
360nono: ;AN000;
361 transfer SYS_RET_OK ;AN000;;MS. done
362capstring: ;AN000;
363 MOV SI,DX ;AN000;;MS. si=dx
364 CMP AL,CAP_STRING ;AN000;;MS. cap string ?
365 JNZ capascii ;AN000;;MS. no
366 CMP CX,0 ;AN000;;MS. check count 0
367 JZ nono ;AN000;;MS. yes finished
368concap: ;AN000;
369 LODSB ;AN000;;MS. get char
370 IF DBCS ;AN000;;MS.
371 invoke TESTKANJ ;AN000;;MS. DBCS ?
372 JZ notdbcs ;AN000;;MS. no
373 INC SI ;AN000;;MS. skip 2 chars
374 DEC CX ;AN000;;MS. bad input, one DBCS char at end
375 JZ nono ;AN000;;MS. yes
376 JMP SHORT next99 ;AN000;;MS.
377notdbcs: ;AN000;
378 ENDIF ;AN000;
379
380 invoke GETLET3 ;AN000;;MS. upper case it
381 MOV byte ptr [SI-1],AL ;AN000;;MS. store back
382next99: ;AN000;
383 LOOP concap ;AN000;;MS. continue
384 JMP nono ;AN000;;MS. done
385capascii: ;AN000;
386 CMP AL,CAP_ASCIIZ ;AN000;;MS. cap ASCIIZ string ?
387 JNZ capinval ;AN000;;MS. no
388concap2: ;AN000;
389 LODSB ;AN000;;MS. get char
390 CMP AL,0 ;AN000;;MS. end of string ?
391 JZ nono ;AN000;;MS. yes
392 IF DBCS ;AN000;;MS.
393 invoke TESTKANJ ;AN000;;MS. DBCS ?
394 JZ notdbcs2 ;AN000;;MS. no
395 CMP BYTE PTR [SI],0 ;AN000;;MS. bad input, one DBCS char at end
396 JZ nono ;AN000;;MS. yes
397 INC SI ;AN000;;MS. skip 2 chars
398 JMP concap2 ;AN000;;MS.
399notdbcs2: ;AN000;
400 ENDIF ;AN000;
401 invoke GETLET3 ;AN000;;MS. upper case it
402 MOV byte ptr [SI-1],AL ;AN000;;MS. store back
403 JMP concap2 ;AN000;;MS. continue
404
405
406notcap:
407 CMP CX,5 ; minimum size is 5
408 JB sizeerror
409 context DS
410 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG
411 CMP DX,-1 ; active country ?
412 JNZ GETCDPG ; no
413 MOV DX,[SI.ccDosCountry] ; get active country id
414GETCDPG:
415 CMP BX,-1 ; active code page?
416 JNZ CHKAGAIN ; no, check again
417 MOV BX,[SI.ccDosCodePage] ; get active code page id
418CHKAGAIN:
419 CMP DX,[SI.ccDosCountry] ; same as active country id?
420 JNZ CHKNLS ; no
421 CMP BX,[SI.ccDosCodePage] ; same as active code page id?
422 JNZ CHKNLS ; no
423CHKTYPE:
424 MOV BX,[SI.ccSysCodePage] ; bx = sys code page id
425; CMP AL,SetALL ; select all?
426; JNZ SELONE
427; MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG.ccNumber_of_entries
428SELONE:
429 PUSH CX ; save cx
430 MOV CX,[SI.ccNumber_of_entries]
431 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG.ccSetUcase
432NXTENTRY:
433 CMP AL,[SI] ; compare info type
434 JZ FOUNDIT
435 ADD SI,5 ; next entry
436 LOOP NXTENTRY
437 POP CX
438capinval:
439 error error_Invalid_Function ; info type not found
440FOUNDIT:
441 MOVSB ; move info id byte
442 POP CX ; retsore char count
443 CMP AL,SetCountryInfo ; select country info type ?
444 JZ setsize
445 MOV CX,4 ; 4 bytes will be moved
446 MOV AX,5 ; 5 bytes will be returned in CX
447OK_RETN:
448 REP MOVSB ; copy info
449 MOV CX,AX ; CX = actual length returned
450 MOV AX,BX ; return sys code page in ax
451GETDONE:
452 invoke get_user_stack ; return actual length to user's CX
453 MOV [SI.user_CX],CX
454 transfer SYS_RET_OK
455setsize:
456 SUB CX,3 ; size after length field
457 CMP WORD PTR [SI],CX ; less than table size
458 JAE setsize2 ; no
459 MOV CX,WORD PTR [SI] ; truncate to table size
460setsize2:
461 MOV ES:[DI],CX ; copy actual length to user's
462 ADD DI,2 ; update index
463 ADD SI,2
464 MOV AX,CX
465 ADD AX,3 ; AX has the actual length
466 JMP OK_RETN ; go move it
467CHKNLS:
468 XOR AH,AH
469 PUSH AX ; save info type
470 POP BP ; bp = info type
471 CallInstall NLSInstall,NLSFUNC,0 ; check if NLSFUNC in memory
472 CMP AL,0FFH
473 JZ NLSNXT ; in memory
474sizeerror:
475 error error_Invalid_Function
476NLSNXT: CallInstall GetExtInfo,NLSFUNC,2 ;get extended info
477 CMP AL,0 ; success ?
478 JNZ NLSERROR
479 MOV AX,[SI.ccSysCodePage] ; ax = sys code page id
480 JMP GETDONE
481NLSERROR:
482 transfer SYS_RET_ERR ; return what is got from NLSFUNC
483
484EndProc $GetExtCntry
485
486BREAK <$GetSetCdPg - get or set global code page>
487;
488; Inputs:
489; MOV AH,GetSetCdPg ; DOS 3.3
490; MOV AL,n ; n = 1 : get code page, n = 2 : set code page
491; MOV BX,CODE_PAGE ( set code page only)
492; INT 21
493; Function:
494; get or set the global code page
495; Outputs:
496; No Carry:
497; global code page is set (set global code page)
498; BX = active code page id (get global code page)
499; DX = system code page id (get global code page)
500; Carry:
501; Register AX has the error code.
502
503
504 procedure $GetSetCdPg,NEAR ; DOS 3.3
505ASSUME DS:NOTHING,ES:NOTHING
506 context DS
507 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG
508 CMP AL,1 ; get global code page
509 JNZ setglpg ; set global cod epage
510 MOV BX,[SI.ccDosCodePage] ; get active code page id
511 MOV DX,[SI.ccSysCodePage] ; get sys code page id
512 invoke get_user_stack
513ASSUME DS:NOTHING
514 MOV [SI.user_BX],BX ; update returned bx
515 MOV [SI.user_DX],DX ; update returned dx
516OK_RETURN:
517 transfer SYS_RET_OK
518ASSUME DS:DOSGROUP
519setglpg:
520 CMP AL,2
521 JNZ nomem
522;;;;;;; CMP BX,[SI.ccDosCodePage] ; same as active code page
523;;;;;;; JZ OK_RETURN ; yes
524 MOV DX,[SI.ccDosCountry]
525 CallInstall NLSInstall,NLSFUNC,0 ; check if NLSFUNC in memory
526 CMP AL,0FFH
527 JNZ nomem ; not in memory
528 CallInstall SetCodePage,NLSFUNC,1 ;set the code page
529 CMP AL,0 ; success ?
530 JZ OK_RETURN ; yes
531 CMP AL,65 ; set device code page failed
532 JNZ seterr
533 MOV AX,65
534 MOV [EXTERR],AX
535 MOV [EXTERR_ACTION],errACT_Ignore
536 MOV [EXTERR_CLASS],errCLASS_HrdFail
537 MOV [EXTERR_LOCUS],errLOC_SerDev
538 transfer From_GetSet
539
540seterr:
541 transfer SYS_RET_ERR
542nomem:
543 error error_Invalid_Function ; function not defined
544;
545EndProc $GetSetCdPg
546
547
548
549
550BREAK <$Get_Drive_Freespace -- Return bytes of free disk space on a drive>
551 procedure $GET_DRIVE_FREESPACE,NEAR
552ASSUME DS:NOTHING,ES:NOTHING
553
554; Inputs:
555; DL = Drive number
556; Function:
557; Return number of free allocation units on drive
558; Outputs:
559; BX = Number of free allocation units
560; DX = Total Number of allocation units on disk
561; CX = Sector size
562; AX = Sectors per allocation unit
563; = -1 if bad drive specified
564; This call returns the same info in the same registers (except for FAT pointer)
565; as the old FAT pointer calls
566
567 context DS
568 MOV AL,DL
569 invoke GetThisDrv ; Get drive
570SET_AX_RET:
571 JC BADFDRV
572 invoke DISK_INFO
573 XCHG DX,BX
574 JC SET_AX_RET ; User FAILed to I 24
575 XOR AH,AH ; Chuck Fat ID byte
576DoSt:
577 invoke get_user_stack
578ASSUME DS:NOTHING
579 MOV [SI.user_DX],DX
580 MOV [SI.user_CX],CX
581 MOV [SI.user_BX],BX
582 MOV [SI.user_AX],AX
583 return
584BADFDRV:
585; MOV AL,error_invalid_drive ; Assume error
586 invoke FCB_RET_ERR
587 MOV AX,-1
588 JMP DoSt
589EndProc $GET_DRIVE_FREESPACE
590
591BREAK <$Get_DMA, $Set_DMA -- Get/Set current DMA address>
592 procedure $GET_DMA,NEAR
593ASSUME DS:NOTHING,ES:NOTHING
594
595; Inputs:
596; None
597; Function:
598; Get DISK TRANSFER ADDRESS
599; Returns:
600; ES:BX is current transfer address
601
602 MOV BX,WORD PTR [DMAADD]
603 MOV CX,WORD PTR [DMAADD+2]
604 invoke get_user_stack
605 MOV [SI.user_BX],BX
606 MOV [SI.user_ES],CX
607 return
608EndProc $GET_DMA
609
610 procedure $SET_DMA,NEAR
611ASSUME DS:NOTHING,ES:NOTHING
612
613; Inputs:
614; DS:DX is desired new disk transfer address
615; Function:
616; Set DISK TRANSFER ADDRESS
617; Returns:
618; None
619
620 MOV WORD PTR [DMAADD],DX
621 MOV WORD PTR [DMAADD+2],DS
622 return
623EndProc $SET_DMA
624
625BREAK <$Get_Default_Drive, $Set_Default_Drive -- Set/Get default drive>
626 procedure $GET_DEFAULT_DRIVE,NEAR
627ASSUME DS:NOTHING,ES:NOTHING
628
629; Inputs:
630; None
631; Function:
632; Return current drive number
633; Returns:
634; AL = drive number
635
636 MOV AL,[CURDRV]
637 return
638EndProc $GET_DEFAULT_DRIVE
639
640 procedure $SET_DEFAULT_DRIVE,NEAR
641ASSUME DS:NOTHING,ES:NOTHING
642
643; Inputs:
644; DL = Drive number for new default drive
645; Function:
646; Set the default drive
647; Returns:
648; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD
649
650 MOV AL,DL
651 INC AL ; A=1, b=2...
652 invoke GetVisDrv ; see if visible drive
653 JC SETRET ; errors do not set
654; LDS SI,ThisCDS ; get CDS
655; TEST [SI].curdir_flags,curdir_splice ; was it spliced?
656; JNZ SetRet ; yes, do not set
657 MOV [CURDRV],AL ; no, set
658SETRET:
659 MOV AL,[CDSCOUNT] ; let user see what the count really is
660RET17: return
661EndProc $SET_DEFAULT_DRIVE
662
663BREAK <$Get_Interrupt_Vector - Get/Set interrupt vectors>
664 procedure $GET_INTERRUPT_VECTOR,NEAR
665ASSUME DS:NOTHING,ES:NOTHING
666
667; Inputs:
668; AL = interrupt number
669; Function:
670; Get the interrupt vector
671; Returns:
672; ES:BX is current interrupt vector
673
674 CALL RECSET
675 LES BX,DWORD PTR ES:[BX]
676 invoke get_user_stack
677 MOV [SI.user_BX],BX
678 MOV [SI.user_ES],ES
679 return
680EndProc $GET_INTERRUPT_VECTOR
681
682 procedure $SET_INTERRUPT_VECTOR,NEAR
683ASSUME DS:NOTHING,ES:NOTHING
684
685; Inputs:
686; AL = interrupt number
687; DS:DX is desired new interrupt vector
688; Function:
689; Set the interrupt vector
690; Returns:
691; None
692
693 CALL RECSET
694 CLI ; Watch out!!!!! Folks sometimes use
695 MOV ES:[BX],DX ; this for hardware ints (like timer).
696 MOV ES:[BX+2],DS
697 STI
698 return
699EndProc $SET_INTERRUPT_VECTOR
700
701 IF ALTVECT
702TABLE SEGMENT
703VECIN:
704; INPUT VECTORS
705Public GSET001S,GSET001E
706GSET001S label byte
707 DB 22H ; Terminate
708 DB 23H ; ^C
709 DB 24H ; Hard error
710 DB 28H ; Spooler
711LSTVEC DB ? ; ALL OTHER
712
713VECOUT:
714; GET MAPPED VECTOR
715 DB int_terminate
716 DB int_ctrl_c
717 DB int_fatal_abort
718 DB int_spooler
719LSTVEC2 DB ? ; Map to itself
720
721NUMVEC = VECOUT-VECIN
722GSET001E label byte
723TABLE ENDS
724 ENDIF
725
726procedure RECSET,NEAR
727
728 IF ALTVECT
729 context ES
730 MOV [LSTVEC],AL ; Terminate list with real vector
731 MOV [LSTVEC2],AL ; Terminate list with real vector
732 MOV CX,NUMVEC ; Number of possible translations
733 MOV DI,OFFSET DOSGROUP:VECIN ; Point to vectors
734 REPNE SCASB
735 MOV AL,ES:[DI+NUMVEC-1] ; Get translation
736 ENDIF
737
738 XOR BX,BX
739 MOV ES,BX
740 MOV BL,AL
741 SHL BX,1
742 SHL BX,1
743 return
744EndProc recset
745
746BREAK <$Char_Oper - hack on paths, switches so that xenix can look like PCDOS>
747;
748; input: AL = function:
749; 0 - read switch char
750; 1 - set switch char (char in DL)
751; 2 - read device availability
752; Always returns available
753; 3 - set device availability
754; No longer supported (NOP)
755; output: (get) DL - character/flag
756;
757 procedure $CHAR_OPER,NEAR
758 ASSUME DS:NOTHING,ES:NOTHING
759 context DS
760 CMP AL,1
761 JB CharGetSw
762 JZ CharSetSw
763 CMP AL,3
764 JB CharGetDev
765 JZ CharSetDev
766 MOV AL,-1
767 return
768CharGetSw:
769 MOV DL,chSwitch
770 JMP SHORT CharSet
771CharSetSw:
772 MOV chSwitch,DL
773 return
774CharGetDev:
775 MOV DL,-1
776CharSet:
777 Invoke Get_User_Stack
778 ASSUME DS:NOTHING
779 MOV [SI.User_DX],DX
780CharSetDev:
781 return
782EndProc $CHAR_OPER
783
784BREAK <$GetExtendedError - Return Extended DOS error code>
785;
786; input: None
787; output: AX = Extended error code (0 means no extended error)
788; BL = recommended action
789; BH = class of error
790; CH = locus of error
791; ES:DI = may be pointer
792;
793 procedure $GetExtendedError,NEAR
794 ASSUME DS:NOTHING,ES:NOTHING
795 Context DS
796 MOV AX,[EXTERR]
797 LES DI,[EXTERRPT]
798 MOV BX,WORD PTR [EXTERR_ACTION] ; BL = Action, BH = Class
799 MOV CH,[EXTERR_LOCUS]
800 invoke get_user_stack
801ASSUME DS:NOTHING
802 MOV [SI.user_DI],DI
803 MOV [SI.user_ES],ES
804 MOV [SI.user_BX],BX
805 MOV [SI.user_CX],CX
806 transfer SYS_RET_OK
807EndProc $GetExtendedError
808
809BREAK <$Get_Global_CdPg - Return Global Code Page>
810;
811; input: None
812; output: AX = Global Code Page
813;
814 procedure Get_Global_CdPg,NEAR
815 ASSUME DS:NOTHING,ES:NOTHING
816 PUSH SI
817 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG
818 MOV AX,CS:[SI.ccDosCodePage]
819 POP SI
820 return
821EndProc Get_Global_CdPg
822
823;-------------------------------Start of DBCS 2/13/KK
824BREAK <ECS_call - Extended Code System support function>
825
826ASSUME DS:NOTHING, ES:NOTHING
827
828 procedure $ECS_call,NEAR
829
830; Inputs:
831; AL = 0 get lead byte table
832; on return DS:SI has the table location
833;
834; AL = 1 set / reset interim console flag
835; DL = flag (00H or 01H)
836; no return
837;
838; AL = 2 get interim console flag
839; on return DL = current flag value
840;
841; AL = OTHER then error, and returns with:
842; AX = error_invalid_function
843;
844; NOTE: THIS CALL DOES GUARANTEE THAT REGISTER OTHER THAN
845; SS:SP WILL BE PRESERVED!
846
847 IF DBCS ;AN000;
848 ;AN000;
849 or al, al ; AL = 0 (get table)? ;AN000;
850 je get_lbt ;AN000;
851 cmp al, SetInterimMode ; AL = 1 (set / reset interim flag)? ;AN000;
852 je set_interim ;AN000;
853 cmp al, GetInterimMode ; AL = 2 (get interim flag)? ;AN000;
854 je get_interim ;AN000;
855 error error_invalid_function ;AN000;
856 ;AN000;
857get_lbt: ; get lead byte table ;AN000;
858 push ax ;AN000;
859 push bx ;AN000;
860 push ds ;AN000;
861 context DS ;AN000;
862 MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccSetDBCS ;AN000;
863 MOV AX,[BX+1] ; set EV address to DS:SI ;AN000;
864 MOV BX,[BX+3] ;AN000;
865 ADD AX,2 ; Skip Lemgth ;AN000;
866 invoke get_user_stack ;AN000;
867 assume ds:nothing ;AN000;
868 MOV [SI.user_SI], AX ;AN000;
869 MOV [SI.user_DS], BX ;AN000;
870 pop ds ;AN000;
871 pop bx ;AN000;
872 pop ax ;AN000;
873 transfer SYS_RET_OK ;AN000;
874
875set_interim: ; Set interim console flag ;AN000;
876 push dx ;AN000;
877 and dl,01 ; isolate bit 1 ;AN000;
878 mov [InterCon], dl ;AN000;
879 push ds ;AN000;
880 mov ds, [CurrentPDB] ;AN000;
881 mov byte ptr ds:[PDB_InterCon], dl ; update value in pdb ;AN000;
882 pop ds ;AN000;
883 pop dx ;AN000;
884 transfer SYS_RET_OK ;AN000;
885
886get_interim: ;AN000;
887 push dx ;AN000;
888 push ds ;AN000;
889 mov dl,[InterCon] ;AN000;
890 invoke get_user_stack ; get interim console flag ;AN000;
891 assume ds:nothing ;AN000;
892 mov [SI.user_DX],DX ;AN000;
893 pop ds ;AN000;
894 pop dx ;AN000;
895 transfer SYS_RET_OK ;AN000;
896 ELSE ;AN000;
897 or al, al ; AL = 0 (get table)? ;AN000;
898 jnz okok ;AN000;
899get_lbt: ;AN000;
900 invoke get_user_stack ;AN000;
901 assume ds:nothing ;AN000;
902 MOV [SI.user_SI], Offset Dosgroup:DBCS_TAB+2 ;AN000;
903 MOV [SI.user_DS], CS ;AN000;
904okok: ;AN000;
905 transfer SYS_RET_OK ; ;AN000;
906
907 ENDIF ;AN000;
908
909$ECS_call endp ;AN000;
910
911CODE ENDS
912 END
diff --git a/v4.0/src/DOS/HANDLE.ASM b/v4.0/src/DOS/HANDLE.ASM
new file mode 100644
index 0000000..e67c2ae
--- /dev/null
+++ b/v4.0/src/DOS/HANDLE.ASM
@@ -0,0 +1,893 @@
1; SCCSID = @(#)handle.asm 1.1 85/04/10
2TITLE HANDLE - Handle-related system calls
3NAME HANDLE
4;
5; Handle related system calls for MSDOS 2.X. Only top-level system calls
6; are present. I/O specs are defined in DISPATCH. The system calls are:
7;
8; $Close written
9; $Commit written DOS 3.3 F.C. 6/4/86
10; $ExtHandle written DOS 3.3 F.C. 6/4/86
11; $Read written
12; Align_Buffer DOS 4.00
13; $Write written
14; $LSeek written
15; $FileTimes written
16; $Dup written
17; $Dup2 written
18;
19; Revision history:
20;
21; Created: MZ 28 March 1983
22; MZ 15 Dec 1982 Jeff Harbers and Multiplan hard disk copy
23; rely on certain values in AX when $CLOSE
24; succeeds even though we document it as
25; always trashing AX.
26;
27; A000 version 4.00 Jan. 1988
28;
29
30.xlist
31;
32; get the appropriate segment definitions
33;
34include dosseg.asm
35
36CODE SEGMENT BYTE PUBLIC 'CODE'
37 ASSUME SS:DOSGROUP,CS:DOSGROUP
38
39.xcref
40INCLUDE DOSSYM.INC
41INCLUDE DEVSYM.INC
42include EA.inc
43include version.inc
44.cref
45.list
46.sall
47
48 EXTRN DOS_Read:NEAR, DOS_Write:NEAR
49
50IF BUFFERFLAG
51 extrn save_user_map:near
52 extrn restore_user_map:near
53 extrn Setup_EMS_Buffers:near
54ENDIF
55
56 I_need ThisSFT,DWORD ; pointer to SFT entry
57 I_need DMAAdd,DWORD ; old-style DMA address
58 I_Need EXTERR_LOCUS,byte ; Extended Error Locus
59 I_need FailErr,BYTE ; failed error flag
60 I_need User_ID,WORD ; current effective user_id
61 i_need JShare,DWORD ; jump table
62 I_need CurrentPDB,WORD ; current process data block
63 I_need EXTOPEN_ON,BYTE ;AN000;FT. flag for extended open
64; I_need XA_device,BYTE ;AN000; XA device
65 I_need XA_type,BYTE ;AN000; extended open subfunction
66; I_need XA_handle,WORD ;AN000; handle
67 I_need THISCDS,DWORD ;AN000;
68 I_need DUMMYCDS,128 ;AN000;
69 I_need SAVE_ES,WORD ;AN000; saved ES
70 I_need SAVE_DI,WORD ;AN000; saved DI
71 I_need SAVE_DS,WORD ;AN000; saved DS
72 I_need SAVE_SI,WORD ;AN000; saved SI
73 I_need SAVE_CX,WORD ;AN000; saved CX
74
75IF BUFFERFLAG
76
77 I_need BUF_EMS_MODE,BYTE
78 I_need BUF_EMS_LAST_PAGE,DWORD
79 I_need BUF_EMS_FIRST_PAGE,DWORD
80 I_need BUF_EMS_SAFE_FLAG,BYTE
81 I_need BUF_EMS_NPA640,WORD
82 I_need BUF_EMS_PAGE_FRAME,WORD
83 I_need BUF_EMS_PFRAME,WORD
84 I_need LASTBUFFER,DWORD
85
86ENDIF
87
88; I_need XA_ES,WORD ;AN000; extended find
89; I_need XA_BP,WORD ;AN000; extended find
90; I_need XA_from,BYTE ;AN000; for filetimes
91if debug
92 I_need BugLev,WORD
93 I_need BugTyp,WORD
94include bugtyp.asm
95endif
96
97BREAK <$Close - return a handle to the system>
98
99;
100; Assembler usage:
101; MOV BX, handle
102; MOV AH, Close
103; INT int_command
104;
105; Error return:
106; AX = error_invalid_handle
107;
108; No registers returned
109
110Procedure $Close,NEAR
111 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
112 fmt TypSysCall,LevLog,<"$p Close\n">
113 fmt TypSysCall,LevArgs,<"$p Handle = $x\n">,<BX>
114;
115; Grab the SFT pointer from the JFN.
116;
117 call CheckOwner ; get system file entry
118 JC CloseError ; error return
119 fmt TypAccess,LevSFN,<"$p Close SFT $x:$x\n">,<es,di>
120 context DS ; For DOS_CLOSE
121 MOV WORD PTR [ThisSFT],DI ; save offset of pointer
122 MOV WORD PTR [ThisSFT+2],ES ; save segment value
123;
124; DS:SI point to JFN table entry.
125; ES:DI point to SFT
126;
127; We now examine the user's JFN entry; If the file was a 70-mode file (network
128; FCB, we examine the ref count on the SFT; if it was 1, we free the JFN.
129; If the file was not a net FCB, we free the JFN too.
130;
131 CMP ES:[DI].sf_ref_count,1 ; will the SFT become free?
132 JZ FreeJFN ; yes, free JFN anyway.
133 MOV AL,BYTE PTR ES:[DI].sf_mode
134 AND AL,sharing_mask
135 CMP AL,sharing_net_fcb
136 JZ PostFree ; 70-mode and big ref count => free it
137;
138; The JFN must be freed. Get the pointer to it and replace the contents with
139; -1.
140;
141FreeJFN:
142 Invoke pJFNFromHandle ; d = pJFN (handle);
143 fmt TypAccess,LevSFN,<"$p Close jfn pointer $x:$x\n">,<es,di>
144 MOV BYTE PTR ES:[DI],0FFh ; release the JFN
145PostFree:
146;
147; ThisSFT is correctly set, we have DS = DOSGROUP. Looks OK for a DOS_CLOSE!
148;
149 invoke DOS_Close
150;
151; DOS_Close may return an error. If we see such an error, we report it but
152; the JFN stays closed because DOS_Close always frees the SFT!
153;
154 JC CloseError
155 fmt TypSysCall,LevLog,<"$p: Close ok\n">
156 MOV AH,close ; MZ Bogus multiplan fix
157 transfer Sys_Ret_OK
158CloseError:
159 ASSUME DS:NOTHING
160 fmt TypSysCall,LevLog,<"$p: Close error $x\n">,<AX>
161 transfer Sys_Ret_Err
162EndProc $Close
163
164BREAK <$Commit - commit the file>
165
166;
167; Assembler usage:
168; MOV BX, handle
169; MOV AH, Commit
170; INT int_command
171;
172; Error return:
173; AX = error_invalid_handle
174;
175; No registers returned
176
177Procedure $Commit,NEAR
178 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
179;
180; Grab the SFT pointer from the JFN.
181;
182 call CheckOwner ; get system file entry
183 JC Commiterror ; error return
184 context DS ; For DOS_COMMIT
185 MOV WORD PTR [ThisSFT],DI ; save offset of pointer
186 MOV WORD PTR [ThisSFT+2],ES ; save segment value
187;
188; ES:DI point to SFT
189;
190;
191; ThisSFT is correctly set, we have DS = DOSGROUP. Looks OK for a DOS_COMMIT
192;
193 invoke DOS_COMMIT
194;
195;
196 JC Commiterror
197 MOV AH,Commit ;
198 transfer Sys_Ret_OK
199Commiterror:
200 ASSUME DS:NOTHING
201 transfer Sys_Ret_Err
202EndProc $Commit
203
204
205BREAK <$ExtHandle - extend handle count>
206
207;
208; Assembler usage:
209; MOV BX, Number of Opens Allowed (MAX=65534;66535 is
210; MOV AX, 6700H reserved to mark SFT
211; INT int_command busy )
212;
213; Error return:
214; AX = error_not_enough_memory
215; or error_too_many_open_files
216; No registers returned
217
218Procedure $ExtHandle,NEAR
219 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
220;
221;
222;
223 XOR BP,BP ; 0: enlarge 1: shrink 2:psp
224 CMP BX,FilPerProc ; < 20
225 JAE getpdb ; no
226 MOV BX,FilPerProc ; bx = 20
227
228getpdb:
229 MOV ES,[CurrentPDB] ; get user process data block
230 MOV CX,ES:[PDB_JFN_Length] ; get number of handle allowed
231 CMP BX,CX ; the requested == current
232 JE ok_done ; yes and exit
233 JA larger ; go allocate new table
234
235 MOV BP,1 ; shrink
236 MOV DS,WORD PTR ES:[PDB_JFN_Pointer+2] ;
237 MOV SI,BX ;
238 SUB CX,BX ; get difference
239chck_handles:
240 CMP BYTE PTR DS:[SI],-1 ; scan through handles to ensure close
241 JNZ too_many_files ; status
242 INC SI
243 LOOP chck_handles
244 CMP BX,FilPerProc ; = 20
245 JA larger ; no
246
247 MOV BP,2 ; psp
248 MOV DI,PDB_JFN_Table ; es:di -> jfn table in psp
249 PUSH BX
250 JMP movhandl
251
252larger:
253 CMP BX,-1 ; 65535 is not allowed
254 JZ invalid_func
255 CLC
256 PUSH BX ; save requested number
257 ADD BX,0FH ; adjust to paragraph boundary
258 MOV CL,4
259 RCR BX,CL ; DOS 4.00 fix ;AC000;
260 AND BX,1FFFH ; clear most 3 bits
261
262 PUSH BP
263 invoke $ALLOC ; allocate memory
264 POP BP
265 JC no_memory ; not enough meory
266
267 MOV ES,AX ; es:di points to new table memory
268 XOR DI,DI
269movhandl:
270 MOV DS,[CurrentPDB] ; get user PDB address
271
272 TEST BP,3 ; enlarge ?
273 JZ enlarge ; yes
274 POP CX ; cx = the amount you shrink
275 PUSH CX
276 JMP copy_hand
277ok_done:
278 transfer Sys_Ret_OK
279too_many_files:
280 MOV AL,error_too_many_open_files
281 transfer Sys_Ret_Err
282enlarge:
283 MOV CX,DS:[PDB_JFN_Length] ; get number of old handles
284copy_hand:
285 MOV DX,CX
286 LDS SI,DS:[PDB_JFN_Pointer] ; get old table pointer
287ASSUME DS:NOTHING
288 REP MOVSB ; copy infomation to new table
289
290 POP CX ; get new number of handles
291 PUSH CX ; save it again
292 SUB CX,DX ; get the difference
293 MOV AL,-1 ; set availability to handles
294 REP STOSB
295
296 MOV DS,[CurrentPDB] ; get user process data block
297 CMP WORD PTR DS:[PDB_JFN_Pointer],0 ; check if original table pointer
298 JNZ update_info ; yes, go update PDB entries
299 PUSH BP
300 PUSH DS ; save old table segment
301 PUSH ES ; save new table segment
302 MOV ES,WORD PTR DS:[PDB_JFN_Pointer+2] ; get old table segment
303 invoke $DEALLOC ; deallocate old table meomory
304 POP ES ; restore new table segment
305 POP DS ; restore old table segment
306 POP BP
307
308update_info:
309 TEST BP,2 ; psp?
310 JZ non_psp ; no
311 MOV WORD PTR DS:[PDB_JFN_Pointer],PDB_JFN_Table ; restore
312 JMP final
313non_psp:
314 MOV WORD PTR DS:[PDB_JFN_Pointer],0 ; new table pointer offset always 0
315final:
316 MOV WORD PTR DS:[PDB_JFN_Pointer+2],ES ; update table pointer segment
317 POP DS:[PDB_JFN_Length] ; restore new number of handles
318 transfer Sys_Ret_Ok
319no_memory:
320 POP BX ; clean stack
321 MOV AL,error_not_enough_memory
322 transfer Sys_Ret_Err
323invalid_func:
324 MOV AL,error_invalid_function
325 transfer Sys_Ret_Err
326EndProc $ExtHandle
327
328BREAK <$READ - Read from a file handle>
329;
330; Assembler usage:
331; LDS DX, buf
332; MOV CX, count
333; MOV BX, handle
334; MOV AH, Read
335; INT int_command
336; AX has number of bytes read
337; Errors:
338; AX = read_invalid_handle
339; = read_access_denied
340;
341; Returns in register AX
342
343procedure $READ,NEAR
344 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
345 fmt TypSysCall,LevLog,<"Read\n">
346 fmt TypSysCall,LevArgs,<" Handle $x Cnt $x Buf $x:$x\n">,<BX,CX,DS,DX>
347 MOV SI,OFFSET DOSGROUP:DOS_Read
348ReadDo:
349 invoke pJFNFromHandle
350 JC ReadError
351 MOV AL,ES:[DI]
352 call CheckOwner ; get the handle
353 JNC ReadSetup ; no errors do the operation
354ReadError:
355 fmt TypSysCall,LevLog,<"Read/Write error $x\n">,<AX>
356 transfer SYS_RET_ERR ; go to error traps
357ReadSetup:
358 MOV WORD PTR [ThisSFT],DI ; save offset of pointer
359 MOV WORD PTR [ThisSFT+2],ES ; save segment value
360;; Extended Open
361 TEST ES:[DI.sf_mode],INT_24_ERROR ;AN000;;EO. need i24
362 JZ needi24 ;AN000;;EO. yes
363 OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;;EO. set it off
364needi24: ;AN000;
365
366;; Extended Open
367 SaveReg <<WORD PTR [DMAAdd]>, <WORD PTR [DMAAdd+2]>>
368;;;;; BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!!
369 CALL Align_Buffer ;AN000;MS. align user's buffer
370;;;;; END BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!!
371
372IF BUFFERFLAG
373
374; int 3
375; cmp [BUF_EMS_MODE], -1
376; jz dos_call
377; call choose_buf_page
378; jc ReadError
379; call save_user_map
380
381;dos_call:
382ENDIF
383 context DS ; go for DOS addressability
384 CALL SI ; indirect call to operation
385 RestoreReg <<WORD PTR [DMAAdd+2]>, <WORD PTR [DMAAdd]>>
386
387IF BUFFERFLAG
388 pushf
389 push ax
390 push bx
391
392 cmp cs:[BUF_EMS_MODE], -1
393 jz dos_call_done
394 call restore_user_map
395 mov ax, word ptr cs:[BUF_EMS_LAST_PAGE]
396 cmp cs:[BUF_EMS_PFRAME], ax
397 je dos_call_done
398 mov word ptr cs:[LASTBUFFER], -1
399 mov cs:[BUF_EMS_PFRAME], ax
400 mov ax, word ptr cs:[BUF_EMS_LAST_PAGE+2]
401 mov cs:[BUF_EMS_PAGE_FRAME], ax
402 mov cs:[BUF_EMS_SAFE_FLAG], 1
403 call Setup_EMS_Buffers
404
405dos_call_done:
406 pop bx
407 pop ax
408 popf
409ENDIF
410
411IF NOT BUFFERFLAG
412 JC ReadError ; if error, say bye bye
413ELSE
414 jmp tmp_rerr
415tmp_rerr:
416 jc ReadError
417ENDIF
418
419 MOV AX,CX ; get correct return in correct reg
420 fmt TypSysCall,LevLog,<"Read/Write cnt done $x\n">,<AX>
421 transfer sys_ret_ok ; successful return
422EndProc $READ
423
424;
425; Input: DS:DX points to user's buffer addr
426; Function: rearrange segment and offset for READ/WRITE buffer
427; Output: [DMAADD] set
428;
429;
430
431procedure Align_Buffer,NEAR ;AN000;
432 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
433 MOV BX,DX ; copy offset
434 SaveReg <CX> ; don't stomp on count
435 MOV CL,4 ; bits to shift bytes->para
436 SHR BX,CL ; get number of paragraphs
437 RestoreReg <CX> ; get count back
438 MOV AX,DS ; get original segment
439 ADD AX,BX ; get new segment
440 MOV DS,AX ; in seg register
441 AND DX,0Fh ; normalize offset
442 MOV WORD PTR [DMAAdd],DX ; use user DX as offset
443 MOV WORD PTR [DMAAdd+2],DS ; use user DS as segment for DMA
444 return ;AN000;
445EndProc Align_Buffer ;AN000;
446
447BREAK <$WRITE - write to a file handle>
448
449;
450; Assembler usage:
451; LDS DX, buf
452; MOV CX, count
453; MOV BX, handle
454; MOV AH, Write
455; INT int_command
456; AX has number of bytes written
457; Errors:
458; AX = write_invalid_handle
459; = write_access_denied
460;
461; Returns in register AX
462
463procedure $WRITE,NEAR
464 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
465 fmt TypSysCall,LevLog,<"Write\n">
466 fmt TypSysCall,LevArgs,<" Handle $x Cnt $x Buf $x:$x\n">,<BX,CX,DS,DX>
467 MOV SI,OFFSET DOSGROUP:DOS_Write
468 JMP ReadDo
469EndProc $Write
470
471BREAK <$LSEEK - move r/w pointer>
472
473;
474; Assembler usage:
475; MOV DX, offsetlow
476; MOV CX, offsethigh
477; MOV BX, handle
478; MOV AL, method
479; MOV AH, LSeek
480; INT int_command
481; DX:AX has the new location of the pointer
482; Error returns:
483; AX = error_invalid_handle
484; = error_invalid_function
485; Returns in registers DX:AX
486
487procedure $LSEEK,NEAR
488 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
489 call CheckOwner ; get system file entry
490LSeekError:
491
492IF BUFFERFLAG
493 JC TMP_RERR
494ELSE
495 JC ReadError ; error return
496ENDIF
497 CMP AL,2 ; is the seek value correct?
498 JBE LSeekDisp ; yes, go dispatch
499 MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
500 error error_invalid_function ; invalid method
501LSeekDisp:
502 CMP AL,1 ; best way to dispatch; check middle
503 JB LSeekStore ; just store CX:DX
504 JA LSeekEOF ; seek from end of file
505 ADD DX,WORD PTR ES:[DI.SF_Position]
506 ADC CX,WORD PTR ES:[DI.SF_Position+2]
507LSeekStore:
508 MOV AX,CX ; AX:DX
509 XCHG AX,DX ; DX:AX is the correct value
510LSeekSetpos:
511 MOV WORD PTR ES:[DI.SF_Position],AX
512 MOV WORD PTR ES:[DI.SF_Position+2],DX
513 invoke Get_user_stack
514 MOV DS:[SI.User_DX],DX ; return DX:AX
515 transfer SYS_RET_OK ; successful return
516
517LSeekEOF:
518 TEST ES:[DI.sf_flags],sf_isnet
519 JNZ Check_LSeek_Mode ; Is Net
520LOCAL_LSeek:
521 ADD DX,WORD PTR ES:[DI.SF_Size]
522 ADC CX,WORD PTR ES:[DI.SF_Size+2]
523 JMP LSeekStore ; go and set the position
524
525Check_LSeek_Mode:
526 TEST ES:[DI.sf_mode],sf_isfcb
527 JNZ LOCAL_LSeek ; FCB treated like local file
528 MOV AX,ES:[DI.sf_mode]
529 AND AX,sharing_mask
530 CMP AX,sharing_deny_none
531 JZ NET_LSEEK ; LSEEK exported in this mode
532 CMP AX,sharing_deny_read
533 JNZ LOCAL_LSeek ; Treated like local Lseek
534NET_LSEEK:
535; JMP LOCAL_LSeek
536; REMOVE ABOVE INSTRUCTION TO ENABLE DCR 142
537 CallInstall Net_Lseek,multNet,33
538 JNC LSeekSetPos
539 transfer SYS_RET_ERR
540
541EndProc $LSeek
542
543BREAK <FileTimes - modify write times on a handle>
544
545;
546; Assembler usage:
547; MOV AH, FileTimes (57H)
548; MOV AL, func
549; MOV BX, handle
550; ; if AL = 1 then then next two are mandatory
551; MOV CX, time
552; MOV DX, date
553; INT 21h
554; ; if AL = 0 then CX/DX has the last write time/date
555; ; for the handle.
556;
557; AL=02 get extended attributes
558; BX=handle
559; CX=size of buffer (0, return max size )
560; DS:SI query list (si=-1, selects all EA)
561; ES:DI buffer to hold EA list
562;
563; AL=03 get EA name list
564; BX=handle
565; CX=size of buffer (0, return max size )
566; ES:DI buffer to hold name list
567;
568; AL=04 set extended attributes
569; BX=handle
570; ES:DI buffer of EA list
571;
572;
573;
574;
575; Error returns:
576; AX = error_invalid_function
577; = error_invalid_handle
578;
579
580procedure $File_Times,NEAR
581 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
582 CMP AL,2 ; correct subfunction?
583 JAE gsetxa
584 JMP filetimes_ok ; Yes, continue
585;;;; DOS 4.00 ;AN000;
586gsetxa: ;AN000;
587 EnterCrit critSFT ;AN000;;FT. enter critical section
588 CMP AL,4 ;AN000;;FT. =4
589 JBE gshandle ;AN000;;FT. 2,3,4 do get/set by handle
590funcerr: ;AN000;
591 JMP inval_func ;AN000;;FT. invalid function
592 ;AN000;
593gshandle: ;AN000;
594 MOV [SAVE_ES],ES ;AN000;;FT. save regs
595 MOV [SAVE_DI],DI ;AN000;;FT.
596 MOV [SAVE_DS],DS ;AN000;;FT. save regs
597 MOV [SAVE_SI],SI ;AN000;;FT.
598 MOV [SAVE_CX],CX ;AN000;;FT.
599 MOV [XA_TYPE],AL ;AN000;;FT.
600 ;AN000;
601; MOV [XA_handle],BX ;AN000; ;FT. save handle
602 CALL CheckOwner ;AN000; ;FT. get sf pointer
603 JNC getsetit ;AN000; ;FT. good handle
604 LeaveCrit critSFT ;AN000; ;FT. leave critical section
605 JMP LSeekError ;AN000; ;FT. turkey handle
606 ;AN000;
607getsetit: ;AN000;
608 MOV WORD PTR [ThisSFT],DI ;AN000; ;FT. set ThisSFT
609 MOV WORD PTR [ThisSFT+2],ES ;AN000; ;FT. set ThisSFT
610; TEST ES:[DI.sf_mode],INT_24_ERROR ;AN000;;FT. mask INT 24
611; JZ nomask ;AN000;;FT. no
612; OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;;FT. set bit for I24 handler
613nomask: ;AN000;
614 TEST ES:[DI.sf_flags],sf_isnet ;AN000;;FT. remote handle
615 JZ localhandle ;AN000;;FT. no
616 LeaveCrit critSFT ;AN000;;FT. doesn't support Network
617
618 MOV BL,[XA_TYPE] ;AN000;;FT.
619IFSsearch: ;AN000;
620 MOV AX,(multNET SHL 8) or 45 ;AN000;;FT. Get/Set XA support
621 INT 2FH ;AN000;
622 JC getseterror ;AN000;;FT. error
623 transfer SYS_RET_OK ;AN000;;FT.
624localhandle: ;AN000;
625; TEST ES:[DI.sf_flags],devid_device ;AN000;;FT. device
626; JZ getsetfile8 ;AN000;;FT. no
627; MOV [XA_device],1 ;AN000;;FT. indicating device
628; JMP SHORT doXA ;AN000;;FT. do XA
629getsetfile8: ;AN000;
630; MOV [XA_device],0 ;AN000;;FT. indicating File
631; LES BP,ES:[DI.sf_devptr] ;AN000;;FT. ES:BP -> DPB
632
633doXA: ;AN000;
634; MOV [XA_from],By_XA ;AN000;;FT. from get/set XA
635; PUSH [SAVE_ES] ;AN000;;FT. save XA list
636; PUSH [SAVE_DI] ;AN000;;FT. save XA list
637
638 invoke GetSet_XA ;AN000;;FT. issue Get/Set XA
639; POP SI ;AN000;;FT. DS:SI -> XA list
640; POP DS ;AN000;
641 JC getexit ;AN000;;FT. error
642; CMP [XA_device],0 ;AN000;;FT. device ?
643; JNZ ftok ;AN000;;FT. yes, exit
644; MOV AX,4 ;AN000;;FT. function 4 for ShSU
645; CMP [XA_type],4 ;AN000;;FT. set XA
646; JNZ ftok ;AN000;;FT. no
647;
648;
649; LES DI,[ThisSFT] ;AN000;;FT. es:di -> sft
650; CMP WORD PTR [SI],0 ;AN000;;FT. null list ?
651; JNZ do_share ;AN000;;FT. no
652 JMP SHORT ftok ;AN000;;FT. return
653getexit: ;AN000;;FT.
654 LeaveCrit critSFT ;AN000;;FT. leave critical section
655
656
657getseterror: ;AN000;
658 transfer SYS_RET_ERR ;AN000;;FT. mark file as dirty
659inval_func:
660
661;;;;; DOS 4.00
662 MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
663 error error_invalid_function ; give bad return
664filetimes_ok:
665 call CheckOwner ; get sf pointer
666 JNC gsdt
667 JMP LSeekError ; turkey handle
668gsdt:
669 OR AL,AL ; is it Get?
670 JNZ filetimes_set ; no, go set the time
671 CLI
672 MOV CX,ES:[DI.sf_Time] ; suck out time
673 MOV DX,ES:[DI.sf_Date] ; and date
674 STI
675 invoke Get_user_stack ; obtain place to return it
676 MOV [SI.user_CX],CX ; and stash in time
677 MOV [SI.user_DX],DX ; and stask in date
678ext_done:
679 transfer SYS_RET_OK ; and say goodnight
680filetimes_set:
681 EnterCrit critSFT
682 MOV ES:[DI.sf_Time],CX ; drop in new time
683 MOV ES:[DI.sf_Date],DX ; and date
684 XOR AX,AX
685do_share:
686if installed
687 Call JShare + 14 * 4
688else
689 Call ShSU
690endif
691datetimeflg:
692 AND ES:[DI.sf_Flags],NOT devid_file_clean
693 OR ES:[DI.sf_Flags],sf_close_nodate
694ftok:
695 LeaveCrit critSFT
696 transfer SYS_RET_OK ; mark file as dirty and return
697EndProc $File_Times
698
699BREAK <$DUP - duplicate a jfn>
700;
701; Assembler usage:
702; MOV BX, fh
703; MOV AH, Dup
704; INT int_command
705; AX has the returned handle
706; Errors:
707; AX = dup_invalid_handle
708; = dup_too_many_open_files
709Procedure $DUP,NEAR
710 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
711 MOV AX,BX ; save away old handle in AX
712 invoke JFNFree ; free handle? into ES:DI, new in BX
713DupErrorCheck:
714 JC DupErr ; nope, bye
715 SaveReg <ES,DI> ; save away SFT
716 RestoreReg <SI,DS> ; into convenient place DS:SI
717 XCHG AX,BX ; get back old handle
718 call CheckOwner ; get sft in ES:DI
719 JC DupErr ; errors go home
720 invoke DOS_Dup_Direct
721 invoke pJFNFromHandle ; get pointer
722 MOV BL,ES:[DI] ; get SFT number
723 MOV DS:[SI],BL ; stuff in new SFT
724 transfer SYS_RET_OK ; and go home
725DupErr: transfer SYS_RET_ERR
726
727EndProc $Dup
728
729BREAK <$DUP2 - force a dup on a particular jfn>
730;
731; Assembler usage:
732; MOV BX, fh
733; MOV CX, newfh
734; MOV AH, Dup2
735; INT int_command
736; Error returns:
737; AX = error_invalid_handle
738;
739Procedure $Dup2,NEAR
740 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
741 SaveReg <BX,CX> ; save source
742 MOV BX,CX ; get one to close
743 invoke $Close ; close destination handle
744 RestoreReg <BX,AX> ; old in AX, new in BX
745 invoke pJFNFromHandle ; get pointer
746 JMP DupErrorCheck ; check error and do dup
747EndProc $Dup2
748
749Break <CheckOwner - verify ownership of handles from server>
750
751;
752; CheckOwner - Due to the ability of the server to close file handles for a
753; process without the process knowing it (delete/rename of open files, for
754; example), it is possible for the redirector to issue a call to a handle
755; that it soes not rightfully own. We check here to make sure that the
756; issuing process is the owner of the SFT. At the same time, we do a
757; SFFromHandle to really make sure that the SFT is good.
758;
759; Inputs: BX has the handle
760; User_ID is the current user
761; Output: Carry Clear => ES:DI points to SFT
762; Carry Set => AX has error code
763; Registers modified: none
764;
765
766Procedure CheckOwner,NEAR
767 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
768 invoke SFFromHandle
769 retc
770 push ax
771 mov ax,user_id
772 cmp ax,es:[di].sf_UID
773 pop ax
774 retz
775 mov al,error_invalid_handle
776 stc
777 return
778EndProc CheckOwner
779
780;-------------------------------------------------------------------------
781; Function name : choose_buf_page
782; Inputs : DMAADD = Xaddr
783; cx = # of bytes to transfer
784; Outputs : if NC
785;
786; SAFE_FLAG - 0 ==> page is safe. no need to
787; detect collision between
788; user & system buffer.
789; SAFE_FLAG - 1 ==> page is unsafe. Must check
790; for collision
791;
792; CY - error
793;
794;
795; High Level Alogrithm:
796;
797; 1. If Xaddr. is above the first physical page above 640K
798; 2. choose that page
799; 3. set safe flag
800; 4. else
801; 5. choose highest page above 640K
802; 6. If 6 or more pages above 640k
803; 7. Set safe flag
804; 8. else
805; 9. if Xaddr. + # of bytes to transfer does not spill into the
806; chosen page
807; 10. set safe flag
808; 11.else
809; 12. clear safe flag
810; 13.endif
811; 14.endif
812; 15.endif
813;
814;----------------------------------------------------------------------------
815;Procedure choose_buf_page,near
816;
817; assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup
818;
819; push cx
820; push bx
821; push dx
822; push si
823; push ds
824; push ax
825;
826; mov ax, word ptr [DMAADD+2]
827; and ax, 0fc00h ; page segment of transfer segment
828;
829; cmp ax, word ptr [BUF_EMS_FIRST_PAGE]
830; ja pick_first
831;
832; cmp [BUF_EMS_NPA640], 6
833; jae safe_pick_last
834;
835; add cx, word ptr [DMAADD] ; get final offset
836; mov bx, cx
837;
838; mov cl, 4
839; shr bx, cl ; get # of paragraphs
840; mov ax, word ptr [DMAADD+2] ; get initial segment
841; add ax, bx ; get final segment
842;
843; and ax, 0fc00h
844; cmp ax, word ptr [BUF_EMS_LAST_PAGE]
845; jne safe_pick_last
846;
847; mov [BUF_EMS_SAFE_FLAG], 0
848; jmp fin_choose_page
849;
850;safe_pick_last:
851; mov [BUF_EMS_SAFE_FLAG], 1
852; jmp fin_choose_page
853;
854;;pick_last:
855;; mov ax, word ptr [BUF_EMS_LAST_PAGE]
856;; mov [BUF_EMS_PFRAME], ax
857;; mov ax, word ptr [BUF_EMS_LAST_PAGE+2]
858;; mov [BUF_EMS_PAGE_FRAME], ax
859;; xor ax, ax
860;; jmp fin_choose_page
861;
862;pick_first:
863; mov ax, word ptr [BUF_EMS_FIRST_PAGE]
864; cmp [BUF_EMS_PFRAME], ax
865; je fin_choose_page
866; mov word ptr [LASTBUFFER], -1
867; mov [BUF_EMS_PFRAME], ax
868; mov ax, word ptr [BUF_EMS_FIRST_PAGE+2]
869; mov [BUF_EMS_PAGE_FRAME], ax
870; mov [BUF_EMS_SAFE_FLAG], 1
871; call Setup_EMS_Buffers
872; jmp fin_choose_page
873;
874;err_choose_page:
875; stc
876;
877;fin_choose_page:
878; clc
879;
880; pop ax
881; pop ds
882; pop si
883; pop dx
884; pop bx
885; pop cx
886; return
887;
888;EndProc choose_buf_page
889;
890
891CODE ENDS
892END
893 \ No newline at end of file
diff --git a/v4.0/src/DOS/HIGHSW.ASM b/v4.0/src/DOS/HIGHSW.ASM
new file mode 100644
index 0000000..9bd758f
--- /dev/null
+++ b/v4.0/src/DOS/HIGHSW.ASM
@@ -0,0 +1,29 @@
1; SCCSID = @(#)highsw.asm 1.1 85/04/10
2TRUE EQU 0FFFFH
3FALSE EQU NOT TRUE
4
5; Use the switches below to produce the standard Microsoft version or the IBM
6; version of the operating system
7MSVER EQU TRUE
8IBM EQU FALSE
9WANG EQU FALSE
10ALTVECT EQU FALSE
11
12; Set this switch to cause DOS to move itself to the end of memory
13HIGHMEM EQU TRUE
14
15 IF IBM
16ESCCH EQU 0 ; character to begin escape seq.
17TOGLPRN EQU TRUE ;One key toggles printer echo
18ZEROEXT EQU TRUE
19 ELSE
20 IF WANG ;Are we assembling for WANG?
21ESCCH EQU 1FH ;Yes. Use 1FH for escape character
22 ELSE
23ESCCH EQU 1BH
24 ENDIF
25CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
26TOGLPRN EQU FALSE ;Separate keys for printer echo on
27 ;and off
28ZEROEXT EQU TRUE
29 ENDIF
diff --git a/v4.0/src/DOS/IFS.ASM b/v4.0/src/DOS/IFS.ASM
new file mode 100644
index 0000000..2893f28
--- /dev/null
+++ b/v4.0/src/DOS/IFS.ASM
@@ -0,0 +1,523 @@
1
2
3
4.xlist ;AN000;
5include dosseg.asm ;AN000;
6
7CODE SEGMENT BYTE PUBLIC 'CODE' ;AN000;
8 ASSUME CS:DOSGROUP, SS:DOSGROUP ;AN000;
9.xcref ;AN000;
10include dossym.inc ;AN000;
11include devsym.inc ;AN000;
12include doscntry.inc ;AN000;
13.cref ;AN000;
14.list
15StackSize = 180h ; gross but effective
16
17 i_need VERFLG ; verify status flag ;AN000;
18 i_need CNTCFLAG ; break status flag ;AN000;
19 i_need CPSWFLAG ; CP switch logic ON/OFF ;AN000;
20 I_need CURRENTPDB,WORD ; Current process identifier ;AN000;
21 I_need HIGH_SECTOR,WORD ;AN000;
22 I_need BUF_HASH_COUNT,WORD ;AN000;
23 I_need FAILERR,WORD ;AN000;
24 I_need USER_ID,WORD ;AN000;
25 I_need CALLDEVAD,DWORD ; ;AN000;
26 I_need SYSINITVAR,WORD ;AN000;
27 I_need MYNAME,16 ; NetBIOS name ;AN000;
28 I_need RETRYCOUNT,WORD ; retry count ;AN000;
29 I_need COUNTRY_CDPG,BYTE ;AN000;
30 i_need DAY,BYTE ; date ;AN000;
31 i_need MONTH,BYTE ;AN000;
32 i_need YEAR,WORD ;AN000;
33 i_need CURBUF,DWORD ;AN000;
34 i_need IFS_DRIVER_ERR,WORD ;AN000;
35 i_need DOS34_FLAG,WORD ; IFS function Read/Write flag ;AN000;
36 i_need Callback_SS,WORD ; ;AN000;
37 i_need Callback_SP,WORD ;AN000;
38 i_need SaveBX,WORD ;AN000;
39 i_need Temp_Var,WORD ;AN000;
40 i_need INDOS,BYTE ;AN000;
41 i_need DskStack,BYTE ;AN000;
42 i_need IOStack,BYTE ;AN000;
43 i_need Callback_flag,BYTE ;AN000;
44
45DOSINFO STRUC ;AN000;
46bsize dw 0 ;AN000;
47files dw 0 ;AN000;
48fcbs1 dw 0 ;AN000;
49fcbs2 dw 0 ;AN000;
50buffers dw 0 ;AN000;
51 dw 0 ;AN000;
52lastdrv dw 0 ;AN000;
53secsize dw 0 ;AN000;
54DosInfo ENDS ;AN000;
55
56
57
58 extrn ABSDRD:NEAR ;AN000;
59 extrn ABSDWRT:NEAR ;AN000;
60 extrn READTIME:NEAR ;AN000;
61 extrn CHECKFLUSH:NEAR ;AN000;
62 extrn GETCURHEAD:NEAR ;AN000;
63
64
65;******************************************************************************
66; *
67; * MODULE: IFS_DOSCALL
68; *
69; * FUNCTION: IFS to DOS function request dispatcher
70; *
71; * FUNCTION: This procedure dispatches the IFS DOS service requests
72; * by calling various DOS service routines
73; *
74; * CALLING SEQUENCE:
75; *
76; * CALL DWORD PTR IFS_DOSCALL@
77; *
78; *
79; * RETURN SEQUENCE:
80; *
81; * If AX = 0 No error
82; *
83; * If AX <> 0 Error
84; * AX = Error Code:
85; *
86; *
87; * INTERNAL REFERENCES: None
88; *
89; *
90; * EXTERNAL REFERENCES: STRATEGY, INTERRUPT, ABSDRD, ABSDWRT,
91; * FIND_SECTOR, MARK_SECTOR, WRITE_BUFFR,
92; * READ_BUFFR, WRITE_BUFFR, FREE_BUFFR,
93; * GET_DOS_INFO, FLUSH_BUFF
94; *
95; * NOTES: None
96; *
97; * REVISION HISTORY: New
98; *
99; * COPYRIGHT: "MS DOS IFS Function"
100; * "Version 1.00 (C) Copyright 1988 Microsoft Corporation"
101; * "Licensed Material - Program Property of Microsoft"
102; *
103; *************************************************************************
104
105
106
107
108
109PROCEDURE IFS_DOSCALL,FAR ;AN000;
110 assume DS:NOTHING,ES:NOTHING ;AN000;
111
112 CLI ; ;AN000;
113 CMP AH,39 ; ;AN000;
114 JNZ others ; ;AN000;
115 INC CS:[INDOS] ; in DOS ;AN000;
116 JMP Dosend ; ;AN000;
117others:
118 CMP AH,40 ; ;AN000;
119 JNZ others2 ; ;AN000;
120 DEC CS:[INDOS] ; out DOS ;AN000;
121 JMP Dosend ; ;AN000;
122others2:
123 CMP AH,38 ; ;AN000;
124 JNZ not_stack ; ;AN000;
125 PUSH CS ; ;AN000;
126 POP DS ; ;AN000;
127 MOV SI,OFFSET DOSGROUP:IOSTACK ;AN000;
128 MOV CX,stacksize ;AN000;
129 JMP Dosend ; ;AN000;
130 ; ;AN000;
131not_stack: ; ;AN000;
132 MOV CS:[Temp_Var],DS; save ds for strcmp strcpy ;AN000;
133 PUSH CS ; ;AN000;
134 POP DS ; ;AN000;
135 assume DS:DOSGROUP ;AN000;
136 INC [INDOS] ; in DOS ;AN000;
137 PUSH CX ; save cx ;AN000;
138 PUSH DX ; save cx ;AN000;
139 MOV CX,SS ; cx=stack ;AN000;
140 MOV DX,CS ; cx=stack ;AN000;
141 CMP CX,DX ; dosgroup stack ? ;AN000;
142 POP DX ; save cx ;AN000;
143 POP CX ; restore cx ;AN000;
144 JZ withSS_SP ; yes ;AN000;
145 MOV [Callback_SS],SS ;save SS:SP ;AN000;
146 MOV [Callback_SP],SP ;AN000;
147 MOV [SaveBX],BX ; ;AN000;
148 MOV BX,CS ; prepare system stack ;AN000;
149 MOV SS,BX ; ;AN000;
150 MOV SP,OFFSET DOSGROUP:DSKSTACK ;AN000;
151 MOV BX,[SaveBX] ; ;AN000;
152 MOV [Callback_flag],1 ;set flag ;AN000;
153withSS_SP: ; ;AN000;
154 STI ;AN000;
155 ASSUME DS:NOTHING ;AN000;
156; OR [DOS34_FLAG],Force_I24_Fail ;AN000;
157; ;AN000;
158; cmp ah,0 ; call Strategy routine ?? ;AN000;
159; jne dos_chk_ah1 ; jump if not ;AN000;
160; CALL STRATEGY ; else call strategy routine ;AN000;
161; jmp dos_exit ; then exit ;AN000;
162 ;AN000;
163;Dos_Chk_Ah1: ;AN000;
164; cmp ah,1 ; call interrupt routine ;AN000;
165; jne dos_chk_ah2 ; jump if not ;AN000;
166; CALL INTERRUPT ; else call interrupt routine ;AN000;
167; jmp dos_exit ; then exit ;AN000;
168 ;AN000;
169;Dos_Chk_Ah2: ;AN000;
170; cmp ah,4 ;AN000;
171; jae Dos_Chk_Ah8 ;AN000;
172; mov High_Sector,si ; save HI sector word ;AN000;
173; mov dx,di ; save low sector ;AN000;
174; push es ;AN000;
175; invoke FIND_DPB ; ds:si -> DPB ;AN000;
176; mov bp,si ;AN000;
177; push ds ;AN000;
178; pop es ; es:bp -> DPB ;AN000;
179; pop ds ; DS:BX-->Input buffer ;AN000;
180;
181; cmp ah,2 ; absolute read ?? ;AN000;
182; jne dos_chk_ah3 ; jump if not ;AN000;
183;
184; invoke DSKREAD ; else do absolute read ;AN000;
185; jmp dos_exit ; then return ;AN000;
186
187;Dos_Chk_Ah3: ;AN000;
188; invoke DSKWRITE ; do absolute write ;AN000;
189; jmp dos_exit ; then exit ;AN000;
190
191
192
193Dos_chk_ah32: ;AN000;
194 cmp ah,32
195 jne str_cmp ;AN000;
196 CALL GET_DOS_INFO ; else get DOS information ;AN000;
197 jmp SHORT dos_exit ;AN000; ;AN000;
198str_cmp: ;AN000;
199 mov DS,[Temp_Var] ; restore DS ;AN000;
200 cmp ah,36 ;AN000;
201 jne str_cpy ;AN000;
202 invoke strcmp ; string compare ;AN000;
203 jmp SHORT dos_exit ;AN000;
204str_cpy: ;AN000;
205 cmp ah,37 ;AN000;
206 jne dos_error ;AN000;
207 invoke strcpy ; string copy ;AN000;
208 jmp SHORT dos_exit ;AN000;
209
210Dos_Error: ;AN000;
211 stc
212 ;AN000;
213Dos_Exit: ;AN000;
214 CLI ;AN000;
215 PUSHF ;AN000;
216 AND [DOS34_FLAG],No_Force_I24_Fail ;AN000;
217 DEC [INDOS] ; exit DOS ;AN000;
218 CMP [Callback_flag],0 ;from dosgroup
219 JZ noSS_SP ;yes ;AN000;
220 MOV [Callback_flag],0 ; ;AN000;
221 POPF ;AN000;
222 MOV SP,CS:[Callback_SP]; ;AN000;
223 MOV SS,CS:[Callback_SS]; restore user's SS:SP ;AN000;
224 JMP SHORT DOSend ;AN000;
225noSS_SP: ;AN000;
226 POPF
227Dosend:
228 STI ; ;AN000;
229
230 ret ;return ;AN000;
231
232
233ENDPROC IFS_DOSCALL ;AN000;
234
235
236
237
238
239; ****************************************************************************
240; *
241; * MODULE: STRATEGY
242; *
243; * FUNCTION: Call Strategy Routine
244; *
245; * FUNCTION: This procedure dispatches the IFS DOS service requests
246; * by calling various DOS service functions
247; *
248; * INPUT: ES:BX ---> Device Request Header
249; * AL = Drive #
250; *
251; * CALL STRATEGY
252; *
253; * OUTPUT: output of driver
254; *
255; * INTERNAL REFERENCES: None
256; *
257; *
258; * EXTERNAL REFERENCES: GETTHISDRV
259; *
260; * NOTES: None
261; *
262; * REVISION HISTORY: New
263; *
264; *************************************************************************
265
266;PROCEDURE STRATEGY,NEAR ;AN000;
267
268; INVOKE FIND_DPB ; get DPB from drive number ;AN000;
269; ; DS:SI-->DPB for drive ;AN000;
270; LDS DI,DS:[SI.DPB_Driver_Addr] ; get driver addres from DPB ;AN000;
271; MOV DX,WORD PTR [DI.SDEVSTRAT] ;get strategy routine address;AN000;
272;Driver_Call: ;AN000;
273; MOV WORD PTR [CALLDEVAD],DX ; save it ;AN000;
274; MOV WORD PTR [CALLDEVAD+2],DS ; ;AN000;
275; CALL DWORD PTR [CALLDEVAD] ; call strategy routine ;AN000;
276;STRAT_Exit: ;AN000;
277; RET ; return ;AN000;
278
279;ENDPROC STRATEGY ;AN000;
280
281
282
283
284
285
286
287
288; ****************************************************************************
289; *
290; * MODULE: INTERRUPT
291; *
292; * FUNCTION: This procedure calls the interrupt routine of the drive
293; * specified in the drive#.
294; *
295; * INPUT: AL = Drive #
296; *
297; *
298; * OUTPUT: output of driver
299; *
300; *
301; * INTERNAL REFERENCES: None
302; *
303; *
304; * EXTERNAL REFERENCES: FIND_DPB
305; *
306; * NOTES: None
307; *
308; * REVISION HISTORY: New
309; *
310; *************************************************************************
311
312;PROCEDURE INTERRUPT,NEAR ;AN000;
313
314; INVOKE FIND_DPB ; get DPB from drive number ;AN000;
315; LDS DI,DS:[SI.DPB_Driver_Addr] ; get driver addres from DPB ;AN000;
316; MOV DX,WORD PTR [DI.SDEVINT] ; get interrupt routine addrs;AN000;
317; JMP Driver_Call ;AN000;
318
319;ENDPROC INTERRUPT ;AN000;
320
321
322
323
324
325
326
327
328; ************************************************************************* *
329; *
330; * MODULE: Get_Dos_Info
331; *
332; * FUNCTION: Get DOS information
333; *
334; * INPUT: AL = Dos info code
335; *
336; * OUTPUT: Dos Information in registers
337; *
338; * INTERNAL REFERENCES: None
339; *
340; *
341; * EXTERNAL REFERENCES: READTIME, $GETEXTCNTRY
342; *
343; * NOTES: None
344; *
345; * REVISION HISTORY: New
346; *
347; *************************************************************************
348
349PROCEDURE GET_DOS_INFO,NEAR ;AN000;
350
351 cmp al,0 ; TIME and DATE ?? ;AN000;
352 jne chk_al1 ;AN000;
353
354 Invoke ReadTime ; get time in CX:DX ;AN000;
355
356 push cx ; save time ;AN000;
357 push dx ;AN000;
358
359 MOV CX,[YEAR] ;AN000;
360 ADD CX,1980 ;AN000;
361 MOV DX,WORD PTR [DAY] ; fetch both day and month ;AN000;
362
363 pop bx ; bh = seconds bl = hundredths ;AN000;
364 pop ax ; ah = hour al = minutes ;AN000;
365 ; cx = year dh = month ;AN000;
366 jmp get_info_exit ;AN000;
367
368
369chk_al1: ; Active process info ?? ;AN000;
370 cmp al,1 ;AN000;
371 jne chk_al2 ; no, try next ;AN000;
372 MOV BX,[CurrentPDB] ; BX = active process ID ;AN000;
373 mov DX,[User_ID] ; User ID ;AN000;
374 jmp get_info_exit ; exit ;AN000;
375
376
377chk_al2: ;AN000;
378; cmp al,2 ; get CPSW info ?? ;AN000;
379; jne chk_al3 ; jump if not ;AN000;
380; MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG ;AN000;
381; MOV BX,[SI.ccDosCodePage] ; get dos code page id in BX ;AN000;
382; MOV DL,CPSWFLAG ; get CP Switch status ;AN000;
383; jmp get_info_exit ; exit ;AN000;
384
385
386chk_al3:
387; cmp al,3 ; get CTRL BRK status ?? ;AN000;
388; jne chk_al4 ;AN000;
389; mov dl,CNTCFLAG ; DL = break status flag ;AN000;
390; jmp get_info_exit ; exit ;AN000;
391
392
393chk_al4:
394; cmp al,4 ; get Verify status ?? ;AN000;
395; jne chk_al5
396; mov dl,VERFLG ; DL = verify status flag ;AN000;
397; jmp get_info_exit ; exit ;AN000;
398
399
400chk_al5:
401 cmp al,5 ; Config.sys info ?? ;AN000;
402 jne chk_al6 ;AN000;
403
404 mov si,OFFSET DOSGROUP:SYSINITVAR ; DS:SI-->SysInitVar ;AN000;
405 push ds ;AN000;
406 push si ;AN000;
407 lds si,[si].Sysi_SFT ; get SFT address ;AN000;
408 mov ax,[si].SFCount ; get number of files ;AN000;
409 lds si,[si].SFlink ; get next SFT table ;AN000;
410 cmp si,-1 ; end of table ;AN000;
411 jz nomore ; ;AN000;
412 add ax,[si].SFCount ; ;AN000;
413nomore: ; ;AN000;
414 mov es:[di].files,ax ; save files= value ;AN000;
415 pop si ;AN000;
416 pop ds ;AN000;
417 mov ax,[si].Sysi_MaxSec ; get maximum sector size ;AN000;
418 mov es:[di].secsize,ax ; save files= value ;AN000;
419 mov ax,[si].Sysi_Keep ; ;AN000;
420 mov es:[di].fcbs2,ax ; ;AN000;
421 lds si,[si].Sysi_FCB ; get FCB address ;AN000;
422 mov ax,[si].SFCount ; get number of fcbs ;AN000;
423 mov es:[di].fcbs1,ax ; save fcbs= value ;AN000;
424 jmp get_info_exit ;AN000;
425
426
427
428chk_al6: ;AN000;
429 cmp al,6 ; get machine name ?? ;AN000;
430 jne chk_al7 ; no, check next function ;AN000;
431 context DS ;AN000;
432 mov si,offset DOSGroup:MyName ; DS:SI-->name string ;AN000;
433 ; ES:DI-->return buffer ;AN000;
434 add di,2 ; skip max return size ;AN000;
435 mov cx,15 ; name size ;AN000;
436Chk6_Loop: ;AN000;
437 rep movsb ; copy machine name to return buffer;AN000;
438 xor al,al ; set 16th byte is 0 ;AN000;
439 stosb ;AN000;
440 jmp get_info_exit ; return ;AN000;
441 ;AN000;
442 ;AN000;
443Chk_Al7: ;AN000;
444; cmp al,7 ; get country information ?? ;AN000;
445; jne chk_al8 ; no, try next function ;AN000;
446; mov al,dl ; AL = info ID ;AN000;
447; mov bx,-1 ; select active code page ;AN000;
448; mov dx,-1 ; select active country ;AN000;
449; mov cx,-1 ; get all ;AN000;
450; INVOKE $getExtCntry ; get country info ;AN000;
451; jmp SHORT Get_Info_Exit ; exit ;AN000;
452
453
454Chk_Al8: ;AN000;
455 cmp al,8 ; get share retry count ?? ;AN000;
456 jne bad_param ; no, Bad parameter ;AN000;
457 mov bx,RetryCount ; BX = Share retry count ;AN000;
458 jmp SHORT Get_Info_Exit ; exit ;AN000;
459
460Bad_Param: ; Bad parameter ;AN000;
461 stc ; ;AN000;
462
463Get_Info_Exit: ; exit ;AN000;
464
465 ret ;AN000;
466
467
468ENDPROC GET_DOS_INFO ;AN000;
469
470
471
472
473
474
475
476
477; ************************************************************************* *
478; *
479; * MODULE: $IFS_IOCTL
480; *
481; * FUNCTION: Handle IFS Driver IOCTL calls
482; *
483; * INPUT: AH = 6B function code
484; * AL = XX 00 = Drive IOCTL, 01 = Psudo device IOCTL
485; * CX = 00 Reserved
486; * BL = XX Device Number
487; * DS:DX Pointer to Buffer
488; *
489; * OUTPUT:
490; * IF CARRY = 0 No Error
491; * IF CARRY = 1 Error
492; * AX = ERROR CODE
493; *
494; * INTERNAL REFERENCES: None
495; *
496; *
497; * EXTERNAL REFERENCES: INT 2F
498; *
499; * NOTES: None
500; *
501; * REVISION HISTORY: New
502; *************************************************************************
503
504PROCEDURE $IFS_IOCTL,NEAR ;AN000;
505
506 PUSH AX ;AN000;
507 MOV AX,(multnet SHL 8) OR 47 ; pass control to IFS Func ;AN000;
508 INT 2FH ;AN000;
509 POP BX ;AN000;
510 JC ABB_ERR ;AN000;
511 TRANSFER SYS_RET_OK ; return ;AN000;
512
513ABB_ERR: ;AN000;
514 transfer SYS_RET_ERR ; error return ;AN000;
515
516ENDPROC $IFS_IOCTL ;AN000;
517
518
519
520CODE ENDS ;AN000;
521 END ;AN000;
522
523
diff --git a/v4.0/src/DOS/IOCTL.ASM b/v4.0/src/DOS/IOCTL.ASM
new file mode 100644
index 0000000..8007244
--- /dev/null
+++ b/v4.0/src/DOS/IOCTL.ASM
@@ -0,0 +1,745 @@
1; SCCSID = @(#)IOCTL.INC 1.15 85/09/05
2TITLE IOCTL - IOCTL system call
3NAME IOCTL
4
5;
6;
7; IOCTL system call.
8;
9;
10; $IOCTL
11;
12; Revision history:
13;
14; Created: ARR 4 April 1983
15;
16; GenericIOCTL added: KGS 22 April 1985
17;
18; A000 version 4.00 Jan. 1988
19
20
21
22.xlist
23;
24; get the appropriate segment definitions
25;
26include dosseg.asm
27
28CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME SS:DOSGROUP,CS:DOSGROUP
30
31.xcref
32INCLUDE DOSSYM.INC
33INCLUDE DEVSYM.INC
34include ioctl.inc
35include ifssym.inc ;AN000;
36.cref
37.list
38
39 i_need THISCDS,DWORD
40 i_need IOCALL,BYTE
41 i_need IOMED,BYTE
42 i_need IOSCNT,WORD
43 i_need IOXAD,DWORD
44 I_need RetryCount,WORD
45 I_need RetryLoop,WORD
46 I_need EXTERR_LOCUS,BYTE
47 I_need OPENBUF,BYTE
48 I_need ExtErr,WORD
49 I_need DrvErr,BYTE
50 I_need USER_IN_AX,WORD ;AN000;
51 I_need Temp_Var2,WORD ;AN000;
52
53BREAK <IOCTL - munge on a handle to do device specific stuff>
54
55;
56; Assembler usage:
57; MOV BX, Handle
58; MOV DX, Data
59;
60; (or LDS DX,BUF
61; MOV CX,COUNT)
62;
63; MOV AH, Ioctl
64; MOV AL, Request
65; INT 21h
66;
67; AH = 0 Return a combination of low byte of sf_flags and device driver
68; attribute word in DX, handle in BX:
69; DH = high word of device driver attributes
70; DL = low byte of sf_flags
71; 1 Set the bits contained in DX to sf_flags. DH MUST be 0. Handle
72; in BX.
73; 2 Read CX bytes from the device control channel for handle in BX
74; into DS:DX. Return number read in AX.
75; 3 Write CX bytes to the device control channel for handle in BX from
76; DS:DX. Return bytes written in AX.
77; 4 Read CX bytes from the device control channel for drive in BX
78; into DS:DX. Return number read in AX.
79; 5 Write CX bytes to the device control channel for drive in BX from
80; DS:DX. Return bytes written in AX.
81; 6 Return input status of handle in BX. If a read will go to the
82; device, AL = 0FFh, otherwise 0.
83; 7 Return output status of handle in BX. If a write will go to the
84; device, AL = 0FFh, otherwise 0.
85; 8 Given a drive in BX, return 1 if the device contains non-
86; removable media, 0 otherwise.
87; 9 Return the contents of the device attribute word in DX for the
88; drive in BX. 0200h is the bit for shared. 1000h is the bit for
89; network. 8000h is the bit for local use.
90; A Return 8000h if the handle in BX is for the network or not.
91; B Change the retry delay and the retry count for the system. BX is
92; the count and CX is the delay.
93;
94; Error returns:
95; AX = error_invalid_handle
96; = error_invalid_function
97; = error_invalid_data
98;
99;-------------------------------------------------------------------------------
100;
101; This is the documentation copied from DOS 4.0 it is much better
102; than the above
103;
104; There are several basic forms of IOCTL calls:
105;
106;
107; ** Get/Set device information: **
108;
109; ENTRY (AL) = function code
110; 0 - Get device information
111; 1 - Set device information
112; (BX) = file handle
113; (DX) = info for "Set Device Information"
114; EXIT 'C' set if error
115; (AX) = error code
116; 'C' clear if OK
117; (DX) = info for "Get Device Information"
118; USES ALL
119;
120;
121; ** Read/Write Control Data From/To Handle **
122;
123; ENTRY (AL) = function code
124; 2 - Read device control info
125; 3 - Write device control info
126; (BX) = file handle
127; (CX) = transfer count
128; (DS:DX) = address for data
129; EXIT 'C' set if error
130; (AX) = error code
131; 'C' clear if OK
132; (AX) = count of bytes transfered
133; USES ALL
134;
135;
136; ** Read/Write Control Data From/To Block Device **
137;
138; ENTRY (AL) = function code
139; 4 - Read device control info
140; 5 - Write device control info
141; (BL) = Drive number (0=default, 1='A', 2='B', etc)
142; (CX) = transfer count
143; (DS:DX) = address for data
144; EXIT 'C' set if error
145; (AX) = error code
146; 'C' clear if OK
147; (AX) = count of bytes transfered
148; USES ALL
149;
150;
151; ** Get Input/Output Status **
152;
153; ENTRY (AL) = function code
154; 6 - Get Input status
155; 7 - Get Output Status
156; (BX) = file handle
157; EXIT 'C' set if error
158; (AX) = error code
159; 'C' clear if OK
160; (AL) = 00 if not ready
161; (AL) = FF if ready
162; USES ALL
163;
164;
165; ** Get Drive Information **
166;
167; ENTRY (AL) = function code
168; 8 - Check for removable media
169; 9 - Get device attributes
170; (BL) = Drive number (0=default, 1='A', 2='B', etc)
171; EXIT 'C' set if error
172; (AX) = error code
173; 'C' clear if OK
174; (AX) = 0/1 media is removable/fixed (func. 8)
175; (DX) = device attribute word (func. 9)
176; USES ALL
177;
178;
179; ** Get Redirected bit **
180;
181; ENTRY (AL) = function code
182; 0Ah - Network stuff
183; (BX) = file handle
184; EXIT 'C' set if error
185; (AX) = error code
186; 'C' clear if OK
187; (DX) = SFT flags word, 8000h set if network file
188; USES ALL
189;
190;
191; ** Change sharer retry parameters **
192;
193; ENTRY (AL) = function code
194; 0Bh - Set retry parameters
195; (CX) = retry loop count
196; (DX) = number of retries
197; EXIT 'C' set if error
198; (AX) = error code
199; 'C' clear if OK
200; USES ALL
201;
202;
203; =================================================================
204;
205; ** New Standard Control **
206;
207; ALL NEW IOCTL FACILITIES SHOULD USE THIS FORM. THE OTHER
208; FORMS ARE OBSOLETE.
209;
210; =================================================================
211;
212; ENTRY (AL) = function code
213; 0Ch - Control Function subcode
214; (BX) = File Handle
215; (CH) = Category Indicator
216; (CL) = Function within category
217; (DS:DX) = address for data, if any
218; (SI) = Passed to device as argument, use depends upon function
219; (DI) = Passed to device as argument, use depends upon function
220; EXIT 'C' set if error
221; (AX) = error code
222; 'C' clear if OK
223; (SI) = Return value, meaning is function dependent
224; (DI) = Return value, meaning is function dependent
225; (DS:DX) = Return address, use is function dependent
226; USES ALL
227;
228; ============== Generic IOCTL Definitions for DOS 3.2 ============
229; (See dos/ioctl.mac for more info)
230;
231; ENTRY (AL) = function code
232; 0Dh - Control Function subcode
233; (BL) = Drive Number (0 = Default, 1= 'A')
234; (CH) = Category Indicator
235; (CL) = Function within category
236; (DS:DX) = address for data, if any
237; (SI) = Passed to device as argument, use depends upon function
238; (DI) = Passed to device as argument, use depends upon function
239;
240; EXIT 'C' set if error
241; (AX) = error code
242; 'C' clear if OK
243; (DS:DX) = Return address, use is function dependent
244; USES ALL
245;
246
247 procedure $IOCTL,NEAR
248 ASSUME DS:NOTHING,ES:NOTHING
249 MOV SI,DS ; Stash DS for calls 2,3,4 and 5
250 context DS
251 CMP AL,3
252 JBE ioctl_check_char ; char device
253 JMP ioctl_check_block ; Block device
254ioctl_check_char:
255 invoke SFFromHandle ; ES:DI -> SFT
256 JNC ioctl_check_permissions ; have valid handle
257ioctl_bad_handle:
258 error error_invalid_handle
259
260ioctl_check_permissions:
261 CMP AL,2
262 JAE ioctl_control_string
263 CMP AL,0
264 MOV AL,BYTE PTR ES:[DI.sf_flags]; Get low byte of flags
265 JZ ioctl_read ; read the byte
266 PUSH DX ;AN000;MS.
267 AND DH,0FEH ;AN000;MS.allow DH=01H
268 POP DX ;AN000;MS.
269 JZ ioctl_check_device ; can I set with this data?
270 error error_invalid_data ; no DH <> 0
271
272ioctl_bad_funj2:
273 JMP ioctl_bad_fun
274
275ioctl_check_device:
276 TEST AL,devid_device ; can I set this handle?
277 JZ do_exception ; no, it is a file.
278 OR DL,devid_device ; Make sure user doesn't turn off the
279 ; device bit!! He can muck with the
280 ; others at will.
281 MOV [EXTERR_LOCUS],errLOC_SerDev
282 MOV BYTE PTR ES:[DI.sf_flags],DL ;AC000;MS.; Set flags
283do_exception:
284 OR BYTE PTR ES:[DI.sf_flags+1],DH;AN000;MS.;set 100H bit for disk full
285
286 transfer SYS_RET_OK
287
288
289
290
291
292ioctl_read:
293 MOV [EXTERR_LOCUS],errLOC_Disk
294 XOR AH,AH
295 TEST AL,devid_device ; Should I set high byte
296 JZ ioctl_no_high ; no
297 MOV [EXTERR_LOCUS],errLOC_SerDev
298 LES DI,ES:[DI.sf_devptr] ; Get device pointer
299 MOV AH,BYTE PTR ES:[DI.SDEVATT+1] ; Get high byte
300ioctl_no_high:
301 MOV DX,AX
302 invoke get_user_stack
303 MOV [SI.user_DX],DX
304 transfer SYS_RET_OK
305
306ioctl_control_string:
307 TEST ES:[DI.sf_flags],devid_device ; can I?
308 JNZ ioctl_ctl_str_1
309 JMP ioctl_bad_fun ; No it is a file
310ioctl_ctl_str_1:
311 TEST ES:[DI.sf_flags],sf_isnet ;AN000;IFS.; IFS ?
312 JZ localrw ;AN000;IFS.; no
313 JMP callifs ;AN000;IFS.; call IFS
314localrw:
315 MOV [EXTERR_LOCUS],errLOC_SerDev
316 LES DI,ES:[DI.sf_devptr] ; Get device pointer
317 XOR BL,BL ; Unit number of char dev = 0
318 JMP ioctl_do_string
319
320ioctl_get_devj:
321 JMP ioctl_get_dev
322
323ioctl_check_block:
324 DEC AL
325 DEC AL ; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9
326 CMP AL,3
327 JBE ioctl_get_devj
328 CMP AL,6
329 JAE ioctl_rem_media_check
330
331 MOV AH,1
332 SUB AL,4 ; 6=0,7=1
333 JZ ioctl_get_status
334 MOV AH,3
335ioctl_get_status:
336 PUSH AX
337 invoke GET_IO_SFT
338 POP AX
339 JNC DO_IOFUNC
340 JMP ioctl_bad_handle ; invalid SFT
341
342DO_IOFUNC:
343 invoke IOFUNC
344 MOV AH,AL
345 MOV AL,0FFH
346 JNZ ioctl_status_ret
347 INC AL
348ioctl_status_ret:
349 transfer SYS_RET_OK
350
351ioctl_rem_media_check: ; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9
352 JE ioctl_rem_mediaj
353
354 SUB AL,7 ; 9=0,10=1,11=2,12=3,13=4,14=5,15=6
355 JNZ Rem_med_chk_1
356 JMP Ioctl_Drive_attr
357
358ioctl_rem_mediaj:
359 jmp ioctl_rem_media
360
361ioctl_bad_funj4:
362 jmp ioctl_bad_fun
363
364Rem_med_chk_1:
365
366 DEC AL ; 10=0,11=1,12=2,13=3,14=4,15=5
367 jnz Set_Retry_chk
368 Jmp Ioctl_Handle_redirj
369
370Set_Retry_chk:
371 DEC AL ; 11=0,12=1,13=2,14=3,15=4
372 JZ Set_Retry_Parameters
373
374 DEC AL ; 12=0,13=1,14=2,15=3
375 JZ GENERICIOCTLHANDLE
376
377 DEC AL ; 13=0,14=1,15=2
378 JZ GENERICIOCTL
379
380 CMP AL,2
381 JA ioctl_bad_funj4
382 JMP ioctl_drive_owner
383Set_Retry_Parameters:
384 MOV RetryLoop,CX ; 0 retry loop count allowed
385 OR DX,DX ; zero retries not allowed
386 JNZ goodtr
387 JMP IoCtl_Bad_Fun
388goodtr:
389 MOV RetryCount,DX ; Set new retry count
390doneok:
391 transfer Sys_Ret_Ok ; Done
392
393; Generic IOCTL entry point.
394; here we invoke the Generic IOCTL using the IOCTL_Req structure.
395; SI:DX -> Users Device Parameter Table
396; IOCALL -> IOCTL_Req structure
397GENERICIOCTLHANDLE:
398 invoke SFFromHandle ; Get SFT for device.
399 jnc goodh
400 JMP ioctl_bad_handlej
401goodh:
402; test word ptr [DI.sf_flags],sf_isnet
403 CALL TEST_IFS_REMOTE ;AN000;;IFS. test if remote
404 JZ okokok ;AN000;;IFS.
405 jmp ioctl_bad_fun ; Cannot do this over net.
406okokok:
407 TEST [DI.sf_flags],sf_isnet ;AN000;IFS.; local IFS
408 JNZ callifs ;AN000;IFS.; yes
409
410
411 mov [EXTERR_LOCUS],ErrLOC_Serdev
412 les di,es:[di.sf_devptr] ; Get pointer to device.
413 jmp short Do_GenIOCTL
414
415GENERICIOCTL:
416 mov [EXTERR_LOCUS],ErrLOC_Disk
417 cmp ch,IOC_DC ; Only disk devices are allowed to use
418 jne ioctl_bad_fun ; no handles with Generic IOCTL.
419 CALL Check_If_Net ; ES:DI := Get_hdr_block of device in BL
420 JNZ ioctl_bad_fun ; There are no "net devices", and they
421 PUSH ES ; certainly don't know how to do this ;AN000;
422 PUSH DI ;AN000;IFS.
423 LES DI,[THISCDS] ;AN000;IFS. ;
424 TEST ES:[DI.curdir_flags],curdir_isnet;AN000;IFS. ; local IFS ?
425 POP DI ;AN000;IFS.
426 POP ES ;AN000;IFS.
427 JZ Do_GenIOCTL ;AN000;IFS. ; no
428callifs:
429 CMP byte ptr [User_In_AX+1],69H ;AN000; ;IFS.
430 JNZ is44xx ;AN000; ;IFS.
431 MOV AX,440DH ;AN000; ;IFS.
432 PUSH AX ;AN000; ;IFS.
433 JMP SHORT callrose ;AN000; ;IFS.
434is44xx:
435 PUSH [User_In_AX] ;AN000; ;IFS. call IFSFUNC
436callrose:
437 MOV DS,SI ;AN000; ;IFS.
438 MOV AX,(multNET SHL 8) or 43 ;AN000; ;IFS.
439 INT 2FH ;AN000; ;IFS.
440 POP BX ;AN000; ;IFS.
441 JNC doneok ;AN000; ;IFS.
442 MOV DI,AX ;AN000; ;IFS.
443 JMP device_err ;AN000; ;IFS.
444Do_GenIOCTL:
445 test ES:[DI.SDEVATT],DEV320 ; Can device handle Generic IOCTL funcs
446 jz ioctl_bad_fun
447 PUSH ES ; DEVIOCALL2 expects Device header block
448 PUSH DI ; in DS:SI
449 ;set up Generic IOCTL Request Block
450 MOV byte ptr IOCALL.ReqLen,(size IOCTL_Req)
451 MOV byte ptr IOCALL.ReqFunc,GENIOCTL
452 MOV byte ptr IOCALL.ReqUnit,BL
453 MOV byte ptr IOCALL.MajorFunction,CH
454 MOV byte ptr IOCALL.MinorFunction,CL
455 MOV word ptr IOCALL.Reg_SI,SI
456 MOV word ptr IOCALL.Reg_DI,DI
457 MOV word ptr IOCALL.GenericIOCTL_Packet,DX
458 MOV word ptr IOCALL.GenericIOCTL_Packet + 2,SI
459
460 MOV BX,offset DOSGROUP:IOCALL
461
462 PUSH SS
463 POP ES
464
465ASSUME DS:NOTHING ; DS:SI -> Device header.
466 POP SI
467 POP DS
468 jmp ioctl_do_IO ; Perform Call to device driver
469
470IOCtl_Handle_RedirJ:
471 JMP IOCTL_Handle_Redir
472ioctl_bad_fun:
473 error error_invalid_function
474
475ioctl_bad_handlej:
476 jmp ioctl_bad_handle
477
478; Function 8
479ioctl_rem_media:
480 CALL Check_If_Net
481 JNZ ioctl_bad_fun ; There are no "net devices", and they
482 ; certainly don't know how to do this
483 ; call.
484 TEST ES:[DI.SDEVATT],DEVOPCL ; See if device can
485 JZ ioctl_bad_fun ; NO
486 MOV [IOCALL.REQFUNC],DEVRMD
487 MOV AL,REMHL
488 MOV AH,BL ; Unit number
489 MOV WORD PTR [IOCALL.REQLEN],AX
490 XOR AX,AX
491 MOV [IOCALL.REQSTAT],AX
492 PUSH ES
493 POP DS
494ASSUME DS:NOTHING
495 MOV SI,DI ; DS:SI -> driver
496 PUSH SS
497 POP ES
498 MOV BX,OFFSET DOSGROUP:IOCALL ; ES:BX -> Call header
499 SaveReg <DS,SI>
500 invoke DEVIOCALL2
501 RestoreReg <SI,DS>
502 MOV AX,[IOCALL.REQSTAT] ; Get Status word
503 AND AX,STBUI ; Mask to busy bit
504 MOV CL,9
505 SHR AX,CL ; Busy bit to bit 0
506 transfer SYS_RET_OK
507
508; Function 9
509Ioctl_Drive_attr:
510
511;;;;; MOV AL,BL ;AC000;; Drive
512;;;;; invoke GETTHISDRV ;AC000;
513;;;;; ;AC000;
514;;;;; JC ioctl_drv_err ; drive not valid
515 call Get_Driver_BL
516 JC ioctl_drv_err ; drive not valid
517 MOV AX,[Temp_Var2] ;AN000;IFS.
518 mov dx,word ptr es:[di.SDEVATT] ; get device attribute word
519 MOV BL,AL ; Phys letter to BL (A=0)
520 LES DI,[THISCDS]
521;;;;; TEST ES:[DI.curdir_flags],curdir_isnet
522 CALL TEST_IFS_REMOTE2 ;AN000;IFS. test if remote
523 JZ IOCTLShare
524 OR DX,1000h
525IOCTLShare:
526 Context DS
527ASSUME DS:NOTHING
528 MOV SI,OFFSET DOSGROUP:OPENBUF
529 ADD BL,"A"
530 MOV [SI],BL
531 MOV WORD PTR [SI+1],003AH ; ":",0
532 MOV AX,0300H
533 CLC
534 INT int_IBM
535 JNC ioctlLocal ; Not shared
536 OR DX,0200H ; Shared, bit 9
537IOCTLLocal:
538 TEST ES:[DI].curdir_flags,curdir_local
539 JZ ioctl_set_dx
540 OR DX,8000h
541
542ioctl_set_DX:
543 invoke get_user_stack
544 MOV [SI.user_DX],DX
545 transfer SYS_RET_OK
546
547ioctl_drv_err:
548 MOV AL,[DrvErr] ;AN000;IFS. DrvErr is saved in GetThisDrv
549 transfer SYS_RET_ERR ;AN000;IFS.
550
551; Function 10
552Ioctl_Handle_redir:
553 invoke SFFromHandle ; ES:DI -> SFT
554 JNC ioctl_got_sft ; have valid handle
555 error error_invalid_handle
556
557ioctl_got_sft:
558 MOV DX,ES:[DI.sf_flags] ; Get flags
559 JMP ioctl_set_DX
560
561ioctl_bad_funj:
562 JMP ioctl_bad_fun
563
564ioctl_get_dev:
565 DOSAssume CS,<DS>,"IOCTL/IOCtl_Get_Dev"
566 CALL Check_If_Net
567 JNZ ioctl_bad_funj ; There are no "net devices", and they
568 ; certainly don't know how to do this
569 ; call.
570ioctl_do_string:
571 TEST ES:[DI.SDEVATT],DEVIOCTL; See if device accepts control
572 JZ ioctl_bad_funj ; NO
573 DEC AL
574 DEC AL
575 JZ ioctl_control_read
576 MOV [IOCALL.REQFUNC],DEVWRIOCTL
577 JMP SHORT ioctl_control_call
578ioctl_control_read:
579 MOV [IOCALL.REQFUNC],DEVRDIOCTL
580ioctl_control_call:
581 MOV AL,DRDWRHL
582ioctl_setup_pkt:
583 MOV AH,BL ; Unit number
584 MOV WORD PTR [IOCALL.REQLEN],AX
585 XOR AX,AX
586 MOV [IOCALL.REQSTAT],AX
587 MOV [IOMED],AL
588 MOV [IOSCNT],CX
589 MOV WORD PTR [IOXAD],DX
590 MOV WORD PTR [IOXAD+2],SI
591 PUSH ES
592 POP DS
593ASSUME DS:NOTHING
594 MOV SI,DI ; DS:SI -> driver
595 PUSH SS
596 POP ES
597 MOV BX,OFFSET DOSGROUP:IOCALL ; ES:BX -> Call header
598ioctl_do_IO:
599 invoke DEVIOCALL2
600 TEST [IOCALL.REQSTAT],STERR ;Error?
601 JNZ Ioctl_string_err
602 MOV AX,[IOSCNT] ; Get actual bytes transferred
603 transfer SYS_RET_OK
604
605Ioctl_string_err:
606 MOV DI,[IOCALL.REQSTAT] ;Get Error
607device_err:
608 AND DI,STECODE ; mask out irrelevant bits
609 MOV AX,DI
610 invoke SET_I24_EXTENDED_ERROR
611 mov ax, cs:extErr
612 transfer SYS_RET_ERR
613
614Get_Driver_BL:
615 DOSAssume CS,<DS>,"Get_Driver_BL"
616 ASSUME ES:NOTHING
617; BL is drive number (0=default)
618; Returns pointer to device in ES:DI, unit number in BL if carry clear
619; No regs modified
620
621 PUSH AX
622 MOV AL,BL ; Drive
623 invoke GETTHISDRV
624 JNC ioctl_goodrv ;AC000;IFS.
625 CMP AL,error_not_dos_disk ;AN000;IFS. if unknow media then
626 JZ ioctl_goodrv ;AN000;IFS. let it go
627 STC ;AN000;IFS. else
628 JMP SHORT ioctl_bad_drv ;AN000;IFS. error
629ioctl_goodrv:
630 XOR BL,BL ; Unit zero on Net device
631 MOV [EXTERR_LOCUS],errLOC_Net
632 LES DI,[THISCDS]
633; TEST ES:[DI.curdir_flags],curdir_isnet
634 CALL TEST_IFS_REMOTE2 ;AN000;;IFS. test if remote
635 LES DI,ES:[DI.curdir_devptr]; ES:DI -> Dpb or net dev
636 JNZ got_dev_ptr ; Is net
637 MOV [EXTERR_LOCUS],errLOC_Disk
638 MOV BL,ES:[DI.dpb_UNIT] ; Unit number
639 LES DI,ES:[DI.dpb_driver_addr] ; Driver addr
640got_dev_ptr:
641 CLC
642 MOV [Temp_Var2],AX ;AN000;IFS.
643ioctl_bad_drv:
644 POP AX
645 return
646
647;
648; Checks if the device is over the net or not. Returns result in ZERO flag.
649; If no device is found, the return address is popped off the stack, and a
650; jump is made to ioctl_drv_err.
651;
652; On Entry:
653; Registers same as those for Get_Driver_BL
654;
655; On Exit:
656; ZERO flag - set if not a net device
657; - reset if net device
658; ES:DI -> the device
659;
660Check_If_Net:
661 CALL Get_Driver_BL
662 JC ioctl_drv_err_pop ; invalid drive letter
663entry TEST_IFS_REMOTE2
664 PUSH ES
665 PUSH DI
666 LES DI,[THISCDS]
667 TEST ES:[DI.curdir_flags],curdir_isnet
668 JZ belocal ;AN000; ;IFS.
669 LES DI,ES:[DI.curdir_ifs_hdr] ;AN000; ;IFS. test if remote
670TEST_REMOTE: ;AN000;
671 TEST ES:[DI.ifs_attribute],IFSREMOTE;AN000; ;IFS.
672belocal:
673 POP DI
674 POP ES
675 ret
676
677ioctl_drv_err_pop:
678 pop ax ; pop off return address
679 jmp ioctl_drv_err
680
681ioctl_bad_funj3:
682 jmp ioctl_bad_fun
683
684ioctl_string_errj:
685 jmp ioctl_string_err
686
687; Functions 14 and 15
688ioctl_drive_owner:
689 Call Check_If_Net
690 JNZ ioctl_bad_funj3 ; There are no "net devices", and they
691 ; certainly don't know how to do this
692 ; call.
693 TEST ES:[DI.SDEVATT],DEV320 ; See if device can handle this
694 JZ ioctl_bad_funj3 ; NO
695 dec al
696 jz GetOwner
697 MOV [IOCALL.REQFUNC],DEVSETOWN
698 jmp short ioctl_do_own
699GetOwner:
700 MOV [IOCALL.REQFUNC],DEVGETOWN
701ioctl_do_own:
702 MOV AL,OWNHL
703 MOV AH,BL ; Unit number
704 MOV WORD PTR [IOCALL.REQLEN],AX
705 XOR AX,AX
706 MOV [IOCALL.REQSTAT],AX
707 PUSH ES
708 POP DS
709ASSUME DS:NOTHING
710 MOV SI,DI ; DS:SI -> driver
711 PUSH SS
712 POP ES
713 MOV BX,OFFSET DOSGROUP:IOCALL ; ES:BX -> Call header
714 SaveReg <DS,SI>
715 invoke DEVIOCALL2
716 RestoreReg <SI,DS>
717 test [IOCALL.REQSTAT],STERR
718 jnz ioctl_string_errj
719 MOV AL,BYTE PTR [IOCALL.REQUNIT] ; Get owner returned by device
720 ; owner returned is 1-based.
721 transfer SYS_RET_OK
722
723EndProc $IOCTL
724
725
726;Input: ES:DI -> SFT
727;Functions: test if a remote file
728;Output: Z flag set, local file
729;
730
731 procedure TEST_IFS_REMOTE,NEAR ;AN000;
732 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
733
734 TEST ES:[DI.sf_flags],sf_isnet ;AN000;;IFS. ifs ?
735 JZ nonifs ;AN000;;IFS. no
736 PUSH ES ;AN000;;IFS. save regs
737 PUSH DI ;AN000;;IFS.
738 LES DI,ES:[DI.sf_IFS_hdr] ;AN000;;IFS. get ifs header
739 JMP TEST_REMOTE ;AN000;;IFS.
740nonifs: ;AN000;
741 return ;AN000;;IFS.
742EndProc TEST_IFS_REMOTE ;AN000;
743
744CODE ENDS
745END
diff --git a/v4.0/src/DOS/ISEARCH.ASM b/v4.0/src/DOS/ISEARCH.ASM
new file mode 100644
index 0000000..bfae821
--- /dev/null
+++ b/v4.0/src/DOS/ISEARCH.ASM
@@ -0,0 +1,364 @@
1; SCCSID = @(#)isearch.asm 1.1 85/04/10
2TITLE DOS_SEARCH - Internal SEARCH calls for MS-DOS
3NAME DOS_SEARCH
4; Low level routines for doing local and NET directory searches
5;
6; DOS_SEARCH_FIRST
7; DOS_SEARCH_NEXT
8; RENAME_NEXT
9;
10; Revision history:
11;
12; Created: ARR 30 March 1983
13; A000 version 4.00 Jan. 1988
14; A001 PTM 3564 -- serach for fastopen
15
16;
17; get the appropriate segment definitions
18;
19.xlist
20include dosseg.asm
21
22CODE SEGMENT BYTE PUBLIC 'CODE'
23 ASSUME SS:DOSGROUP,CS:DOSGROUP
24
25.xcref
26INCLUDE DOSSYM.INC
27INCLUDE DEVSYM.INC
28INCLUDE fastopen.inc
29INCLUDE fastxxxx.inc
30.cref
31.list
32
33Installed = TRUE
34
35 i_need NoSetDir,BYTE
36 i_need Creating,BYTE
37 i_need THISCDS,DWORD
38 i_need CURBUF,DWORD
39 i_need DMAADD,DWORD
40 i_need DummyCDS,128
41 i_need THISDPB,DWORD
42 i_need THISDRV,BYTE
43 i_need NAME1,BYTE
44 i_need ATTRIB,BYTE
45 i_need DIRSTART,WORD
46 i_need LASTENT,WORD
47 i_need FOUND_DEV,BYTE
48 I_need WFP_Start,WORD
49 i_need EXTERR_LOCUS,BYTE
50 i_need FastopenFlg,BYTE
51 I_need DOS34_FLAG,WORD
52
53; Inputs:
54; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
55; terminated)
56; [CURR_DIR_END] Points to end of Current dir part of string
57; ( = -1 if current dir not involved, else
58; Points to first char after last "/" of current dir part)
59; [THISCDS] Points to CDS being used
60; (Low word = -1 if NUL CDS (Net direct request))
61; [SATTRIB] Is attribute of search, determines what files can be found
62; [DMAADD] Points to 53 byte buffer
63; Function:
64; Initiate a search for the given file spec
65; Outputs:
66; CARRY CLEAR
67; The 53 bytes ot DMAADD are filled in as follows:
68;
69; LOCAL
70; Drive Byte (A=1, B=2, ...) High bit clear
71; NEVER STORE DRIVE BYTE AFTER found_it
72; 11 byte search name with Meta chars in it
73; Search Attribute Byte, attribute of search
74; WORD LastEnt value
75; WORD DirStart
76; 4 byte pad
77; 32 bytes of the directory entry found
78; NET
79; 21 bytes First byte has high bit set
80; 32 bytes of the directory entry found
81;
82; CARRY SET
83; AX = error code
84; error_no_more_files
85; No match for this file
86; error_path_not_found
87; Bad path (not in curr dir part if present)
88; error_bad_curr_dir
89; Bad path in current directory part of path
90; DS preserved, others destroyed
91
92 procedure DOS_SEARCH_FIRST,NEAR
93 DOSAssume CS,<DS>,"DOS_Search_First"
94 ASSUME ES:NOTHING
95
96 LES DI,[THISCDS]
97 CMP DI,-1
98 JNZ TEST_RE_NET
99IF NOT Installed
100 transfer NET_SEQ_SEARCH_FIRST
101ELSE
102 MOV AX,(multNET SHL 8) OR 25
103 INT 2FH
104 return
105ENDIF
106
107TEST_RE_NET:
108 TEST ES:[DI.curdir_flags],curdir_isnet
109 JZ LOCAL_SEARCH_FIRST
110IF NOT Installed
111 transfer NET_SEARCH_FIRST
112ELSE
113 MOV AX,(multNET SHL 8) OR 27
114 INT 2FH
115 return
116ENDIF
117
118LOCAL_SEARCH_FIRST:
119 EnterCrit critDisk
120 TEST [DOS34_FLAG],SEARCH_FASTOPEN ;AN000;
121 JZ NOFN ;AN000;
122 OR [FastOpenflg],Fastopen_Set ;AN000;
123NOFN: ;AN000;
124 MOV [NoSetDir],1 ; if we find a dir, don't change to it
125 CALL CHECK_QUESTION ;AN000;;FO. is '?' in path
126 JNC norm_getpath ;AN000;;FO. no
127 AND [FastOpenflg],Fast_yes ;AN000;;FO. reset fastopen
128norm_getpath:
129 invoke GetPath
130getdone:
131 JNC find_check_dev
132 JNZ bad_path
133 OR CL,CL
134 JZ bad_path
135find_no_more:
136 MOV AX,error_no_more_files
137BadBye:
138 AND CS:[FastOpenflg],Fast_yes ;AN000;;FO. reset fastopen
139
140 STC
141 LeaveCrit critDisk
142 return
143
144bad_path:
145 MOV AX,error_path_not_found
146 JMP BadBye
147
148find_check_dev:
149 OR AH,AH
150 JNS found_entry
151 MOV [LastEnt],-1 ; Cause DOS_SEARCH_NEXT to fail
152 INC [Found_Dev] ; Tell DOS_RENAME we found a device
153found_entry:
154;
155; We set the physical drive byte here Instead of after found_it; Doing
156; a search-next may not have wfp_start set correctly
157;
158 LES DI,[DMAADD]
159 MOV SI,WFP_Start ; get pointer to beginning
160 LODSB
161 SUB AL,'A'-1 ; logical drive
162 STOSB ; High bit not set (local)
163found_it:
164 LES DI,[DMAADD]
165 INC DI
166 PUSH DS ;FO.;AN001; save ds
167 TEST [Fastopenflg],Set_For_Search ;FO.;AN001; from fastopen
168 JZ notfast ;FO.;AN001;
169 MOV SI,BX ;FO.;AN001;
170 MOV DS,WORD PTR [CURBUF+2] ;FO.;AN001;
171 JMP SHORT movmov ;FO.;AN001;
172
173
174notfast:
175 MOV SI,OFFSET DOSGROUP:NAME1; find_buf 2 = formatted name
176movmov:
177; Special E5 code
178 MOVSB
179 CMP BYTE PTR ES:[DI-1],5
180 JNZ NOTKANJB
181 MOV BYTE PTR ES:[DI-1],0E5H
182NOTKANJB:
183
184 MOV CX,10
185 REP MOVSB
186 POP DS ;FO.;AN001; restore ds
187
188
189 MOV AL,[Attrib]
190 STOSB
191 PUSH AX ; Save AH device info
192 MOV AX,[LastEnt]
193 STOSW
194 MOV AX,[DirStart]
195 STOSW
196; 4 bytes of 21 byte cont structure left for NET stuff
197 ADD DI,4
198 POP AX ; Recover AH device info
199 OR AH,AH
200 JS DOSREL ; Device entry is DOSGROUP relative
201 CMP WORD PTR [CURBUF],-1
202 JNZ OKSTORE
203 TEST [FastOPenFlg],Set_For_Search ;AN000;;FO. from fastopen and is good
204 JNZ OKSTORE ;AN000;;FO.
205
206
207
208 ; The user has specified the root directory itself, rather than some
209 ; contents of it. We can't "find" that.
210 MOV WORD PTR ES:[DI-8],-1 ; Cause DOS_SEARCH_NEXT to fail by
211 ; stuffing a -1 at Lastent
212 JMP find_no_more
213
214OKSTORE:
215 MOV DS,WORD PTR [CURBUF+2]
216ASSUME DS:NOTHING
217DOSREL:
218 MOV SI,BX ; SI-> start of entry
219
220; NOTE: DOS_RENAME depends on BX not being altered after this point
221
222 MOV CX,SIZE dir_entry
223;;;;; 7/29/86
224 MOV AX,DI ; save the 1st byte addr
225 REP MOVSB
226 MOV DI,AX ; restore 1st byte addr
227 CMP BYTE PTR ES:[DI],05H ; special char check
228 JNZ NO05
229 MOV BYTE PTR ES:[DI],0E5H ; convert it back to E5
230NO05:
231
232;;;;; 7/29/86
233 AND CS:[FastOpenflg],Fast_yes ;AN000;;FO. reset fastopen
234 context DS
235 CLC
236 LeaveCrit critDisk
237 return
238
239EndProc DOS_SEARCH_FIRST
240
241BREAK <DOS_SEARCH_NEXT - scan for subsequent matches>
242
243; Inputs:
244; [DMAADD] Points to 53 byte buffer returned by DOS_SEARCH_FIRST
245; (only first 21 bytes must have valid information)
246; Function:
247; Look for subsequent matches
248; Outputs:
249; CARRY CLEAR
250; The 53 bytes at DMAADD are updated for next call
251; (see DOS_SEARCH_FIRST)
252; CARRY SET
253; AX = error code
254; error_no_more_files
255; No more files to find
256; DS preserved, others destroyed
257
258 procedure DOS_SEARCH_NEXT,NEAR
259 DOSAssume CS,<DS>,"DOS_Search_Next"
260 ASSUME ES:NOTHING
261
262 LES DI,[DMAADD]
263 MOV AL,ES:[DI]
264 TEST AL,80H ; Test for NET
265 JZ LOCAL_SEARCH_NEXT
266IF NOT Installed
267 transfer NET_SEARCH_NEXT
268ELSE
269 MOV AX,(multNET SHL 8) OR 28
270 INT 2FH
271 return
272ENDIF
273
274LOCAL_SEARCH_NEXT:
275;AL is drive A=1
276 MOV [EXTERR_LOCUS],errLOC_Disk
277 EnterCrit critDisk
278 MOV WORD PTR ThisCDS,OFFSET DOSGROUP:DummyCDS
279 MOV WORD PTR ThisCDS+2,CS
280 ADD AL,'A'-1
281 invoke InitCDS
282
283; invoke GetThisDrv ; Set CDS pointer
284
285 JC No_files ; Bogus drive letter
286 LES DI,[THISCDS] ; Get CDS pointer
287 LES BP,ES:[DI.curdir_devptr]; Get DPB pointer
288 invoke GOTDPB ; [THISDPB] = ES:BP
289
290 mov AL,ES:[BP.dpb_drive]
291 mov ThisDrv,AL
292
293 MOV WORD PTR [CREATING],0E500H
294 MOV [NoSetDir],1 ; if we find a dir, don't change to it
295 LDS SI,[DMAADD]
296ASSUME DS:NOTHING
297 LODSB ; Drive Byte
298
299; DEC AL
300; MOV [THISDRV],AL
301
302 entry RENAME_NEXT ; Entry used by DOS_RENAME
303
304 context ES ; THIS BLOWS ES:BP POINTER TO DPB
305 MOV DI,OFFSET DOSGROUP:NAME1
306 MOV CX,11
307 REP MOVSB ; Search name
308 LODSB ; Attribute
309 MOV [ATTRIB],AL
310 LODSW ; LastEnt
311 OR AX,AX
312 JNS cont_load
313No_files:
314 JMP find_no_more
315
316cont_load:
317 PUSH AX ; Save LastEnt
318 LODSW ; DirStart
319 MOV BX,AX
320 context DS
321 LES BP,[THISDPB] ; Recover ES:BP
322 invoke SetDirSrch
323 JNC SEARCH_GOON
324 POP AX ; Clean stack
325 JMP No_files
326
327SEARCH_GOON:
328 invoke StartSrch
329 POP AX
330 invoke GetEnt
331 JC No_files
332 invoke NextEnt
333 JC No_files
334 XOR AH,AH ; If Search_Next, can't be a DEV
335 JMP found_it
336
337EndProc DOS_SEARCH_NEXT
338
339
340;Input: [WFP_START]= pointer to final path
341;Function: check '?' char
342;Output: carry clear, if no '?'
343; carry set, if '?' exists
344
345 procedure CHECK_QUESTION,NEAR ;AN000;
346 ASSUME ES:NOTHING,DS:NOTHING ;AN000;
347
348 PUSH CS ;AN000;;FO.
349 POP DS ;AN000;;FO. ds:si -> final path
350 MOV SI,[WFP_START] ;AN000;;FO.
351getnext: ;AN000;
352 LODSB ;AN000;;FO. get char
353 OR AL,AL ;AN000;;FO. is it null
354 JZ NO_Question ;AN000;;FO. yes
355 CMP AL,'?' ;AN000;;FO. is '?'
356 JNZ getnext ;AN000;;FO. no
357 STC ;AN000;;FO.
358NO_Question: ;AN000;
359 return ;AN000;;FO.
360
361EndProc CHECK_QUESTION ;AN000;
362
363CODE ENDS
364 END
diff --git a/v4.0/src/DOS/KSTRIN.ASM b/v4.0/src/DOS/KSTRIN.ASM
new file mode 100644
index 0000000..1eeee39
--- /dev/null
+++ b/v4.0/src/DOS/KSTRIN.ASM
@@ -0,0 +1,690 @@
1; SCCSID = @(#)strin.asm 1.2 85/04/18
2;
3; Revision history:
4; A000 version 4.00 Jan. 1988
5;
6Break
7
8; Inputs:
9; DS:DX Point to an input buffer
10; Function:
11; Fill buffer from console input until CR
12; Returns:
13; None
14
15 procedure $STD_CON_STRING_INPUT,NEAR ;System call 10
16ASSUME DS:NOTHING,ES:NOTHING
17
18 MOV AX,SS
19 MOV ES,AX
20 MOV SI,DX
21 XOR CH,CH
22 LODSW
23 mov cs:Temp_Var,si ;AN000; ; 3/31/KK
24;
25; AL is the buffer length
26; AH is the template length
27;
28 OR AL,AL
29 retz ;Buffer is 0 length!!?
30 MOV BL,AH ;Init template counter
31 MOV BH,CH ;Init template counter
32 ;
33 ; BL is the number of bytes in the template
34 ;
35 CMP AL,BL
36 JBE NOEDIT ;If length of buffer inconsistent with contents
37 CMP BYTE PTR [BX+SI],c_CR
38 JZ EDITON ;If CR correctly placed EDIT is OK
39;
40; The number of chars in the template is >= the number of chars in buffer or
41; there is no CR at the end of the template. This is an inconsistant state
42; of affairs. Pretend that the template was empty:
43;
44NOEDIT:
45 MOV BL,CH ;Reset buffer
46EDITON:
47 MOV DL,AL
48 DEC DX ;DL is # of bytes we can put in the buffer
49;
50; Top level. We begin to read a line in.
51;
52NEWLIN:
53 MOV AL,[CARPOS]
54 MOV [STARTPOS],AL ;Remember position in raw buffer
55 PUSH SI
56 MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here
57 MOV [INSMODE],CH ;Insert mode off
58 MOV BH,CH ;No chars from template yet
59 MOV DH,CH ;No chars to new line yet
60 call IntCNE0 ;AN000; Get first char 2/17/KK
61 jz SavCh ;AN000; if ZF set then interim character 2/17/KK
62 CMP AL,c_LF ;Linefeed
63 JNZ GOTCH ;Filter out LF so < works
64;
65; This is the main loop of reading in a character and processing it.
66;
67; BH is the index of the next byte in the template
68; BL is the length of the template
69; DH is the number of bytes in the buffer
70; DL is the length of the buffer
71;
72entry GETCH
73 call IntCNE0 ;AN000;; 2/17/KK
74 jz SavCh ;AN000;; if ZF set then interim character 2/17/KK
75GOTCH:
76;
77; ^F ignored in case BIOS did not flush the input queue.
78;
79 CMP AL,"F"-"@"
80 JZ GETCH
81;
82; If the leading char is the function-key lead byte
83;
84 CMP AL,[ESCCHAR]
85 JNZ ARM03 ;AN000;; 2/17/KK
86 Jmp ESCC ;AN000;; 2/17/KK
87ARM03: ;AN000;; 2/17/KK
88;
89; Rubout and ^H are both destructive backspaces.
90;
91 CMP AL,c_DEL
92 JZ BACKSPJ0 ;AN000; 2/17/KK
93 CMP AL,c_BS
94 JNZ ARM04 ;AN000;; 2/17/KK
95BACKSPJ0: ;AN000;; 2/17/KK
96 Jmp BACKSPJ ;AN000;; 2/17/KK
97ARM04: ;AN000;; 2/17/KK
98;
99; ^W deletes backward once and then backs up until a letter is before the
100; cursor
101;
102 CMP AL,"W" - "@"
103; The removal of the comment characters before the jump statement will
104; cause ^W to backup a word.
105;*** JZ WordDel
106 NOP
107 NOP
108 CMP AL,"U" - "@"
109; The removal of the comment characters before the jump statement will
110; cause ^U to clear a line.
111;*** JZ LineDel
112 NOP
113 NOP
114
115;
116; CR terminates the line.
117;
118 CMP AL,c_CR
119 JNZ ARM01 ;AN000;; 2/17/KK
120 Jmp ENDLIN ;AN000;; 2/17/KK
121ARM01: ;AN000;; 2/17/KK
122;
123; LF goes to a new line and keeps on reading.
124;
125 CMP AL,c_LF
126 JNZ ARM00 ;AN000;; 2/17/KK
127 Jmp PHYCRLF ;AN000;; 2/17/KK
128ARM00: ;AN000;; 2/17/KK
129;
130; ^X (or ESC) deletes the line and starts over
131;
132 CMP AL,[CANCHAR]
133 JNZ SAVCH ;AN000;; 2/13/KK
134 JMP KILNEW ;AN000;; 2/13/KK
135InterLoop: ;AN000;; 2/17/KK
136 call IntCNE0 ;AN000;; Get another interim character 2/17/KK
137;
138; Otherwise, we save the input character.
139;
140SAVCH:
141 pushf ;AN000; 2/17/KK
142 CMP DH,DL
143 JAE BUFFUL ; buffer is full.
144;----------------------------- Start of DBCS 2/13/KK
145
146 invoke TESTKANJ ;AN000;
147 JZ ISNORM ;AN000;
148 INC DH ;AN000;
149 CMP DH,DL ;AN000;
150 JB GOTROOM ;AN000;
151 DEC DH ;AN000;; No room for second byte
152 call IntCNE0 ;AN000;; Get second byte
153 JMP SHORT BUFFUL ;AN000;
154 ;AN000;
155GOTROOM: ;AN000;
156 STOSB ;AN000;; Store first byte
157 popf ;AN000;
158 call outchax ;AN000;
159 call IntCNE0 ;AN000;; Get second byte
160 pushf ;AN000;
161 STOSB ;AN000;; Store second byte
162 INC DH ;AN000;
163 popf ;AN000;
164 call outchax ;AN000;
165 jnz ContIn1 ;AN000;; interim character?
166 call InterCheck ;AN000;
167 call InterCheck ;AN000;
168 jmp short InterLoop ;AN000;; not interim skip another check
169
170ISNORM:
171;----------------------------- End of DBCS 2/13/KK
172 STOSB ;AN000;
173 INC DH ;AN000;; increment count in buffer.
174 popf ;AN000;; 2/17/KK
175 invoke BUFOUTx ;AN000;; Print control chars nicely 2/17/KK
176 jnz ContIn1 ;AN000;; 2/17/KK
177 call InterCheck ;AN000;; 2/17/KK
178 jmp short InterLoop ;AN000;; 2/17/KK
179CONTIN1: ;AN000;; 2/13/KK
180;;;CONTIN: ;AN000;; 2/13/KK
181 CMP BYTE PTR [INSMODE],0
182 JNZ GETCH0 ; insertmode => don't advance template
183 CMP BH,BL
184 JAE GETCH0 ; no more characters in template
185 INC SI ; Skip to next char in template
186 INC BH ; remember position in template
187
188 PUSH AX ;
189 MOV AL,BYTE PTR [SI-1] ;AN000;; 2/13/KK
190 invoke TESTKANJ ;AN000;; 2/13/KK
191 POP AX ;AN000;; 2/13/KK
192 JZ GETCH0 ;AN000;; Wasn't a dual byte 2/13/KK
193 INC SI ;AN000;; Was a dual byte, 2/13/KK
194 INC BH ;AN000;; skip one more 2/13/KK
195GETCH0: ;AN000;; 2/17/KK
196 JMP GETCH ;AN000;; 2/17/KK
197
198BACKSPJ: JMP SHORT BACKSP
199
200BUFFUL:
201 popf ;AN000;; 2/17/KK
202 MOV AL,7 ;AN000;; Bell to signal full buffer
203 invoke OUTT
204 JMP GETCH
205; 2/17/KK
206; Reduce character count, reduce pointer 2/17/KK
207; 2/17/KK
208InterCheck: ;AN000;; 2/17/KK
209 dec dh ;AN000;; adjust count 2/17/KK
210 dec di ;AN000;; adjust buffer pointer 2/17/KK
211 ret ;AN000;; 2/17/KK
212
213ESCC:
214 transfer OEMFunctionKey ; let the OEM's handle the key dispatch
215
216ENDLIN:
217 STOSB ; Put the CR in the buffer
218 invoke OUTT ; Echo it
219 POP DI ; Get start of user buffer
220 MOV [DI-1],DH ; Tell user how many bytes
221 INC DH ; DH is length including CR
222COPYNEW:
223 SaveReg <DS,ES>
224 RestoreReg <DS,ES> ; XCHG ES,DS
225 MOV SI,OFFSET DOSGROUP:INBUF
226 MOV CL,DH ; set up count
227 REP MOVSB ; Copy final line to user buffer
228 return
229;
230; Output a CRLF to the user screen and do NOT store it into the buffer
231;
232PHYCRLF:
233 invoke CRLF
234 JMP GETCH
235
236;
237; Delete the previous line
238;
239LineDel:
240 OR DH,DH
241 JNZ bridge00 ;AN000;; 2/13/KK
242 JMP GetCh ;AN000;; 2/13/KK
243bridge00: ;AN000;; 2/13/KK
244 Call BackSpace
245 JMP LineDel
246
247;
248; delete the previous word.
249;
250WordDel:
251WordLoop:
252 Call BackSpace ; backspace the one spot
253 OR DH,DH
254 JZ GetChJ
255 MOV AL,ES:[DI-1]
256 cmp al,'0'
257 jb GetChj
258 cmp al,'9'
259 jbe WordLoop
260 OR AL,20h
261 CMP AL,'a'
262 JB GetChJ
263 CMP AL,'z'
264 JBE WordLoop
265GetChJ:
266 JMP GetCh
267;
268; The user wants to throw away what he's typed in and wants to start over. We
269; print the backslash and then go to the next line and tab to the correct spot
270; to begin the buffered input.
271;
272 entry KILNEW
273 MOV AL,"\"
274 invoke OUTT ;Print the CANCEL indicator
275 POP SI ;Remember start of edit buffer
276PUTNEW:
277 invoke CRLF ;Go to next line on screen
278 MOV AL,[STARTPOS]
279 invoke TAB ;Tab over
280 JMP NEWLIN ;Start over again
281
282
283;
284; Destructively back up one character position
285;
286entry BackSp
287 Call BackSpace
288 JMP GetCh
289
290BackSpace:
291 OR DH,DH
292 JZ OLDBAK ;No chars in line, do nothing to line
293 CALL BACKUP ;Do the backup
294 MOV AL,ES:[DI] ;Get the deleted char
295 invoke TESTKANJ ;AN000;2/13/KK
296 JNZ OLDBAK ;AN000; Was a dual byte, done 2/13/KK
297 CMP AL," "
298 JAE OLDBAK ;Was a normal char
299 CMP AL,c_HT
300 JZ BAKTAB ;Was a tab, fix up users display
301;; 9/27/86 fix for ctrl-U backspace
302 CMP AL,"U"-"@" ; ctrl-U is a section symbol not ^U
303 JZ OLDBAK
304 CMP AL,"T"-"@" ; ctrl-T is a paragraphs symbol not ^T
305 JZ OLDBAK
306;; 9/27/86 fix for ctrl-U backspace
307 CALL BACKMES ;Was a control char, zap the '^'
308OLDBAK:
309 CMP BYTE PTR [INSMODE],0
310 retnz ;In insert mode, done
311 OR BH,BH
312 retz ;Not advanced in template, stay where we are
313 DEC BH ;Go back in template
314 DEC SI
315;-------------------------- Start of DBCS 2/13/KK
316 OR BH,BH ;AN000;
317 retz ;AN000;; If we deleted one char and it was the only
318 ;AN000;; one, could not have dual byte
319;;;; POP AX ;AN000;; Get start of template
320;;;; PUSH AX ;AN000;; Put it back on stack
321 mov ax,cs:Temp_Var ;AN000;; 3/31/KK
322 XCHG AX,SI ;AN000;
323LOOKDUAL: ;AN000;
324 CMP SI,AX ;AN000;
325 JAE ATLOC ;AN000;
326 PUSH AX ;AN000;
327 MOV AL,BYTE PTR [SI];AN000;
328 invoke TESTKANJ ;AN000;
329 POP AX ;AN000;
330 JZ ONEINC ;AN000;
331 INC SI ;AN000;
332ONEINC: ;AN000;
333 INC SI ;AN000;
334 JMP SHORT LOOKDUAL ;AN000;
335 ;AN000;
336ATLOC: ;AN000;
337 retz ;AN000;; Correctly pointing to start of single byte
338 DEC AX ;AN000;; Go back one more to correctly point at start
339 DEC BH ;AN000; ; of dual byte
340 MOV SI,AX ;AN000;
341 return ;AN000;
342;-------------------------- End of DBCS 2/13/KK
343
344BAKTAB:
345 PUSH DI
346 DEC DI ;Back up one char
347 STD ;Go backward
348 MOV CL,DH ;Number of chars currently in line
349 MOV AL," "
350 PUSH BX
351 MOV BL,7 ;Max
352 JCXZ FIGTAB ;At start, do nothing
353FNDPOS:
354 SCASB ;Look back
355 JNA CHKCNT
356 CMP BYTE PTR ES:[DI+1],9
357 JZ HAVTAB ;Found a tab
358 DEC BL ;Back one char if non tab control char
359CHKCNT:
360 LOOP FNDPOS
361FIGTAB:
362 SUB BL,[STARTPOS]
363HAVTAB:
364 SUB BL,DH
365 ADD CL,BL
366 AND CL,7 ;CX has correct number to erase
367 CLD ;Back to normal
368 POP BX
369 POP DI
370 JZ OLDBAK ;Nothing to erase
371TABBAK:
372 invoke BACKMES
373 LOOP TABBAK ;Erase correct number of chars
374 JMP SHORT OLDBAK
375
376BACKUP:
377 DEC DH ;Back up in line
378 DEC DI
379;-------------------------Start of DBCS 2/13/KK
380 OR DH,DH ;AN000;
381 JZ BACKMES ;AN000;; If deleted one and got only, no dual
382 MOV AX,DI ;AN000;
383 MOV DI,OFFSET DOSGROUP:INBUF;AN000;
384LOOKDUAL2: ;AN000;
385 CMP DI,AX ;AN000;
386 JAE ATLOC2 ;AN000;
387 PUSH AX ;AN000;
388 MOV AL,BYTE PTR ES:[DI] ;AN000;
389 invoke TESTKANJ ;AN000;
390 POP AX ;AN000;
391 JZ ONEINC2 ;AN000;
392 INC DI ;AN000;
393ONEINC2: ;AN000;
394 INC DI ;AN000;
395 JMP SHORT LOOKDUAL2 ;AN000;
396 ;AN000;
397ATLOC2: ;AN000;
398 JE BACKMES ;AN000;; Correctly deleted single byte
399 DEC AX ;AN000; Go back one more to correctly delete dual byte
400 DEC DH ;AN000;
401 MOV DI,AX ;AN000;
402 CALL BACKMES ;AN000;
403;---------------------------End of DBCS 2/13/KK
404BACKMES:
405 MOV AL,c_BS ;Backspace
406 invoke OUTT
407 MOV AL," " ;Erase
408 invoke OUTT
409 MOV AL,c_BS ;Backspace
410 JMP OUTT ;Done
411
412;User really wants an ESC character in his line
413 entry TwoEsc
414 MOV AL,[ESCCHAR]
415 JMP SAVCH
416
417;Copy the rest of the template
418 entry COPYLIN
419 MOV CL,BL ;Total size of template
420 SUB CL,BH ;Minus position in template, is number to move
421 JMP SHORT COPYEACH
422
423 entry CopyStr
424 invoke FINDOLD ;Find the char
425 JMP SHORT COPYEACH ;Copy up to it
426
427;Copy one char from template to line
428 entry COPYONE
429 MOV CX,1 ;AN000;; 2/13/KK
430 MOV AL,[SI] ;AN000;; get char 2/13/KK
431 invoke TestKanj ;AN000;; is it kanji? 2/13/KK
432 JZ CopyEach ;AN000;; no, go do copy2/13/KK
433 INC CX ;AN000;; do 2 byte copy2/13/KK
434
435;Copy CX chars from template to line
436COPYEACH:
437 MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode
438 CMP DH,DL
439 JZ GETCH2 ;At end of line, can't do anything
440 CMP BH,BL
441 JZ GETCH2 ;At end of template, can't do anything
442 LODSB
443 STOSB
444;----------------------------- Start of DBCS 2/13/KK
445 INC BH ;AN000;; Ahead in template
446 INC DH ;AN000;; Ahead in line
447 CALL TestKanj ;AN000;; 2 byte character?
448 JZ CopyLoop ;AN000;; no, go copy next
449 CMP DH,DL ;AN000;; over boundary?
450 JNZ CopyBoth ;AN000;; no, move both
451 DEC BH ;AN000;; yes, backup template
452 DEC DH ;AN000;; back up line
453 DEC SI ;AN000;; patch (from Dohhaku)
454 DEC DI ;AN000;; remember to backup after previous move
455 JMP GetCh ;AN000;; go get next char
456 ;AN000;
457CopyBoth: ;AN000;
458 invoke BUFOUT ;AN000;; output the first byte
459 LODSB ;AN000;; get the second
460 STOSB ;AN000;; move the second
461 INC BH ;AN000;; bump template
462 INC DH ;AN000;; bump line
463 DEC CX ;AN000;; dump byte count
464CopyLoop: ;AN000;
465 invoke BUFOUT ;AN000;
466 LOOP COPYEACH ;AN000;
467;;;;; invoke BUFOUT
468;;;;; INC BH ;Ahead in template
469;;;;; INC DH ;Ahead in line
470;;;;; LOOP COPYEACH
471;----------------------------- End of DBCS 2/13/KK
472GETCH2:
473 JMP GETCH
474
475;Skip one char in template
476 entry SKIPONE
477 CMP BH,BL
478 JZ GETCH2 ;At end of template
479 INC BH ;Ahead in template
480 INC SI
481 PUSH AX ;AN000;; 2/13/KK
482 MOV AL,BYTE PTR [SI-1] ;AN000;; 2/13/KK
483 invoke TESTKANJ ;AN000;; 2/13/KK
484 POP AX ;AN000;; 2/13/KK
485 JZ GETCH2 ;AN000;; 2/13/KK
486 INC BH ;AN000;; 2/13/KK
487 INC SI ;AN000;; 2/13/KK
488 JMP GETCH
489
490 entry SKIPSTR
491 invoke FINDOLD ;Find out how far to go
492 ADD SI,CX ;Go there
493 ADD BH,CL
494 JMP GETCH
495
496;Get the next user char, and look ahead in template for a match
497;CX indicates how many chars to skip to get there on output
498;NOTE: WARNING: If the operation cannot be done, the return
499; address is popped off and a jump to GETCH is taken.
500; Make sure nothing extra on stack when this routine
501; is called!!! (no PUSHes before calling it).
502
503TABLE SEGMENT ;AN000;; 2/17/KK
504Public KISTR001S,KISTR001E ;AN000;; 2/17/KK
505KISTR001S label byte ;AN000;; 2/17/KK
506LOOKSIZ DB 0 ;AN000;; 0 if byte, NZ if word 2/17/KK
507KISTR001E label byte ;AN000;; 2/17/KK
508TABLE ENDS ;AN000;; 2/17/KK
509
510FINDOLD:
511 MOV [LOOKSIZ],0 ;AN000;; Initialize to byte 2/13/KK
512 call IntCNE1 ;AN000;; 2/17/KK
513 CMP AL,[ESCCHAR] ;AN000;; did he type a function key?
514;;;;; JNZ FindSetup ;AN000;; no, set up for scan 2/13/KK
515 JNZ TryKanj ;AN000;; no, continue testing 2/13/KK
516 call IntCNE1 ;AN000;; 2/17/KK
517 JMP NotFnd ; go try again
518;;;;;;;FindSetup: ;AN000;; 2/13/KK
519TryKanj: ;AN000;; 2/13/KK
520 invoke TESTKANJ ;AN000;; 2/13/KK
521 JZ GOTLSIZ ;AN000;; 2/13/KK
522 INC [LOOKSIZ] ;AN000;; Gonna look for a word 2/13/KK
523 PUSH AX ;AN000;; Save first byte 2/13/KK
524 call IntCNE1 ;AN000;; 2/17/KK
525 POP CX ;AN000;; 2/13/KK
526 MOV AH,AL ;AN000;; 2/13/KK
527 MOV AL,CL ;AN000;; AX is dual byte sequence to look for
528 XOR CX,CX ;AN000;; Re-zero CH 2/13/KK
529GOTLSIZ:
530 MOV CL,BL
531 SUB CL,BH ;CX is number of chars to end of template
532 JZ NOTFND ;At end of template
533 DEC CX ;Cannot point past end, limit search
534 JZ NOTFND ;If only one char in template, forget it
535 PUSH AX ;AN000;; 2/13/KK
536 MOV AL,BYTE PTR [SI] ;AN000;; 2/13/KK
537 invoke TESTKANJ ;AN000;; 2/13/KK
538 POP AX ;AN000;; 2/13/KK
539 JZ NOTDUAL5 ;AN000;; 2/13/KK
540 DEC CX ;AN000;; And one more besides 2/13/KK
541 JZ NOTFND ;AN000;; If only one char in template, forget it
542NOTDUAL5: ;AN000;; 2/13/KK
543 PUSH ES
544 PUSH DS
545 POP ES
546 PUSH DI
547 MOV DI,SI ;Template to ES:DI
548;;;; INC DI 2/13/KK
549;;;; REPNE SCASB ;Look 2/13/KK
550;--------------------- Start of DBCS 2/13/KK
551 PUSH AX ;AN000;
552 MOV AL,BYTE PTR ES:[DI] ;AN000;
553 invoke TESTKANJ ;AN000;
554 POP AX ;AN000;
555 JZ ONEINC5 ;AN000;
556 INC DI ;AN000;; We will skip at least something
557ONEINC5: ;AN000;
558 INC DI ;AN000;
559 CMP [LOOKSIZ],0 ;AN000;
560 JNZ LOOKWORD ;AN000;
561LOOKBYTE: ;AN000;
562 PUSH AX ;AN000;
563 MOV AL,BYTE PTR ES:[DI] ;AN000;
564 invoke TESTKANJ ;AN000;
565 POP AX ;AN000;
566 JZ TESTITB ;AN000;
567 INC DI ;AN000;
568 INC DI ;AN000;
569 DEC CX ;AN000;
570 LOOP LOOKBYTE ;AN000;
571 JMP SHORT ATNOTFND ;AN000;
572 ;AN000;
573TESTITB: ;AN000;
574 DEC CX ;AN000;
575 CMP AL,ES:[DI] ;AN000;
576 JZ ATSPOT ;AN000;
577 INC DI ;AN000;
578 INC CX ;AN000;; Counter next instruction
579 LOOP LOOKBYTE ;AN000;
580ATNOTFND: ;AN000;
581 XOR AL,AL ;AN000;
582 INC AL ;AN000;; Set NZ
583ATSPOT: ; 2/13/K;AN000;K
584;--------------------- End of DBCS 2/13/KK
585 POP DI
586 POP ES
587 JNZ NOTFND ;Didn't find the char
588 NOT CL ;Turn how far to go into how far we went
589 ADD CL,BL ;Add size of template
590 SUB CL,BH ;Subtract current pos, result distance to skip
591 return
592
593NOTFND:
594 POP BP ;Chuck return address
595 JMP GETCH
596;------------------------- Start of DBCS 2/13/KK
597LOOKWORD: ;AN000;
598 PUSH AX ;AN000;
599 MOV AL,BYTE PTR ES:[DI] ;AN000;
600 invoke TESTKANJ ;AN000;
601 POP AX ;AN000;
602 JNZ TESTITW ;AN000;
603 INC DI ;AN000;
604 LOOP LOOKWORD ;AN000;
605 JMP SHORT ATNOTFND ;AN000;
606 ;AN000;
607TESTITW: ;AN000;
608 DEC CX ;AN000;
609 CMP AX,ES:[DI] ;AN000;
610 JZ ATSPOT ;AN000;
611 INC DI ;AN000;
612 INC DI ;AN000;
613 LOOP LOOKWORD ;AN000; ; Performs second DEC of CX
614 JMP SHORT ATNOTFND ;AN000;
615;------------------------- End of DBCS 2/13/KK
616
617entry REEDIT
618 MOV AL,"@" ;Output re-edit character
619 invoke OUTT
620 POP DI
621 PUSH DI
622 PUSH ES
623 PUSH DS
624 invoke COPYNEW ;Copy current line into template
625 POP DS
626 POP ES
627 POP SI
628 MOV BL,DH ;Size of line is new size template
629 JMP PUTNEW ;Start over again
630
631 entry EXITINS
632 entry ENTERINS
633 NOT BYTE PTR [INSMODE]
634 JMP GETCH
635
636;Put a real live ^Z in the buffer (embedded)
637 entry CTRLZ
638 MOV AL,"Z"-"@"
639 JMP SAVCH
640
641;Output a CRLF
642 entry CRLF
643 MOV AL,c_CR
644 invoke OUTT
645 MOV AL,c_LF
646 JMP OUTT
647
648EndProc $STD_CON_STRING_INPUT
649
650;-------------- Start of DBCS 2/17/KK
651PUBLIC IntCNE0 ;AN000;
652procedure IntCNE0,near ;AN000;
653 push word ptr [InterCon] ;AN000;
654 mov [InterCon],01 ;AN000;
655get_com: ;AN000;
656 invoke INTER_CON_INPUT_NO_ECHO ;AN000;; get a byte character
657 pop word ptr [InterCon] ;AN000;
658 ret ;AN000;
659IntCNE0 endp ;AN000;
660 ;AN000;
661procedure IntCNE1,near ;AN000;
662 push word ptr [InterCon] ;AN000;
663 mov [InterCon],00 ;AN000;
664 jmp short get_com ;AN000;
665IntCNE1 endp ;AN000;
666 ;AN000;
667 procedure outchax,near ;AN000;
668 pushf ;AN000;
669 mov [SaveCurFlg],0 ;AN000;
670 jnz sj1 ;AN000;
671 mov [SaveCurFlg],1 ;AN000;
672sj1: ;AN000;
673 CALL OUTCHA ;AN000;
674 mov [SaveCurFlg],0 ;AN000;
675 popf ;AN000;
676 ret ;AN000;
677outchax endp ;AN000;
678 ;AN000;
679 procedure bufoutx,near ;AN000;
680 pushf ;AN000;
681 mov [SaveCurFlg],0 ;AN000;
682 jnz sj2 ;AN000;
683 mov [SaveCurFlg],1 ;AN000;
684sj2: ;AN000;
685 invoke BUFOUT ;AN000;
686 mov [SaveCurFlg],0 ;AN000;
687 popf ;AN000;
688 ret ;AN000;
689bufoutx endp ;AN000;
690;-------------- End of DBCS 2/17/KK
diff --git a/v4.0/src/DOS/LOCK.ASM b/v4.0/src/DOS/LOCK.ASM
new file mode 100644
index 0000000..2089882
--- /dev/null
+++ b/v4.0/src/DOS/LOCK.ASM
@@ -0,0 +1,372 @@
1; SCCSID = @(#)lock.asm 1.1 85/04/10
2TITLE LOCK ROUTINES - Routines for file locking
3NAME LOCK
4
5;
6; LOCK_CHECK
7; LOCK_VIOLATION
8; $LockOper
9;
10; Revision history:
11; A000 version 4.00 Jan. 1988
12;
13include dosseg.asm
14
15CODE SEGMENT BYTE PUBLIC 'CODE'
16 ASSUME SS:DOSGROUP,CS:DOSGROUP
17
18.xlist
19.xcref
20INCLUDE DOSSYM.INC
21INCLUDE DEVSYM.INC
22include lock.inc ;AN000;
23.cref
24.list
25
26AsmVars <IBM, Installed>
27
28Installed = TRUE
29
30 i_need THISSFT,DWORD
31 i_need THISDPB,DWORD
32 i_need EXTERR,WORD
33 i_need ALLOWED,BYTE
34 i_need RetryCount,WORD
35 I_need fShare,BYTE
36 I_Need EXTERR_LOCUS,BYTE ; Extended Error Locus
37 i_need JShare,DWORD
38 i_need Lock_Buffer,DWORD ;AN000; DOS 4.00
39 i_need Temp_Var,WORD ;AN000; DOS 4.00
40
41BREAK <$LockOper - Lock Calls>
42
43;
44; Assembler usage:
45; MOV BX, Handle (DOS 3.3)
46; MOV CX, OffsetHigh
47; MOV DX, OffsetLow
48; MOV SI, LengthHigh
49; MOV DI, LengthLow
50; MOV AH, LockOper
51; MOV AL, Request
52; INT 21h
53;
54; Error returns:
55; AX = error_invalid_handle
56; = error_invalid_function
57; = error_lock_violation
58;
59; Assembler usage:
60; MOV AX, 5C?? (DOS 4.00)
61;
62; 0? lock all
63; 8? lock write
64; ?2 lock multiple
65; ?3 unlock multiple
66; ?4 lock/read
67; ?5 write/unlock
68; ?6 add (lseek EOF/lock/write/unlock)
69; MOV BX, Handle
70; MOV CX, count or size
71; LDS DX, buffer
72; INT 21h
73;
74; Error returns:
75; AX = error_invalid_handle
76; = error_invalid_function
77; = error_lock_violation
78
79 procedure $LockOper,NEAR
80ASSUME DS:NOTHING,ES:NOTHING
81; MOV BP,AX ;MS. BP=AX ;AN000;
82; AND BP,7FH ;MS. clear bit 7 ;AN000;
83; CMP BP,Lock_add ;MS. supported function ? ;AN000;
84; JA lock_bad_func ;MS. no, ;AN000;
85
86 CMP AL,1 ;AN000;;MS. no,
87 JA lock_bad_func ;AN000;;MS. no,
88
89 PUSH DI ; Save LengthLow
90 invoke SFFromHandle ; ES:DI -> SFT
91 JNC lock_do ; have valid handle
92 POP DI ; Clean stack
93 error error_invalid_handle
94lock_bad_func:
95 MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
96 error error_invalid_function
97
98; Align_buffer call has been deleted, since it corrupts the DTA (6/5/88) P5013
99
100lock_do:
101; PUSH AX ;AN000;;MS. save ax
102; PUSH BX ;AN000;;MS. save handle
103; MOV [Temp_Var],DX ;AN000;;MS. save DX
104; invoke Align_Buffer ;AN000;;MS. align ds:dx and set DMAADD
105; POP BX ;AN000;;MS. restore handle
106; POP AX ;AN000;;MS. save ax
107 ;AN000;
108; CMP BP,Unlock_all ;AN000;;MS. old function 0 or 1 ?
109; JA chk_lock_mul ;AN000;;MS. no, new function
110; TEST AL,80H ;AN000;;MS. 80H bit on ?
111; JZ old_33 ;AN000;;MS. no, old DOS 3.3 interface
112; MOV CX,1 ;AN000;;MS. adjust for new interface
113; ADD BP,2 ;AN000;;MS.
114; JMP SHORT chk_lock_mul ;AN000;;MS.
115old_33:
116 MOV BX,AX ;AN000;;MS. save AX
117 ;AN000;
118;; MOV DX,[Temp_Var] ;AN000;;MS. retore DX (P5013) 6/5/88
119
120 MOV BP, OFFSET DOSGROUP:Lock_Buffer ;AN000;;MS. get DOS LOCK buffer
121 MOV WORD PTR [BP.Lock_position],DX ;AN000;;MS. set low offset
122 MOV WORD PTR [BP.Lock_position+2],CX;AN000;;MS. set high offset
123 POP CX ;AN000;;MS. get low length
124 MOV WORD PTR [BP.Lock_length],CX ;AN000;;MS. set low length
125 MOV WORD PTR [BP.Lock_length+2],SI ;AN000;;MS. set high length
126 MOV CX,1 ;AN000;;MS. one range
127 PUSH CS ;AN000;;MS.
128 POP DS ;AN000;;MS. DS:DX points to
129 MOV DX,BP ;AN000;;MS. Lock_Buffer
130 TEST AL,Unlock_all ;AN000;;MS. function 1
131 JNZ DOS_Unlock ;AN000;;MS. yes
132 JMP DOS_Lock ;AN000;;MS. function 0
133;;chk_lock_mul: ;AN000;
134; POP SI ;AN000;;MS. pop low length
135; TEST ES:[DI.sf_flags],sf_isnet ;AN000;;MS. net handle?
136; JZ LOCAL_DOS_LOCK ;AN000;;MS. no
137; invoke OWN_SHARE ;AN000;;MS. IFS owns share ?
138; JNZ LOCAL_DOS_LOCK ;AN000;;MS. no
139; MOV BX,AX ;AN000;;MS. BX=AX
140; CallInstall NET_XLock,multNet,10 ;AN000;;MS. issue Net Extended Lock
141; MOV [Temp_Var],CX ;AN000;;MS. cx= retuened from IFS
142; JMP ValChk ;AN000;;MS. check return
143;LOCAL_DOS_LOCK: ;AN000;
144; CMP BP,Lock_mul_range ;AN000;;MS. lock mul range?
145; JNZ unmul ;AN000;;MS. lock mul range?
146; JMP LOCAL_LOCK ;AN000;;MS. yes
147;unmul:
148; CMP BP,Unlock_mul_range ;AN000;;MS. unlock mul range?
149; JZ LOCAL_UNLOCK ;AN000;;MS. yes
150; CMP BP,Lock_read ;AN000;;MS. lock read?
151; JNZ chk_write_unlock ;AN000;;MS. no
152; CALL Set_Lock_Buffer ;AN000;;MS. set DOS lock buffer
153; CALL Set_Lock ;AN000;;MS. set the lock
154; JC lockerror ;AN000;;MS. error
155; invoke $READ ;AN000;;MS. do read
156; JC lockerror ;AN000;;MS. error
157;lockend: ;AN000;
158; transfer SYS_RET_OK ;AN000;;MS. return
159;chk_write_unlock: ;AN000;
160; CMP BP,Write_unlock ;AN000;;MS. write unlock ?
161; JNZ Lock_addf ;AN000;;MS. no
162; CALL Set_Lock_Buffer ;AN000;;MS. set DOS lock buffer
163;WriteUnlock: ;AN000;
164; PUSH AX ;AN000;;MS. save AX for unlock
165; invoke $WRITE ;AN000;;MS. do write
166; MOV [Temp_Var],AX ;AN000;;MS. save number of bytes writ
167; POP AX ;AN000;;MS. restore AX
168; JC lockerror ;AN000;;MS. error
169; MOV CX,1 ;AN000;;MS. one range unlock
170; PUSH CS ;AN000;;MS.
171; POP DS ;AN000;;MS. DS:DX points to
172; MOV DX,OFFSET DOSGROUP:Lock_Buffer ;AN000;;MS. Lock_BUffer
173; JMP LOCAL_UNLOCK ;AN000;;MS. do unlock
174;Lock_addf: ;AN000;
175; MOV SI,WORD PTR ES:[DI.SF_Size] ;AN000;;MS. must be lock add
176; MOV WORD PTR ES:[DI.SF_Position],SI ;AN000;;MS. set file position to
177; MOV SI,WORD PTR ES:[DI.SF_Size+2] ;AN000;;MS. EOF
178; MOV WORD PTR ES:[DI.SF_Position+2],SI;AN000;;MS.
179; CALL Set_Lock_Buffer ;AN000;;MS. set DOS lock buffer
180; CALL Set_Lock ;AN000;;MS. set the lock
181; JC lockerror ;AN000;;MS. error
182; JMP WriteUnlock ;AN000;;MS. do write unlock
183 ;AN000;;MS.
184DOS_Unlock:
185 TEST ES:[DI.sf_flags],sf_isnet
186 JZ LOCAL_UNLOCK
187;; invoke OWN_SHARE ;AN000;;MS. IFS owns share ?
188;; JNZ LOCAL_UNLOCK ;AN000;;MS. no
189
190 CallInstall Net_Xlock,multNet,10
191 JMP SHORT ValChk
192LOCAL_UNLOCK:
193if installed
194 Call JShare + 7 * 4
195else
196 Call clr_block
197endif
198ValChk:
199 JNC Lock_OK
200lockerror:
201 transfer SYS_RET_ERR
202Lock_OK:
203 MOV AX,[Temp_VAR] ;AN000;;MS. AX= number of bytes
204 transfer SYS_Ret_OK
205DOS_Lock:
206 TEST ES:[DI.sf_flags],sf_isnet
207 JZ LOCAL_LOCK
208;; invoke OWN_SHARE ;AN000;;MS. IFS owns share ?
209;; JNZ LOCAL_LOCK ;AN000;;MS. no
210 CallInstall NET_XLock,multNet,10
211 JMP ValChk
212LOCAL_LOCK:
213if installed
214 Call JShare + 6 * 4
215else
216 Call Set_Block
217endif
218 JMP ValChk
219
220EndProc $LockOper
221
222BREAK <Set_Lock>
223
224; Input:
225; BP = Lock_Buffer addr
226; CX = lock length
227; Function:
228; set the lock
229; Output:
230; carry clear ,Lock is set
231; DS:DX = addr of
232; carry set Lock is not set
233; DS,DX,CX preserved
234
235; procedure Set_Lock,NEAR ;AN000;
236;ASSUME DS:NOTHING,ES:NOTHING ;AN000;
237 ;AN000;
238; PUSH DS ;MS. save regs ;AN000;
239; PUSH DX ;MS. ;AN000;
240; PUSH CX ;MS. ;AN000;
241; ;AN000;
242; PUSH CS ;MS. ;AN000;
243; POP DS ;MS. DS:DX poits to Lock_Buffer ;AN000;
244; MOV DX,BP ;MS. ;AN000;
245; PUSH BX ;MS. save handle ;AN000;
246; PUSH AX ;MS. save functions ;AN000;
247; MOV CX,1 ;MS. set one lock ;AN000;
248;if installed ;AN000;
249; Call JShare + 6 * 4 ;MS. call share set block ;AN000;
250;else ;AN000;
251; Call Set_Block ;MS. ;AN000;
252;endif ;AN000;
253; POP AX ;MS. restore regs ;AN000;
254; POP BX ;MS. ;AN000;
255; POP CX ;MS. ;AN000;
256; POP DX ;MS. ;AN000;
257; POP DS ;MS. ;AN000;
258; return ;MS. ;AN000;
259; ;AN000;
260;EndProc Set_Lock ;AN000;
261
262BREAK <Set_Lock_Buffer>
263
264; Input:
265; ES:DI = addr of SFT
266; CX = lock length
267; Function:
268; set up the lock buffer
269; Output:
270; Lock_Buffer is filled with position and lock length
271; BP = Lock_Buffer addr
272;
273
274; procedure Set_Lock_Buffer,NEAR
275;ASSUME DS:NOTHING,ES:NOTHING
276;
277; MOV BP, OFFSET DOSGROUP:Lock_Buffer ;MS. move file position ;AN000;
278; MOV SI,WORD PTR ES:[DI.sf_position] ;MS. to DOS lock_buffer ;AN000;
279; MOV WORD PTR [BP.Lock_position],SI ;MS. ;AN000;
280; MOV SI,WORD PTR ES:[DI.sf_position+2] ;MS. ;AN000;
281; MOV WORD PTR [BP.Lock_position+2],SI ;MS. ;AN000;
282; MOV WORD PTR [BP.Lock_length],CX ;MS. move cx to lock_buffer ;AN000;
283; MOV WORD PTR [BP.Lock_length+2],0 ;MS. ;AN000;
284; return ;MS. ;AN000;
285;
286;EndProc Set_Lock_Buffer
287
288; Inputs:
289; Outputs of SETUP
290; [USER_ID] Set
291; [PROC_ID] Set
292; Function:
293; Check for lock violations on local I/O
294; Retries are attempted with sleeps in between
295; Outputs:
296; Carry clear
297; Operation is OK
298; Carry set
299; A lock violation detected
300; Outputs of SETUP preserved
301
302 procedure LOCK_CHECK,NEAR
303 DOSAssume CS,<DS>,"Lock_Check"
304 ASSUME ES:NOTHING
305
306 MOV BX,RetryCount ; Number retries
307LockRetry:
308 SaveReg <BX,AX> ; MS. save regs ;AN000;
309if installed
310 call JShare + 8 * 4
311else
312 Call chk_block
313endif
314 RestoreReg <AX,BX> ; MS. restrore regs ;AN000;
315 retnc ; There are no locks
316 Invoke Idle ; wait a while
317 DEC BX ; remember a retry
318 JNZ LockRetry ; more retries left...
319 STC
320 return
321EndProc LOCK_CHECK
322
323; Inputs:
324; [THISDPB] set
325; [READOP] indicates whether error on read or write
326; Function:
327; Handle Lock violation on compatibility (FCB) mode SFTs
328; Outputs:
329; Carry set if user says FAIL, causes error_lock_violation
330; Carry clear if user wants a retry
331;
332; DS, ES, DI, CX preserved, others destroyed
333
334 procedure LOCK_VIOLATION,NEAR
335 DOSAssume CS,<DS>,"Lock_Violation"
336 ASSUME ES:NOTHING
337
338 PUSH DS
339 PUSH ES
340 PUSH DI
341 PUSH CX
342 MOV AX,error_lock_violation
343 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
344 LES BP,[THISDPB]
345 MOV DI,1 ; Fake some registers
346 MOV CX,DI
347 MOV DX,ES:[BP.dpb_first_sector]
348 invoke HARDERR
349 POP CX
350 POP DI
351 POP ES
352 POP DS
353 CMP AL,1
354 retz ; 1 = retry, carry clear
355 STC
356 return
357
358EndProc LOCK_VIOLATION
359
360IF INSTALLED
361;
362; do a retz to return error
363;
364Procedure CheckShare,NEAR
365 ASSUME CS:DOSGROUP,ES:NOTHING,DS:NOTHING,SS:NOTHING
366 CMP fShare,0
367 return
368EndProc CheckShare
369ENDIF
370
371CODE ENDS
372 END
diff --git a/v4.0/src/DOS/MACRO.ASM b/v4.0/src/DOS/MACRO.ASM
new file mode 100644
index 0000000..dea0771
--- /dev/null
+++ b/v4.0/src/DOS/MACRO.ASM
@@ -0,0 +1,445 @@
1; SCCSID = @(#)macro.asm 1.2 85/07/11
2TITLE MACRO - Pathname and macro related internal routines
3NAME MACRO
4;
5; $AssignOper written
6; FIND_DPB written
7; InitCDS written
8; $UserOper written
9; GetVisDrv written
10; GetThisDrv written
11; GetCDSFromDrv written
12;
13; Revision history:
14;
15; Created: MZ 4 April 1983
16; MZ 18 April 1983 Make TransFCB handle extended FCBs
17; AR 2 June 1983 Define/Delete macro for NET redir.
18; MZ 3 Nov 83 Fix InitCDS to reset length to 2
19; MZ 4 Nov 83 Fix NetAssign to use STRLEN only
20; MZ 18 Nov 83 Rewrite string processing for subtree
21; aliasing.
22;
23; MSDOS performs several types of name translation. First, we maintain for
24; each valid drive letter the text of the current directory on that drive.
25; For invalid drive letters, there is no current directory so we pretend to
26; be at the root. A current directory is either the raw local directory
27; (consisting of drive:\path) or a local network directory (consisting of
28; \\machine\path. There is a limit on the point to which a .. is allowed.
29;
30; Given a path, MSDOS will transform this into a real from-the-root path
31; without . or .. entries. Any component that is > 8.3 is truncated to
32; this and all * are expanded into ?'s.
33;
34; The second part of name translation involves subtree aliasing. A list of
35; subtree pairs is maintained by the external utility SUBST. The results of
36; the previous 'canonicalization' are then examined to see if any of the
37; subtree pairs is a prefix of the user path. If so, then this prefix is
38; replaced with the other subtree in the pair.
39;
40; A third part involves mapping this "real" path into a "physical" path. A
41; list of drive/subtree pairs are maintained by the external utility JOIN.
42; The output of the previous translation is examined to see if any of the
43; subtrees in this list are a prefix of the string. If so, then the prefix
44; is replaced by the appropriate drive letter. In this manner, we can
45; 'mount' one device under another.
46;
47; The final form of name translation involves the mapping of a user's
48; logical drive number into the internal physical drive. This is
49; accomplished by converting the drive number into letter:CON, performing
50; the above translation and then converting the character back into a drive
51; number.
52;
53; curdir_list STRUC
54; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir
55; curdir_flags DW ? ; various flags
56; curdir_devptr DD ? ; local pointer to DPB or net device
57; curdir_ID DW ? ; cluster of current dir (net ID)
58; DW ?
59; curdir_end DW ? ; end of assignment
60; curdir_list ENDS
61; curdir_netID EQU DWORD PTR curdir_ID
62; ;Flag word masks
63; curdir_isnet EQU 1000000000000000B
64; curdir_inuse EQU 0100000000000000B
65;
66; There are two main entry points: TransPath and TransFCB. TransPath will
67; take a path and form the real text of the pathname with all . and ..
68; removed. TransFCB will translate an FCB into a path and then invoke
69; TransPath.
70;
71; Implementation note: CURDIR_End field points to the point in the text
72; string where the user may back up to via .. It is the location of a
73; separator character. For the root, it points at the leading /. For net
74; assignments it points at the end (nul) of the initial assignment:
75; A:/ \\foo\bar \\foo\bar\blech\bozo
76; ^ ^ ^
77; A: -> d: /path/ path/ text
78;
79; A000 version 4.00 Jan. 1988
80
81.xlist
82;
83; get the appropriate segment definitions
84;
85include dosseg.asm
86
87CODE SEGMENT BYTE PUBLIC 'CODE'
88 ASSUME SS:DOSGroup,CS:DOSGroup
89
90.xcref
91INCLUDE DOSSYM.INC
92INCLUDE DEVSYM.INC
93.cref
94.list
95.sall
96
97Installed = TRUE
98
99 I_need ThisCDS,DWORD ; pointer to CDS used
100 I_need CDSAddr,DWORD ; pointer to CDS table
101 I_need CDSCount,BYTE ; number of CDS entries
102 I_need CurDrv,BYTE ; current macro assignment (old
103 ; current drive)
104 I_need NUMIO,BYTE ; Number of physical drives
105 I_need fSharing,BYTE ; TRUE => no redirection allowed
106 I_need DummyCDS,80h ; buffer for dummy cds
107 I_need DIFFNAM,BYTE ; flag for MyName being set
108 I_need MYNAME,16 ; machine name
109 I_need MYNUM,WORD ; machine number
110 I_need DPBHEAD,DWORD ; beginning of DPB chain
111 I_need EXTERR_LOCUS,BYTE ; Extended Error Locus
112 I_need DrvErr,BYTE ; drive error
113
114BREAK <$AssignOper -- Set up a Macro>
115
116; Inputs:
117; AL = 00 get assign mode (ReturnMode)
118; AL = 01 set assign mode (SetMode)
119; AL = 02 get attach list entry (GetAsgList)
120; AL = 03 Define Macro (attch start)
121; BL = Macro type
122; = 0 alias
123; = 1 file/device
124; = 2 drive
125; = 3 Char device -> network
126; = 4 File device -> network
127; DS:SI -> ASCIZ source name
128; ES:DI -> ASCIZ destination name
129; AL = 04 Cancel Macro
130; DS:SI -> ASCIZ source name
131; AL = 05 Modified get attach list entry
132; AL = 06 Get ifsfunc item
133; AL = 07 set in_use of a drive's CDS
134; DL = drive number, 0=default 0=A,,
135; AL = 08 reset in_use of a drive's CDS
136; DL = drive number, 0=A, 1=B,,,
137; Function:
138; Do macro stuff
139; Returns:
140; Std Xenix style error return
141
142 procedure $AssignOper,NEAR
143ASSUME DS:NOTHING,ES:NOTHING
144
145 CMP AL,7 ; set in_use ? ;AN000;
146 JNZ chk08 ; no ;AN000;
147srinuse: ;AN000;
148 PUSH AX ; save al ;AN000;
149 MOV AL,DL ; AL= drive id ;AN000;
150 CALL GetCDSFromDrv ; ds:si -> cds ;AN000;
151 POP AX ; ;AN000;
152 JC baddrv ; bad drive ;AN000;
153 CMP WORD PTR [SI.curdir_devptr],0 ; dpb ptr =0 ? ;AN000;
154 JZ baddrv ; no ;AN000;
155 CMP AL,7 ; set ? ;AN000;
156 JNZ resetdrv ; no ;AN000;
157 OR [SI.curdir_flags],curdir_inuse ; set in_use ;AN000;
158 JMP SHORT okdone ; ;AN000;
159resetdrv: ;AN000;
160 AND [SI.curdir_flags],NOT curdir_inuse ; reset in_use ;AN000;
161 JMP SHORT okdone ; ;AN000;
162baddrv: ;AN000;
163 MOV AX,error_invalid_drive ; error ;AN000;
164 JMP SHORT ASS_ERR ; ;AN000;
165chk08: ;AN000;
166 CMP AL,8 ; reset inuse ? ;AN000;
167 JZ srinuse ; yes ;AN000;
168
169 IF NOT INSTALLED
170 transfer NET_ASSOPER
171 ELSE
172 PUSH AX
173 MOV AX,(multnet SHL 8) OR 30
174 INT 2FH
175 POP BX ; Don't zap error code in AX
176 JC ASS_ERR
177okdone:
178 transfer SYS_RET_OK
179
180ASS_ERR:
181 transfer SYS_RET_ERR
182 ENDIF
183
184EndProc $AssignOper
185
186Break <FIND_DPB - Find a DPB from a drive number>
187
188; Inputs: AL has drive number A = 0
189; Outputs: Carry Set
190; No DPB for this drive number
191; Carry Clear
192; DS:SI points to DPB for drive
193; registers modified: DS,SI
194Procedure FIND_DPB,NEAR
195 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
196 LDS SI,[DPBHEAD]
197DPB_LOOP:
198 CMP SI,-1
199 JZ NO_DPB
200 CMP AL,[SI.dpb_drive]
201 retz ; Carry clear
202 LDS SI,[SI.dpb_next_dpb]
203 JMP DPB_LOOP
204
205NO_DPB:
206 STC
207 return
208EndProc FIND_DPB
209
210Break <InitCDS - set up an empty CDS>
211
212; Inputs: ThisCDS points to CDS
213; AL has uppercase drive letter
214; Outputs: ThisCDS is now empty
215; ES:DI point to CDS
216; Carry set if no DPB associated with drive
217; registers modified: AH,ES,DI
218Procedure InitCDS,NEAR
219 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
220 MOV AH,':'
221 PUSH AX
222 SUB AL,"A"-1 ; A = 1
223 CMP [NUMIO],AL
224 POP AX
225 LES DI,[THISCDS]
226 MOV ES:[DI.curdir_flags],0 ; "free" CDS
227 JB RET_OK ; Drive does not map a physical drive
228 MOV WORD PTR ES:[DI.curdir_text],AX
229 PUSH AX
230 MOV AX,"\"
231 MOV WORD PTR ES:[DI.curdir_text+2],AX ; NUL terminate
232 POP AX
233 OR ES:[DI.curdir_flags],curdir_inuse
234 MOV ES:[DI.curdir_END],2 ; MZ 3 Nov 83
235 MOV ES:[DI.curdir_ID],0
236 MOV ES:[DI.curdir_ID+2],0
237 PUSH AX
238 PUSH DS
239 PUSH SI
240 SUB AL,"A" ; A = 0
241 invoke FIND_DPB
242 JC PRET ; OOOOPPPPPSSSS!!!!
243 MOV WORD PTR ES:[DI.curdir_devptr],SI
244 MOV WORD PTR ES:[DI.curdir_devptr+2],DS
245PRET:
246 POP SI
247 POP DS
248 POP AX
249RET_OK: return
250EndProc InitCDS
251
252Break <$UserOper - get/set current user ID (for net)>
253
254;
255; $UserOper - retrieve or initiate a user id string. MSDOS will only
256; maintain this string and do no verifications.
257;
258; Inputs: AL has function type (0-get 1-set 2-printer-set 3-printer-get
259; 4-printer-set-flags,5-printer-get-flags)
260; DS:DX is user string pointer (calls 1,2)
261; ES:DI is user buffer (call 3)
262; BX is assign index (calls 2,3,4,5)
263; CX is user number (call 1)
264; DX is flag word (call 4)
265; Outputs: If AL = 0 then the current user string is written to DS:DX
266; and user CX is set to the user number
267; If AL = 3 then CX bytes have been put at input ES:DI
268; If AL = 5 then DX is flag word
269
270Procedure $UserOper,NEAR
271 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
272 PUSH AX
273 SUB AL,1 ; quick dispatch on 0,1
274 POP AX
275 JB UserGet ; return to user the string
276 JZ UserSet ; set the current user
277 CMP AL,5 ; test for 2,3,4 or 5
278 JBE UserPrint ; yep
279 MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
280 error error_Invalid_Function ; not 0,1,2,3
281
282UserGet:
283; Transfer MYNAME to DS:DX
284; Set Return CX to MYNUM
285 PUSH DS ; switch registers
286 POP ES
287 MOV DI,DX ; destination
288 MOV CX,[MYNUM] ; Get number
289 invoke get_user_stack
290 MOV [SI.User_CX],CX ; Set number return
291 Context DS ; point to DOSGroup
292ASSUME DS:DOSGROUP
293 MOV SI,OFFSET DOSGroup:MyName ; point source to user string
294UserMove:
295ASSUME DS:NOTHING
296 MOV CX,15
297 REP MOVSB ; blam.
298 XOR AX,AX ; 16th byte is 0
299 STOSB
300UserBye:
301 transfer sys_ret_ok ; no errors here
302
303UserSet:
304ASSUME DS:NOTHING
305; Transfer DS:DX to MYNAME
306; CX to MYNUM
307 MOV [MYNUM],CX
308 MOV SI,DX ; user space has source
309 Context ES
310 MOV DI,OFFSET DOSGroup:MyName ; point dest to user string
311 INC [DiffNam] ; signal change
312 JMP UserMove
313
314UserPrint:
315 ASSUME ES:NOTHING
316IF NOT Installed
317 transfer PRINTER_GETSET_STRING
318ELSE
319 PUSH AX
320 MOV AX,(multNET SHL 8) OR 31
321 INT 2FH
322 POP DX ; Clean stack
323 JNC OKPA
324 transfer SYS_RET_ERR
325
326OKPA:
327 transfer SYS_RET_OK
328ENDIF
329
330EndProc $UserOper
331
332Break <GetVisDrv - return visible drive>
333
334;
335; GetVisDrv - correctly map non-spliced inuse drives
336;
337; Inputs: AL has drive identifier (0=default)
338; Outputs: Carry Set - invalid drive/macro
339; Carry Clear - AL has physical drive (0=A)
340; ThisCDS points to CDS
341; Registers modified: AL
342
343Procedure GetVisDrv,NEAR
344 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
345 CALL GetThisDrv ; get inuse drive
346 retc
347 SaveReg <DS,SI>
348 LDS SI,ThisCDS
349 TEST [SI].curdir_flags,curdir_splice
350 RestoreReg <SI,DS>
351 retz ; if not spliced, return OK
352 MOV [DrvErr],error_invalid_drive ;IFS. ;AN000;
353 STC ; signal error
354 return
355EndProc GetVisDrv
356
357Break <Getthisdrv - map a drive designator (0=def, 1=A...)>
358
359;
360; GetThisDrv - look through a set of macros and return the current drive and
361; macro pointer
362;
363; Inputs: AL has drive identifier (1=A, 0=default)
364; Outputs:
365; Carry Set - invalid drive/macro
366; Carry Clear - AL has physical drive (0=A)
367; ThisCDS points to macro
368; Registers modified: AL
369
370Procedure GetThisDrv,NEAR
371 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
372 OR AL,AL ; are we using default drive?
373 JNZ GetMap ; no, go get the CDS pointers
374 MOV AL,[CurDrv] ; get the current drive
375 INC AL ; Counteract next instruction
376GetMap:
377 DEC AL ; 0 = A
378 SaveReg <DS,SI> ; save world
379 mov [EXTERR_LOCUS],errLOC_Disk
380 TEST fSharing,-1 ; Logical or Physical?
381 JZ Not_SRVC ; Logical
382 SaveReg <AX,ES,DI>
383 MOV WORD PTR ThisCDS,OFFSET DOSGroup:DummyCDS
384 MOV WORD PTR ThisCDS+2,CS ; ThisCDS = &DummyCDS;
385 ADD AL,'A'
386 CALL InitCDS ; InitCDS(c);
387 TEST ES:[DI.curdir_flags],curdir_inuse ; Clears carry
388 RestoreReg <DI,ES,AX>
389 JZ GetBerr ; Not a physical drive.
390 JMP SHORT GetBye ; carry clear
391
392Not_SRVC:
393 invoke GetCDSFromDrv
394 JC GetBerr2 ; Unassigned CDS -> return error already set
395 TEST [SI.curdir_flags],curdir_inuse ; Clears Carry
396 JNZ GetBye ; carry clear
397GetBerr:
398 MOV AL,error_not_DOS_disk ;AN000;IFS. Formatted IFS drive
399 CMP WORD PTR [SI.curdir_devptr],0 ;AN000;IFS. dpb ptr =0 ?
400 JNZ notfat ;AN000;IFS. no
401GetBerr2:
402 MOV AL,error_invalid_drive ;AN000;;IFS. invalid FAT drive
403notfat: ;AN000;
404 MOV [DrvErr],AL ;AN000;;IFS. save this for IOCTL
405 mov [EXTERR_LOCUS],errLOC_UNK
406 STC
407GetBye: RestoreReg <SI,DS> ; restore world
408 return
409EndProc GetThisDrv
410
411Break <GetCDSFromDrv - convert a drive number to a CDS pointer>
412
413;
414; GetCDSFromDrv - given a physical drive number, convert it to a CDS
415; pointer, returning an error if the drive number is greater than the
416; number of CDS's
417;
418; Inputs: AL is physical unit # A=0...
419; Outputs: Carry Set if Bad Drive
420; Carry Clear
421; DS:SI -> CDS
422; [THISCDS] = DS:SI
423; Registers modified: DS,SI
424
425Procedure GetCDSFromDrv,NEAR
426 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
427 CMP AL,[CDSCount] ; is this a valid designator
428 JB GetCDS ; yes, go get the macro
429 STC ; signal error
430 return ; bye
431GetCDS:
432 SaveReg <BX,AX>
433 LDS SI,[CDSAddr] ; get pointer to table
434 MOV BL,SIZE CurDir_list ; size in convenient spot
435 MUL BL ; get net offset
436 ADD SI,AX ; convert to true pointer
437 MOV WORD PTR [ThisCDS],SI ; store convenient offset
438 MOV WORD PTR [ThisCDS+2],DS ; store convenient segment
439 RestoreReg <AX,BX>
440 CLC ; no error
441 return ; bye!
442EndProc GetCDSFromDrv
443
444CODE ends
445END
diff --git a/v4.0/src/DOS/MACRO2.ASM b/v4.0/src/DOS/MACRO2.ASM
new file mode 100644
index 0000000..a3ff4cc
--- /dev/null
+++ b/v4.0/src/DOS/MACRO2.ASM
@@ -0,0 +1,1281 @@
1; SCCSID = @(#)macro2.asm 1.2 85/07/23
2TITLE MACRO2 - Pathname and macro related internal routines
3NAME MACRO2
4;
5; TransFCB written
6; TransPath written
7; TransPathSet written
8; TransPathNoSet Written
9; Canonicalize written
10; PathSep written
11; SkipBack written
12; CopyComponent written
13; Splice written
14; $NameTrans written
15; DriveFromText
16; TextFromDrive
17; PathPref
18; ScanPathChar
19;
20; Revision history:
21;
22; Created: MZ 4 April 1983
23; MZ 18 April 1983 Make TransFCB handle extended FCBs
24; AR 2 June 1983 Define/Delete macro for NET redir.
25; MZ 3 Nov 83 Fix InitCDS to reset length to 2
26; MZ 4 Nov 83 Fix NetAssign to use STRLEN only
27; MZ 18 Nov 83 Rewrite string processing for subtree
28; aliasing.
29; BAS 3 Jan 85 ScanPathChar to search for path separator
30; in null terminated string.
31;
32; MSDOS performs several types of name translation. First, we maintain for
33; each valid drive letter the text of the current directory on that drive.
34; For invalid drive letters, there is no current directory so we pretend to
35; be at the root. A current directory is either the raw local directory
36; (consisting of drive:\path) or a local network directory (consisting of
37; \\machine\path. There is a limit on the point to which a .. is allowed.
38;
39; Given a path, MSDOS will transform this into a real from-the-root path
40; without . or .. entries. Any component that is > 8.3 is truncated to
41; this and all * are expanded into ?'s.
42;
43; The second part of name translation involves subtree aliasing. A list of
44; subtree pairs is maintained by the external utility SUBST. The results of
45; the previous 'canonicalization' are then examined to see if any of the
46; subtree pairs is a prefix of the user path. If so, then this prefix is
47; replaced with the other subtree in the pair.
48;
49; A third part involves mapping this "real" path into a "physical" path. A
50; list of drive/subtree pairs are maintained by the external utility JOIN.
51; The output of the previous translation is examined to see if any of the
52; subtrees in this list are a prefix of the string. If so, then the prefix
53; is replaced by the appropriate drive letter. In this manner, we can
54; 'mount' one device under another.
55;
56; The final form of name translation involves the mapping of a user's
57; logical drive number into the internal physical drive. This is
58; accomplished by converting the drive number into letter:CON, performing
59; the above translation and then converting the character back into a drive
60; number.
61;
62; curdir_list STRUC
63; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir
64; curdir_flags DW ? ; various flags
65; curdir_devptr DD ? ; local pointer to DPB or net device
66; curdir_ID DW ? ; cluster of current dir (net ID)
67; DW ?
68; curdir_end DW ? ; end of assignment
69; curdir_list ENDS
70; curdir_netID EQU DWORD PTR curdir_ID
71; ;Flag word masks
72; curdir_isnet EQU 1000000000000000B
73; curdir_inuse EQU 0100000000000000B
74;
75;
76; There are two main entry points: TransPath and TransFCB. TransPath will
77; take a path and form the real text of the pathname with all . and ..
78; removed. TransFCB will translate an FCB into a path and then invoke
79; TransPath.
80;
81; Implementation note: CURDIR_End field points to the point in the text
82; string where the user may back up to via .. It is the location of a
83; separator character. For the root, it points at the leading /. For net
84; assignments it points at the end (nul) of the initial assignment:
85; A:/ \\foo\bar \\foo\bar\blech\bozo
86; ^ ^ ^
87; A: -> d: /path/ path/ text
88;
89; A000 version 4.00 Jan. 1988
90
91.xlist
92;
93; get the appropriate segment definitions
94;
95include dosseg.asm
96
97CODE SEGMENT BYTE PUBLIC 'CODE'
98 ASSUME SS:DOSGroup,CS:DOSGroup
99
100.xcref
101INCLUDE DOSSYM.INC
102INCLUDE DEVSYM.INC
103.cref
104.list
105.sall
106
107Installed = TRUE
108
109 I_need Splices,BYTE ; TRUE => splices are being done.
110 I_need WFP_Start,WORD ; pointer to beginning of expansion
111 I_need Curr_Dir_End,WORD ; offset to end of current dir
112 I_need ThisCDS,DWORD ; pointer to CDS used
113 I_need ThisDPB,DWORD ; pointer to DPB used
114 I_need NAME1,11 ; Parse output of NameTrans
115 I_need OpenBuf,128 ; ususal destination of strings
116 I_need ExtFCB,BYTE ; flag for extended FCBs
117 I_need Sattrib,BYTE ; attribute of search
118 I_need fSplice,BYTE ; TRUE => do splice after canonicalize
119 I_need fSharing,BYTE ; TRUE => no redirection allowed
120 I_Need NoSetDir,BYTE ; TRUE => syscall is interested in
121 ; entry, not contents. We splice only
122 ; inexact matches
123 I_Need cMeta,BYTE ; count of meta chars in path
124 I_Need Temp_Var,WORD ;AN000; variable for temporary use 3/31/KK
125 I_Need DOS34_FLAG,WORD ;AN000; variable for dos34
126 I_Need NO_FILTER_PATH,DWORD ;AN000; pointer to orignal path
127Table SEGMENT
128 EXTRN CharType:BYTE
129Table ENDS
130
131BREAK <TransFCB - convert an FCB into a path, doing substitution>
132
133;
134; TransFCB - Copy an FCB from DS:DX into a reserved area doing all of the
135; gritty substitution.
136;
137; Inputs: DS:DX - pointer to FCB
138; ES:DI - point to destination
139; Outputs: Carry Set - invalid path in final map
140; Carry Clear - FCB has been mapped into ES:DI
141; Sattrib is set from possibly extended FCB
142; ExtFCB set if extended FCB found
143; Registers modified: most
144
145Procedure TransFCB,NEAR
146 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
147PUBLIC MACRO001S,MACRO001E
148MACRO001S:
149 LocalVar FCBTmp,15
150MACRO001E:
151 Enter
152 Context ES ; get DOSGroup addressability
153 SaveReg <ES,DI> ; save away final destination
154 LEA DI,FCBTmp ; point to FCB temp area
155 MOV [ExtFCB],0 ; no extended FCB found
156 MOV [Sattrib],0 ; default search attributes
157 invoke GetExtended ; get FCB, extended or not
158 JZ GetDrive ; not an extended FCB, get drive
159 MOV AL,[SI-1] ; get attributes
160 MOV [SAttrib],AL ; store search attributes
161 MOV [ExtFCB],-1 ; signal extended FCB
162GetDrive:
163 LODSB ; get drive byte
164 invoke GetThisDrv
165 jc BadPack
166 CALL TextFromDrive ; convert 0-based drive to text
167;
168; Scan the source to see if there are any illegal chars
169;
170 MOV BX,OFFSET DOSGroup:CharType
171 IF DBCS ;AN000;
172;----------------------------- Start of DBCS 2/13/KK
173 SaveReg <SI> ;AN000;; back over name, ext
174 MOV CX,8 ;AN000;; 8 chars in main part of name
175FCBScan:LODSB ;AN000;; get a byte
176 invoke testkanj ;AN000;
177 jz notkanj2 ;AN000;
178 DEC CX ;AN000;
179 JCXZ VolidChck ;AN000;; Kanji half char screw up
180 LODSB ;AN000;; second kanji byte
181 jmp short Nextch ;AN000;
182VolidChck: ;AN000;
183 TEST [SAttrib],attr_volume_id ;AN000;; volume id ?
184 JZ Badpack ;AN000;; no, error
185 OR [DOS34_FLAG],DBCS_VOLID ;AN000;; no, error
186 DEC CX ;AN000;; cx=-1
187 INC SI ;AN000;; next char
188 JMP SHORT FCBScango ;AN000;
189notkanj2: ;AN000;
190 XLAT ES:CharType ;AN000;;get bits
191 TEST AL,fFCB ;AN000;
192 JZ BadPack ;AN000;
193NextCh: ;AN000;
194 LOOP FCBScan ;AN000;
195FCBScango: ;AN000;
196 ADD CX,3 ;AN000;; Three chars in extension
197FCBScanE: ;AN000;
198 LODSB ;AN000;
199 invoke testkanj ;AN000;
200 jz notkanj3 ;AN000;
201 DEC CX ;AN000;
202 JCXZ BadPack ;AN000;; Kanji half char problem
203 LODSB ;AN000;; second kanji byte
204 jmp short NextChE ;AN000;
205notkanj3: ;AN000;
206 XLAT ES:CharType ;AN000;; get bits
207 TEST AL,fFCB ;AN000;
208 JZ BadPack ;AN000;
209NextChE: ;AN000;
210 LOOP FCBScanE ;AN000;
211;----------------------------- End of DBCS 2/13/KK
212 ELSE
213
214 MOV CX,11
215 SaveReg <SI> ; back over name, ext
216FCBScan:LODSB ; get a byte
217 XLAT ES:CharType ; get bits
218 TEST AL,fFCB
219 JZ BadPack
220NextCh: LOOP FCBScan
221 ENDIF
222 RestoreReg <SI>
223 MOV BX,DI
224 invoke PackName ; crunch the path
225 RestoreReg <DI,ES> ; get original destination
226 Context DS ; get DS addressability
227 LEA SI,FCBTmp ; point at new pathname
228 CMP BYTE PTR [BX],0
229 JZ BadPack
230 SaveReg <BP>
231 CALL TransPathSet ; convert the path
232 RestoreReg <BP>
233 JNC FCBRet ; bye with transPath error code
234BadPack:
235 STC
236 MOV AL,error_path_not_found
237FCBRet: Leave
238 return
239EndProc TransFCB,NoCheck
240
241BREAK <TransPath - copy a path, do string sub and put in current dir>
242
243;
244; TransPath - copy a path from DS:SI to ES:DI, performing component string
245; substitution, insertion of current directory and fixing . and ..
246; entries. Perform splicing. Allow input string to match splice
247; exactly.
248;
249; TransPathSet - Same as above except No splicing is performed if input path
250; matches splice.
251;
252; TransPathNoSet - No splicing/local using is performed at all.
253;
254; The following anomalous behaviour is required:
255;
256; Drive letters on devices are ignored. (set up DummyCDS)
257; Paths on devices are ignored. (truncate to 0-length)
258; Raw net I/O sets ThisCDS => NULL.
259; fSharing => dummyCDS and no subst/splice. Only canonicalize.
260;
261; Other behaviour:
262;
263; ThisCDS set up.
264; FatRead done on local CDS.
265; ValidateCDS done on local CDS.
266;
267; Brief flowchart:
268;
269; if fSharing then
270; set up DummyCDS (ThisCDS)
271; canonicalize (sets cMeta)
272; splice
273; fatRead
274; return
275; if \\ or d:\\ lead then
276; set up null CDS (ThisCDS)
277; canonicalize (sets cMeta)
278; return
279; if device then
280; set up dummyCDS (ThisCDS)
281; canonicalize (sets cMeta)
282; return
283; if file then
284; getCDS (sets (ThisCDS) from name)
285; validateCDS (may reset current dir)
286; Copy current dir
287; canonicalize (set cMeta)
288; splice
289; generate correct CDS (ThisCDS)
290; if local then
291; fatread
292; return
293;
294; Inputs: DS:SI - point to ASCIZ string path
295; DI - point to buffer in DOSGroup
296; Outputs: Carry Set - invalid path specification: too many .., bad
297; syntax, etc. or user FAILed to I 24.
298; WFP_Start - points to beginning of buffer
299; Curr_Dir_End - points to end of current dir in path
300; DS - DOSGroup
301; Registers modified: most
302
303Procedure TransPath,NEAR
304 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
305 XOR AL,AL
306 JMP SHORT SetSplice
307 Entry TransPathSet
308 MOV AL,-1
309SetSplice:
310 MOV NoSetDir,AL ; NoSetDir = !fExact;
311 MOV AL,-1
312 Entry TransPathNoSet
313 MOV WORD PTR [NO_FILTER_PATH],SI ;AN000;;IFS. save old path for IFS
314 MOV WORD PTR [NO_FILTER_PATH+2],DS ;AN000;;IFS.
315
316 MOV fSplice,AL ; fSplice = TRUE;
317 MOV cMeta,-1
318 MOV WFP_Start,DI
319 MOV Curr_Dir_End,-1 ; crack from start
320 Context ES
321 LEA BP,[DI+TEMPLEN] ; end of buffer
322;
323; if this is through the server dos call, fsharing is set. We set up a
324; dummy cds and let the operation go.
325;
326 TEST fSharing,-1 ; if no sharing
327 JZ CheckUNC ; skip to UNC check
328;
329; ES:DI point to buffer
330;
331 CALL DriveFromText ; get drive and advance DS:SI
332 invoke GetThisDrv ; Set ThisCDS and convert to 0-based
333 jc NoPath
334 CALL TextFromDrive ; drop in new
335 LEA BX,[DI+1] ; backup limit
336 CALL Canonicalize ; copy and canonicalize
337 retc ; errors
338;
339; Perform splices for net guys.
340;
341 Context DS
342 MOV SI,wfp_Start ; point to name
343 TEST fSplice,-1
344 JZ NoServerSplice
345 CALL Splice
346NoServerSplice:
347 Context DS ; for FATREAD
348 LES DI,ThisCDS ; for fatread
349 EnterCrit critDisk
350 Invoke FatRead_CDS
351 LeaveCrit critDisk
352NoPath:
353 MOV AL,error_path_not_found ; Set up for possible bad path error
354 return ; any errors are in Carry flag
355 ASSUME DS:NOTHING
356;
357; Let the network decide if the name is for a spooled device. It will map
358; the name if so.
359;
360CheckUnc:
361 MOV WORD PTR ThisCDS,-1 ; NULL thisCDS
362 CallInstall NetSpoolCheck,multNet,35
363 JNC UNCDone
364;
365; At this point the name is either a UNC-style name (prefixed with two leading
366; \\s) or is a local file/device. Remember that if a net-spooled device was
367; input, then the name has been changed to the remote spooler by the above net
368; call. Also, there may be a drive in front of the \\.
369;
370NO_CHECK:
371 CALL DriveFromText ; eat drive letter
372 PUSH AX ; save it
373 MOV AX,WORD PTR [SI] ; get first two bytes of path
374 Invoke PathChrCmp ; convert to normal form
375 XCHG AH,AL ; swap for second byte
376 Invoke PathChrCmp ; convert to normal form
377 JNZ CheckDevice ; not a path char
378 CMP AH,AL ; are they same?
379 JNZ CheckDevice ; nope
380;
381; We have a UNC request. We must copy the string up to the beginning of the
382; local machine root path
383;
384
385 POP AX
386 MOVSW ; get the lead \\
387UNCCpy: LODSB ; get a byte
388 IF DBCS ;AN000;
389;----------------------------- Start of DBCS 2/23/KK
390 invoke testkanj ;AN000;
391 jz notkanj1 ;AN000;
392 STOSB ;AN000;
393 LODSB ;AN000;
394 OR AL,AL ;AN000;
395 JZ UNCTerm ;AN000;; Ignore half kanji error for now
396 STOSB ;AN000;
397 jmp UNCCpy ;AN000;
398notkanj1: ;AN000;
399;----------------------------- End of DBCS 2/23/KK
400 ENDIF ;AN000;
401 invoke UCase ;AN000;; convert the char
402 OR AL,AL
403 JZ UNCTerm ; end of string. All done.
404 Invoke PathChrCmp ; is it a path char?
405 MOV BX,DI ; backup position
406 STOSB
407 JNZ UNCCpy ; no, go copy
408 CALL Canonicalize ; wham (and set cMeta)
409UNCDone:
410 Context DS
411 IF DBCS
412;----------------------------- Start of DBCS 2/23/KK
413 retc ;AN000; Return if error from Canonicalize
414
415; Although Cononicalize has done lots of good things for us it may also have
416; done e5 to 05 conversion on the fisrt char following a path sep char which is
417; not wanted on a UNC request as this should be left for the remote station.
418; The simplest thing to do is check for such conversions and convert them back
419; again.
420; This check loop is also called from the DoFile section of TransPath if the
421; file is a remote file. Entry point when called is TP_check05 with the
422; inputs/outputs as follows;
423; Inputs : ES:DI = Buffer to check for re-conversion
424; Outputs: None
425; Used : DI,AX
426
427
428 MOV DI,WFP_start ;AN000;; ES:DI points to converted string
429TP_check05: ;AN000;
430 MOV AL,BYTE PTR ES:[DI] ;AN000;; Get character from path
431 OR AL,AL ;AN000;; End of null terminated path?
432 JZ TP_end05 ;AN000;; Finished, CF =0 from OR (ret success)
433 invoke testkanj ;AN000;; Kanji lead character?
434 JZ TP_notK ;AN000;; Check for path seperator if not
435 INC DI ;AN000;; Bypass Kanji second byte
436 JMP TP_nxt05 ;AN000;; Go to check next character
437TP_notK: ;AN000;
438 invoke PathChrCmp ;AN000;; Is it a path seperator char?
439 JNZ TP_nxt05 ;AN000;; Check next character if not
440 CMP BYTE PTR ES:[DI+1],05 ;AN000;; 05 following path sep char?
441 JNZ TP_nxt05 ;AN000;; Check next character if not
442 MOV BYTE PTR ES:[DI+1],0E5h ;AN000;; Convert 05 back to E5
443TP_nxt05: ;AN000;
444 INC DI ;AN000;; Point to next char in path
445 JMP TP_check05 ;AN000;; Test all chars in path
446TP_end05:
447;----------------------------- End of DBCS 2/23/KK
448 ENDIF ;AN000;
449 return ; return error code
450
451 ASSUME DS:NOTHING
452UNCTerm:
453 STOSB ;AN000;
454 JMP UNCDone ;AN000;
455
456CheckDevice:
457;
458; Check DS:SI for device. First eat any path stuff
459;
460 POP AX ; retrieve drive info
461 CMP BYTE PTR DS:[SI],0 ; check for null file
462 JNZ CheckPath
463 MOV AL,error_file_not_found ; bad file error
464 STC ; signal error on null input
465 RETURN ; bye!
466CheckPath:
467 SaveReg <AX,BP> ; save drive number
468 Invoke CheckThisDevice ; snoop for device
469 RestoreReg <BP,AX> ; get drive letter back
470 JNC DoFile ; yes we have a file.
471;
472; We have a device. AX has drive letter. At this point we may fake a CDS ala
473; sharing DOS call. We know by getting here that we are NOT in a sharing DOS
474; call.
475;
476 MOV fSharing,-1 ; simulate sharing dos call
477 invoke GetThisDrv ; set ThisCDS and init DUMMYCDS
478 MOV fSharing,0 ;
479;
480; Now that we have noted that we have a device, we put it into a form that
481; getpath can understand. Normally getpath requires d:\ to begin the input
482; string. We relax this to state that if the d:\ is present then the path
483; may be a file. If D:/ (note the forward slash) is present then we have
484; a device.
485;
486 CALL TextFromDrive
487 MOV AL,'/' ; path sep.
488 STOSB
489 invoke StrCpy ; move remainder of string
490 CLC ; everything OK.
491 Context DS ; remainder of OK stuff
492 return
493;
494; We have a file. Get the raw CDS.
495;
496DoFile:
497 ASSUME DS:NOTHING
498 invoke GetVisDrv ; get proper CDS
499 MOV AL,error_path_not_found ; Set up for possible bad file error
500 retc ; CARRY set -> bogus drive/spliced
501;
502; ThisCDS has correct CDS. DS:SI advanced to point to beginning of path/file.
503; Make sure that CDS has valid directory; ValidateCDS requires a temp buffer
504; Use the one that we are going to use (ES:DI).
505;
506 SaveReg <DS,SI,ES,DI> ; save all string pointers.
507 invoke ValidateCDS ; poke CDS amd make everything OK
508 RestoreReg <DI,ES,SI,DS> ; get back pointers
509 MOV AL,error_path_not_found ; Set up for possible bad path error
510 retc ; someone failed an operation
511;
512; ThisCDS points to correct CDS. It contains the correct text of the
513; current directory. Copy it in.
514;
515 SaveReg <DS,SI>
516 LDS SI,ThisCDS ; point to CDS
517 MOV BX,DI ; point to destination
518 ADD BX,[SI].curdir_end ; point to backup limit
519; LEA SI,[SI].curdir_text ; point to text
520 LEA BP,[DI+TEMPLEN] ; regenerate end of buffer
521 IF DBCS ;AN000;
522;------------------------ Start of DBCS 2/13/KK
523Kcpylp: ;AN000;
524 LODSB ;AN000;
525 invoke TestKanj ;AN000;
526 jz Notkanjf ;AN000;
527 STOSB ;AN000;
528 MOVSB ;AN000;
529 CMP BYTE PTR [SI],0 ;AN000;
530 JNZ Kcpylp ;AN000;
531 MOV AL, '\' ;AN000;
532 STOSB ;AN000;
533 JMP SHORT GetOrig ;AN000;
534Notkanjf: ;AN000;
535 STOSB ;AN000;
536 OR AL,AL ;AN000;
537 JNZ Kcpylp ;AN000;
538 DEC DI ;AN000;; point to NUL byte
539
540;------------------------ End of DBCS 2/13/KK
541 ELSE ;AN000;
542 invoke FStrCpy ; copy string. ES:DI point to end
543 DEC DI ; point to NUL byte
544 ENDIF ;AN000;
545;
546; Make sure that there is a path char at end.
547;
548 MOV AL,'\'
549 CMP ES:[DI-1],AL
550 JZ GetOrig
551 STOSB
552;
553; Now get original string.
554;
555GetOrig:
556 DEC DI ; point to path char
557 RestoreReg <SI,DS>
558;
559; BX points to the end of the root part of the CDS (at where a path char
560; should be) . Now, we decide whether we use this root or extend it with the
561; current directory. See if the input string begins with a leading \
562;
563 CALL PathSep ; is DS:SI a path sep?
564 JNZ PathAssure ; no, DI is correct. Assure a path char
565 OR AL,AL ; end of string?
566 JZ DoCanon ; yes, skip.
567;
568; The string does begin with a \. Reset the beginning of the canonicalization
569; to this root. Make sure that there is a path char there and advance the
570; source string over all leading \'s.
571;
572 MOV DI,BX ; back up to root point.
573SkipPath:
574 LODSB
575 invoke PathChrCmp
576 JZ SkipPath
577 DEC SI
578 OR AL,AL
579 JZ DoCanon
580;
581; DS:SI start at some file name. ES:DI points at some path char. Drop one in
582; for yucks.
583;
584PathAssure:
585 MOV AL,'\'
586 STOSB
587;
588; ES:DI point to the correct spot for canonicalization to begin.
589; BP is the max extent to advance DI
590; BX is the backup limit for ..
591;
592DoCanon:
593 CALL Canonicalize ; wham.
594 retc ; badly formatted path.
595 IF DBCS ;AN000;
596;--------------------- Start of DBCS 2/13/KK
597; Although Cononicalize has done lots of good things for us it may also have
598; done e5 to 05 conversion on the fisrt char following a path sep char which is
599; not wanted if this a remote file as this should be left for the remote
600; station. Check for a leading \\ in the path buffer and call TP_check05 to
601; reconvert if found.
602
603 MOV DI,WFP_start ;AN000;; ES:DI points to string
604 MOV AX,WORD PTR ES:[DI] ;AN000;; Get leading 2 chars from path buffer
605 invoke PathChrCmp ;AN000;; First char a path char?
606 JNZ TP_notremote ;AN000;; Not remote if not.
607 invoke PathChrCmp ;AN000;; Second char a path char?
608 JNZ TP_notremote ;AN000;; Not remote if not
609 CALL TP_check05 ;AN000;; Remote so convert 05 back to e5
610TP_notremote: ;AN000;
611;--------------------- End of DBCS 2/13/KK
612 ENDIF
613;
614; The string has been moved to ES:DI. Reset world to DOS context, pointers
615; to wfp_start and do string substitution. BP is still the max position in
616; buffer.
617;
618 Context DS
619 MOV DI,wfp_start ; DS:SI point to string
620 LDS SI,ThisCDS ; point to CDS
621 ASSUME DS:NOTHING
622; LEA SI,[SI].curdir_text ; point to text
623 CALL PathPref ; is there a prefix?
624 JNZ DoSplice ; no, do splice
625;
626; We have a match. Check to see if we ended in a path char.
627;
628 IF DBCS ;AN000;
629;---------------------------- Start of DBCS 2/13/KK
630 PUSH BX ;AN000;
631 MOV BX,SI ;AN000;
632 MOV SI,WORD PTR ThisCDS ;AN000;; point to CDS
633LOOKDUAL: ;AN000;
634 MOV AL,BYTE PTR [SI] ;AN000;
635 invoke TESTKANJ ;AN000;
636 JZ ONEINC ;AN000;
637 INC SI ;AN000;
638 INC SI ;AN000;
639 CMP SI,BX ;AN000;
640 JB LOOKDUAL ;AN000;
641 POP BX ;AN000;; Last char was KANJI, don't look back
642 JMP SHORT Pathline ;AN000;; for path sep, there isn't one.
643 ;AN000;
644ONEINC: ;AN000;
645 INC SI ;AN000;
646 CMP SI,BX ;AN000;
647 JB LOOKDUAL ;AN000;
648 POP BX ;AN000;
649;------------------------ End of DBCS 2/13/KK
650 ENDIF ;AN000;
651 MOV AL,DS:[SI-1] ; last char to match
652 Invoke PathChrCmp ; did we end on a path char? (root)
653 JZ DoSplice ; yes, no current dir here.
654Pathline: ; 2/13/KK
655 CMP BYTE PTR ES:[DI],0 ; end at NUL?
656 JZ DoSplice
657 INC DI ; point to after current path char
658 MOV Curr_Dir_End,DI ; point to correct spot
659;
660; Splice the result.
661;
662DoSplice:
663 Context DS ; back to DOSGROUP
664 MOV SI,wfp_Start ; point to beginning of string
665 XOR CX,CX
666 TEST fSplice,-1
667 JZ SkipSplice
668 CALL Splice ; replaces in place.
669SkipSplice:
670 ASSUME DS:NOTHING
671;
672; The final thing is to assure ourselves that a FATREAD is done on the local
673; device.
674;
675 Context DS
676 LES DI,ThisCDS ; point to correct drive
677 TEST ES:[DI].curdir_flags,curdir_isnet
678 retnz ; net, no fatread necessary
679 JCXZ Done
680 EnterCrit critDisk
681 invoke FatRead_CDS
682 LeaveCrit critDisk
683 MOV AL,error_path_not_found ; Set up for possible bad path error
684Done: return ; any errors in carry flag.
685EndProc TransPath
686
687BREAK <Canonicalize - copy a path and remove . and .. entries>
688
689;
690; Canonicalize - copy path removing . and .. entries.
691;
692; Inputs: DS:SI - point to ASCIZ string path
693; ES:DI - point to buffer
694; BX - backup limit (offset from ES) points to slash
695; BP - end of buffer
696; Outputs: Carry Set - invalid path specification: too many .., bad
697; syntax, etc.
698; Carry Clear -
699; DS:DI - advanced to end of string
700; ES:DI - advanced to end of canonicalized form after nul
701; Registers modified: AX CX DX (in addition to those above)
702
703Procedure Canonicalize,NEAR
704 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
705;
706; We copy all leading path separators.
707;
708 LODSB ; while (PathChr (*s))
709 Invoke PathChrCmp
710 IF DBCS
711 JNZ CanonDec0 ; 2/19/KK
712 ELSE
713 JNZ CanonDec
714 ENDIF
715 CMP DI,BP ; if (d > dlim)
716 JAE CanonBad ; goto error;
717 STOSB
718 JMP Canonicalize ; *d++ = *s++;
719 IF DBCS ;AN000;
720CanonDec0: ;AN000; 2/19/KK
721; mov cs:Temp_Var,di ;AN000; 3/31/KK
722 ENDIF ;AN000;
723CanonDec:
724 DEC SI
725;
726; Main canonicalization loop. We come here with DS:SI pointing to a textual
727; component (no leading path separators) and ES:DI being the destination
728; buffer.
729;
730CanonLoop:
731;
732; If we are at the end of the source string, then we need to check to see that
733; a potential drive specifier is correctly terminated with a path sep char.
734; Otherwise, do nothing
735;
736 XOR AX,AX
737 CMP [SI],AL ; if (*s == 0) {
738 JNZ DoComponent
739 IF DBCS ;AN000;
740 call chk_last_colon ;AN000; 2/18/KK
741 ELSE ;AN000;
742 CMP BYTE PTR ES:[DI-1],':' ; if (d[-1] == ':')
743 ENDIF ;AN000;
744 JNZ DoTerminate
745 MOV AL,'\' ; *d++ = '\';
746 STOSB
747 MOV AL,AH
748DoTerminate:
749 STOSB ; *d++ = 0;
750 CLC ; return (0);
751 return
752 IF DBCS ;AN000;
753;---------------- Start of DBCS 2/18/KK
754chk_last_colon proc ;AN000;
755 push si ;AN000;
756 push ax ;AN000;
757 push bx ;AN000;
758 mov si,[WFP_START] ;AN000;;PTM. for cd .. use beginning of buf
759 cmp si,di ;AN000;; no data stored ?
760 jb CLC02 ;AN000;;PTM. for cd ..
761 inc si ;AN000;; make NZ flag
762 JMP SHORT CLC09 ;AN000;
763CLC02: ;AN000;
764 mov bx,di ;AN000;
765 dec bx ;AN000;
766CLC_lop: ;AN000;
767 cmp si,bx ;AN000;
768 jb CLC00 ;AN000;
769 jne CLC09 ;AN000;
770CLC01: ;AN000;
771 CMP BYTE PTR ES:[DI-1],':' ;AN000;; if (d[-1] == ':')
772 jmp CLC09 ;AN000;
773CLC00: ;AN000;
774 mov al,es:[si] ;AN000;
775 inc si ;AN000;
776 invoke testkanj ;AN000;
777 je CLC_lop ;AN000;
778 inc si ;AN000;
779 jmp CLC_lop ;AN000;
780CLC09: ;AN000;
781 pop bx ;AN000;
782 pop ax ;AN000;
783 pop si ;AN000;
784 ret ;AN000;
785chk_last_colon endp ;AN000;
786;---------------- Endt of DBCS 2/18/KK
787 ENDIF ;AN000;
788
789CanonBad:
790 CALL ScanPathChar ; check for path chars in rest of string
791 MOV AL,error_path_not_found ; Set up for bad path error
792 JZ PathEnc ; path character encountered in string
793 MOV AL,error_file_not_found ; Set bad file error
794PathEnc:
795 STC
796 return
797;
798; We have a textual component that we must copy. We uppercase it and truncate
799; it to 8.3
800;
801DoComponent: ; }
802 CALL CopyComponent ; if (!CopyComponent (s, d))
803 retc ; return (-1);
804;
805; We special case the . and .. cases. These will be backed up.
806;
807 CMP WORD PTR ES:[DI],'.' + (0 SHL 8)
808 JZ Skip1
809 CMP WORD PTR ES:[DI],'..'
810 JNZ CanonNormal
811 DEC DI ; d--;
812Skip1: CALL SkipBack ; SkipBack ();
813 MOV AL,error_path_not_found ; Set up for possible bad path error
814 retc
815 JMP CanonPath ; }
816;
817; We have a normal path. Advance destination pointer over it.
818;
819CanonNormal: ; else
820 ADD DI,CX ; d += ct;
821;
822; We have successfully copied a component. We are now pointing at a path
823; sep char or are pointing at a nul or are pointing at something else.
824; If we point at something else, then we have an error.
825;
826CanonPath:
827 CALL PathSep
828 JNZ CanonBad ; something else...
829;
830; Copy the first path char we see.
831;
832 LODSB ; get the char
833 Invoke PathChrCmp ; is it path char?
834 JNZ CanonDec ; no, go test for nul
835 CMP DI,BP ; beyond buffer end?
836 JAE CanonBad ; yep, error.
837 STOSB ; copy the one byte
838;
839; Skip all remaining path chars
840;
841CanonPathLoop:
842 LODSB ; get next byte
843 Invoke PathChrCmp ; path char again?
844 JZ CanonPathLoop ; yep, grab another
845 DEC SI ; back up
846 JMP CanonLoop ; go copy component
847EndProc Canonicalize
848
849BREAK <PathSep - determine if char is a path separator>
850
851;
852; PathSep - look at DS:SI and see if char is / \ or NUL
853; Inputs: DS:SI - point to a char
854; Outputs: AL has char from DS:SI (/ => \)
855; Zero set if AL is / \ or NUL
856; Zero reset otherwise
857; Registers modified: AL
858
859Procedure PathSep,NEAR
860 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
861 MOV AL,[SI] ; get the character
862 entry PathSepGotCh ; already have character
863 OR AL,AL ; test for zero
864 retz ; return if equal to zero (NUL)
865 invoke PathChrCmp ; check for path character
866 return ; and return HIS determination
867EndProc PathSep
868
869BREAK <SkipBack - move backwards to a path separator>
870
871;
872; SkipBack - look at ES:DI and backup until it points to a / \
873; Inputs: ES:DI - point to a char
874; BX has current directory back up limit (point to a / \)
875; Outputs: ES:DI backed up to point to a path char
876; AL has char from output ES:DI (path sep if carry clear)
877; Carry set if illegal backup
878; Carry Clear if ok
879; Registers modified: DI,AL
880
881Procedure SkipBack,NEAR
882 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
883 IF DBCS ;AN000;
884;-------------------------- Start of DBCS 2/13/KK
885 PUSH DS ;AN000;
886 PUSH SI ;AN000;
887 PUSH CX ;AN000;
888 PUSH ES ;AN000;
889 POP DS ;AN000;
890 MOV SI,BX ;AN000;; DS:SI -> start of ES:DI string
891 MOV CX,DI ;AN000;; Limit of forward scan is input DI
892 MOV AL,[SI] ;AN000;
893 invoke PathChrCmp ;AN000;
894 JNZ SkipBadP ;AN000;; Backup limit MUST be path char
895 CMP DI,BX ;AN000;
896 JBE SkipBadP ;AN000;
897 MOV DI,BX ;AN000;; Init backup point to backup limit
898Skiplp: ;AN000;
899 CMP SI,CX ;AN000;
900 JAE SkipOK ;AN000;; Done, DI is correct backup point
901 LODSB ;AN000;
902 invoke Testkanj ;AN000;
903 jz Notkanjv ;AN000;
904 lodsb ;AN000;; Skip over second kanji byte
905 JMP Skiplp ;AN000;
906NotKanjv: ;AN000;
907 invoke PathChrCmp ;AN000;
908 JNZ Skiplp ;AN000;; New backup point
909 MOV DI,SI ;AN000;; DI point to path sep
910 DEC DI ;AN000;
911 jmp Skiplp ;AN000;
912SkipOK: ;AN000;
913 MOV AL,ES:[DI] ;AN000;; Set output AL
914 CLC ;AN000;; return (0);
915 POP CX ;AN000;
916 POP SI ;AN000;
917 POP DS ;AN000;
918 return ;AN000;
919 ;AN000;
920SkipBadP: ;AN000;
921 POP CX ;AN000;
922 POP SI ;AN000;
923 POP DS ;AN000;
924;-------------------------- End of DBCS 2/13/KK
925 ELSE ;AN000;
926 CMP DI,BX ; while (TRUE) {
927 JB SkipBad ; if (d < dlim)
928 DEC DI ; goto err;
929 MOV AL,ES:[DI] ; if (pathchr (*--d))
930 invoke PathChrCmp ; break;
931 JNZ SkipBack ; }
932 CLC ; return (0);
933 return ;
934 ENDIF ;AN000;
935SkipBad: ;err:
936 MOV AL,error_path_not_found ; bad path error
937 STC ; return (-1);
938 return ;
939EndProc SkipBack
940
941Break <CopyComponent - copy out a file path component>
942
943;
944; CopyComponent - copy a file component from a path string (DS:SI) into ES:DI
945;
946; Inputs: DS:SI - source path
947; ES:DI - destination
948; ES:BP - end of buffer
949; Outputs: Carry Set - too long
950; Carry Clear - DS:SI moved past component
951; CX has length of destination
952; Registers modified: AX,CX,DX
953
954Procedure CopyComponent,NEAR
955 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
956CopyBP EQU WORD PTR [BP]
957CopyD EQU DWORD PTR [BP+2]
958CopyDoff EQU WORD PTR [BP+2]
959CopyS EQU DWORD PTR [BP+6]
960CopySoff EQU WORD PTR [BP+6]
961CopyTemp EQU BYTE PTR [BP+10]
962 SUB SP,14 ; room for temp buffer
963 SaveReg <DS,SI,ES,DI,BP>
964 MOV BP,SP
965 MOV AH,'.'
966 LODSB
967 STOSB
968 CMP AL,AH ; if ((*d++=*s++) == '.') {
969 JNZ NormalComp
970 CALL PathSep ; if (!pathsep(*s))
971 JZ NulTerm
972TryTwoDot:
973 LODSB ; if ((*d++=*s++) != '.'
974 STOSB
975 CMP AL,AH
976 JNZ CopyBad
977 CALL PathSep
978 JNZ CopyBad ; || !pathsep (*s))
979NulTerm: ; return -1;
980 XOR AL,AL ; *d++ = 0;
981 STOSB
982 MOV CopySoff,SI
983 JMP SHORT GoodRet ; }
984NormalComp: ; else {
985 MOV SI,CopySoff
986 Invoke NameTrans ; s = NameTrans (s, Name1);
987 CMP SI,CopySOff ; if (s == CopySOff)
988 JZ CopyBad ; return (-1);
989 TEST fSharing,-1 ; if (!fSharing) {
990 JNZ DoPack
991 AND DL,1 ; cMeta += fMeta;
992 ADD cMeta,DL ; if (cMeta > 0)
993 JG CopyBad ; return (-1);
994 JNZ DoPack ; else
995 OR DL,DL ; if (cMeta == 0 && fMeta == 0)
996 JZ CopyBadPath ; return (-1);
997DoPack: ; }
998 MOV CopySoff,SI
999 Context DS
1000 MOV SI,OFFSET DOSGroup:NAME1
1001 LEA DI,CopyTemp
1002 SaveReg <DI>
1003 Invoke PackName ; PackName (Name1, temp);
1004 RestoreReg <DI>
1005 Invoke StrLen ; if (strlen(temp)+d > bp)
1006 DEC CX
1007 ADD CX,CopyDoff
1008 CMP CX,CopyBP
1009 JAE CopyBad ; return (-1);
1010 MOV SI,DI ; strcpy (d, temp);
1011 LES DI,CopyD
1012 Invoke FStrCpy
1013GoodRet: ; }
1014 CLC
1015 JMP SHORT CopyEnd ; return 0;
1016CopyBad:
1017 STC
1018 CALL ScanPathChar ; check for path chars in rest of string
1019 MOV AL,error_file_not_found ; Set up for bad file error
1020 JNZ CopyEnd
1021CopyBadPath:
1022 STC
1023 MOV AL,error_path_not_found ; Set bad path error
1024CopyEnd:
1025 RestoreReg <BP,DI,ES,SI,DS>
1026 LAHF
1027 ADD SP,14 ; reclaim temp buffer
1028 Invoke Strlen
1029 DEC CX
1030 SAHF
1031 return
1032EndProc CopyComponent,NoCheck
1033
1034Break <Splice - pseudo mount by string substitution>
1035
1036;
1037; Splice - take a string and substitute a prefix if one exists. Change
1038; ThisCDS to point to physical drive CDS.
1039; Inputs: DS:SI point to string
1040; NoSetDir = TRUE => exact matches with splice fail
1041; Outputs: DS:SI points to thisCDS
1042; ES:DI points to DPB
1043; String at DS:SI may be reduced in length by removing prefix
1044; and substituting drive letter.
1045; CX = 0 If no splice done
1046; CX <> 0 otherwise
1047; ThisCDS points to proper CDS if spliced, otherwise it is
1048; left alone
1049; ThisDPB points to proper DPB
1050; Registers modified: DS:SI, ES:DI, BX,AX,CX
1051
1052Procedure Splice,NEAR
1053 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
1054 TEST Splices,-1
1055 JZ AllDone
1056 SaveReg <<WORD PTR ThisCDS>,<WORD PTR ThisCDS+2>> ; TmpCDS = ThisCDS
1057 SaveReg <DS,SI>
1058 RestoreReg <DI,ES>
1059 XOR AX,AX ; for (i=1; s = GetCDSFromDrv (i); i++)
1060SpliceScan:
1061 invoke GetCDSFromDrv
1062 JC SpliceDone
1063 INC AL
1064 TEST [SI.curdir_flags],curdir_splice
1065 JZ SpliceScan ; if ( Spliced (i) ) {
1066 SaveReg <DI>
1067 CALL PathPref ; if (!PathPref (s, d))
1068 JZ SpliceFound ;
1069SpliceSkip:
1070 RestoreReg <DI>
1071 JMP SpliceScan ; continue;
1072SpliceFound:
1073 CMP BYTE PTR ES:[DI],0 ; if (*s || NoSetDir) {
1074 JNZ SpliceDo
1075 TEST NoSetDir,-1
1076 JNZ SpliceSkip
1077SpliceDo:
1078 MOV SI,DI ; p = src + strlen (p);
1079 SaveReg <ES>
1080 RestoreReg <DS,DI>
1081 CALL TextFromDrive1 ; src = TextFromDrive1(src,i);
1082 MOV AX,Curr_Dir_End
1083 OR AX,AX
1084 JS NoPoke
1085 ADD AX,DI ; curdirend += src-p;
1086 SUB AX,SI
1087 MOV Curr_Dir_End,AX
1088NoPoke:
1089 CMP BYTE PTR [SI],0 ; if (*p)
1090 JNZ SpliceCopy ; *src++ = '\\';
1091 MOV AL,"\"
1092 STOSB
1093SpliceCopy: ; strcpy (src, p);
1094 invoke FStrCpy
1095 ADD SP,4 ; throw away saved stuff
1096 OR CL,1 ; signal splice done.
1097 JMP SHORT DoSet ; return;
1098SpliceDone: ; }
1099 ASSUME DS:NOTHING ; ThisCDS = TmpCDS;
1100 RestoreReg <<WORD PTR ThisCDS+2>,<WORD PTR ThisCDS>>
1101AllDone:
1102 XOR CX,CX
1103DoSet:
1104 LDS SI,ThisCDS ; ThisDPB = ThisCDS->devptr;
1105 LES DI,[SI].curdir_devptr
1106 MOV WORD PTR ThisDPB,DI
1107 MOV WORD PTR ThisDPB+2,ES
1108 return
1109EndProc Splice
1110
1111Break <$NameTrans - partially process a name>
1112
1113;
1114; $NameTrans - allow users to see what names get mapped to. This call
1115; performs only string substitution and canonicalization, not splicing. Due
1116; to Transpath playing games with devices, we need to insure that the output
1117; has drive letter and : in it.
1118;
1119; Inputs: DS:SI - source string for translation
1120; ES:DI - pointer to buffer
1121; Outputs:
1122; Carry Clear
1123; Buffer at ES:DI is filled in with data
1124; ES:DI point byte after nul byte at end of dest string in buffer
1125; Carry Set
1126; AX = error_path_not_found
1127; Registers modified: all
1128
1129Procedure $NameTrans,Near
1130 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
1131 SaveReg <DS,SI,ES,DI>
1132 MOV DI,OFFSET DOSGroup:OpenBuf
1133 CALL TransPath ; to translation (everything)
1134 RestoreReg <DI,ES,SI,DS>
1135 JNC TransOK
1136 transfer SYS_Ret_Err
1137TransOK:
1138 MOV SI,OFFSET DOSGroup:OpenBuf
1139 Context DS
1140GotText:
1141 Invoke FStrCpy
1142 Transfer SYS_Ret_OK
1143EndProc $NameTrans
1144
1145Break <DriveFromText - return drive number from a text string>
1146
1147;
1148; DriveFromText - examine DS:SI and remove a drive letter, advancing the
1149; pointer.
1150;
1151; Inputs: DS:SI point to a text string
1152; Outputs: AL has drive number
1153; DS:SI advanced
1154; Registers modified: AX,SI.
1155
1156Procedure DriveFromText,NEAR
1157 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
1158 XOR AL,AL ; drive = 0;
1159 CMP BYTE PTR [SI],0 ; if (*s &&
1160 retz
1161 CMP BYTE PTR [SI+1],':' ; s[1] == ':') {
1162 retnz
1163 IF DBCS ;AN000;
1164;--------------------- Start of DBCS 2/18/KK
1165 push ax ;AN000;
1166 mov al,[si] ;AN000;
1167 invoke testkanj ;AN000;
1168 pop ax ;AN000;
1169 retnz ;AN000;
1170;--------------------- End of DBCS 2/18/KK
1171 ENDIF ;AN000;
1172 LODSW ; drive = (*s | 020) - 'a'+1;
1173 OR AL,020h
1174 SUB AL,'a'-1 ; s += 2;
1175 retnz
1176 MOV AL,-1 ; nuke AL...
1177 return ; }
1178EndProc DriveFromText
1179
1180Break <TextFromDrive - convert a drive number to a text string>
1181
1182;
1183; TextFromDrive - turn AL into a drive letter: and put it at es:di with
1184; trailing :. TextFromDrive1 takes a 1-based number.
1185;
1186; Inputs: AL has 0-based drive number
1187; Outputs: ES:DI advanced
1188; Registers modified: AX
1189
1190Procedure TextFromDrive,NEAR
1191 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
1192 INC AL
1193 Entry TextFromDrive1
1194 ADD AL,'A'-1 ; *d++ = drive-1+'A';
1195 MOV AH,":" ; strcat (d, ":");
1196 STOSW
1197 return
1198EndProc TextFromDrive
1199
1200Break <PathPref - see if one path is a prefix of another>
1201
1202;
1203; PathPref - compare DS:SI with ES:DI to see if one is the prefix of the
1204; other. Remember that only at a pathchar break are we allowed to have a
1205; prefix: A:\ and A:\FOO
1206;
1207; Inputs: DS:SI potential prefix
1208; ES:DI string
1209; Outputs: Zero set => prefix found
1210; DI/SI advanced past matching part
1211; Zero reset => no prefix, DS/SI garbage
1212; Registers modified: CX
1213
1214Procedure PathPref,NEAR
1215 Invoke DStrLen ; get length
1216 DEC CX ; do not include nul byte
1217 IF DBCS ;AN000;
1218;----------------------- Start of DBCS 2/13/KK
1219 SaveReg <AX> ;AN000;; save char register
1220CmpLp: ;AN000;
1221 MOV AL,[SI] ;AN000;
1222 invoke Testkanj ;AN000;
1223 jz NotKanj9 ;AN000;
1224 CMPSW ;AN000;
1225 JNZ Prefix ;AN000;
1226 DEC CX ;AN000;
1227 LOOP CmpLp ;AN000;
1228 JMP SHORT NotSep ;AN000;
1229NotKanj9: ;AN000;
1230 CMPSB ;AN000;
1231 JNZ Prefix ;AN000;
1232 LOOP CmpLp ;AN000;
1233;----------------------- End of DBCS 2/13/KK
1234 ELSE ;AN000;
1235 REPZ CMPSB ; compare
1236 retnz ; if NZ then return NZ
1237 SaveReg <AX> ; save char register
1238 ENDIF ;AN000;
1239 MOV AL,[SI-1] ; get last byte to match
1240 Invoke PathChrCmp ; is it a path char (Root!)
1241 JZ Prefix ; yes, match root (I hope)
1242NotSep: ; 2/13/KK
1243 MOV AL,ES:[DI] ; get next char to match
1244 CALL PathSepGotCh ; was it a pathchar?
1245Prefix:
1246 RestoreReg <AX> ; get back original
1247 return
1248EndProc PathPref
1249
1250Break <ScanPathChar - see if there is a path character in a string>
1251
1252;
1253; ScanPathChar - search through the string (pointed to by DS:SI) for
1254; a path separator.
1255;
1256; Input: DS:SI target string (null terminated)
1257; Output: Zero set => path separator encountered in string
1258; Zero clear => null encountered
1259; Registers modified: SI
1260
1261Procedure ScanPathChar,NEAR
1262 LODSB ; fetch a character
1263 IF DBCS ;AN000;
1264 invoke TestKanj ;AN000;; 2/13/KK
1265 jz NotKanjr ;AN000;; 2/13/KK
1266 LODSB ;AN000;; 2/13/KK
1267 OR AL,AL ;AN000;; 2/13/KK 3/31/removed
1268 JNZ ScanPathChar ;AN000;; 2/13/KK 3/31/removed
1269 INC AL ;AN000;; 2/13/KK
1270 return ;AN000;; 2/13/KK
1271 ;AN000;
1272NotKanjr: ;AN000;; 2/13/KK
1273 ENDIF ;AN000;
1274 call PathSepGotCh
1275 JNZ ScanPathChar ; not \, / or NUL => go back for more
1276 invoke PathChrCmp ; path separator?
1277 return
1278EndProc ScanPathChar
1279
1280CODE ends
1281END
diff --git a/v4.0/src/DOS/MAKEFILE b/v4.0/src/DOS/MAKEFILE
new file mode 100644
index 0000000..12912c4
--- /dev/null
+++ b/v4.0/src/DOS/MAKEFILE
@@ -0,0 +1,221 @@
1#*************************** Makefile for DOS ***************************
2
3msg =..\messages
4inc =..\inc
5hinc =..\hinc
6make =nmake -i
7dos =.
8
9#
10###################### Dependencies begin here ##########################
11#
12
13all: msdos.sys
14
15msdos.cl1: msdos.skl \
16 $(msg)\$(COUNTRY).msg
17
18dossym.inc: $(inc)\dosmac.inc $(inc)\bpb.inc \
19 $(inc)\buffer.inc $(inc)\sysvar.inc $(inc)\vector.inc \
20 $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc $(inc)\curdir.inc \
21 $(inc)\cpmfcb.inc $(inc)\find.inc $(inc)\pdb.inc $(inc)\exe.inc \
22 $(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc $(inc)\mi.inc \
23 $(inc)\filemode.inc $(inc)\error.inc $(inc)\syscall.inc
24 echo "touch dossym.inc; files that are in ..\inc"
25
26$(inc)\nibdos.obj:
27 cd ..\inc
28 $(make)
29 cd ..\dos
30
31$(inc)\const2.obj:
32 cd ..\inc
33 $(make)
34 cd ..\dos
35
36$(inc)\msdata.obj:
37 cd ..\inc
38 $(make)
39 cd ..\dos
40
41$(inc)\mstable.obj:
42 cd ..\inc
43 $(make)
44 cd ..\dos
45
46$(inc)\msdosme.obj:
47 cd ..\inc
48 $(make)
49 cd ..\dos
50
51msdisp.obj: msdisp.asm mssw.asm disp.asm \
52 $(inc)\dossym.inc $(inc)\dosseg.asm
53
54mscode.obj: mscode.asm mssw.asm ms_code.asm \
55 $(inc)\dossym.inc $(inc)\dosseg.asm $(inc)\devsym.inc
56
57time.obj: time.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
58 $(inc)\devsym.inc
59
60getset.obj: getset.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
61 $(inc)\devsym.inc
62
63parse.obj: parse.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
64 $(inc)\devsym.inc
65
66misc.obj: misc.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
67 $(inc)\devsym.inc $(inc)\bugtyp.asm
68
69misc2.obj: misc2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
70 $(inc)\bugtyp.asm
71
72crit.obj: crit.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
73 $(inc)\bugtyp.asm
74
75cpmio.obj: cpmio.asm $(inc)\dosseg.asm \
76 $(inc)\dossym.inc \
77 $(inc)\devsym.inc \
78 kstrin.asm strin.asm
79
80cpmio2.obj: cpmio2.asm $(inc)\dosseg.asm \
81 $(inc)\dossym.inc $(inc)\devsym.inc
82
83fcbio.obj: fcbio.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
84 $(inc)\devsym.inc $(inc)\sf.inc $(inc)\fastopen.inc
85
86fcbio2.obj: fcbio2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
87 $(inc)\devsym.inc
88
89search.obj: search.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
90 $(inc)\devsym.inc
91
92path.obj: path.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
93 $(inc)\devsym.inc
94
95ioctl.obj: ioctl.asm $(inc)\ioctl.inc $(inc)\dosseg.asm \
96 $(inc)\dossym.inc $(inc)\devsym.inc
97
98delete.obj: delete.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
99 $(inc)\devsym.inc $(inc)\sf.inc $(inc)\fastxxxx.inc $(inc)\fastopen.inc
100
101rename.obj: rename.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
102 $(inc)\devsym.inc $(inc)\sf.inc
103
104finfo.obj: finfo.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
105 $(inc)\devsym.inc
106
107dup.obj: dup.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
108 $(inc)\devsym.inc
109
110create.obj: create.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
111 $(inc)\devsym.inc
112
113open.obj: open.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
114 $(inc)\devsym.inc $(inc)\fastopen.inc
115
116dinfo.obj: dinfo.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
117 $(inc)\devsym.inc $(inc)\bugtyp.asm $(inc)\buffer.inc
118
119isearch.obj: isearch.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
120 $(inc)\devsym.inc
121
122abort.obj: abort.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
123 $(inc)\devsym.inc $(inc)\sf.inc
124
125close.obj: close.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
126 $(inc)\devsym.inc $(inc)\buffer.inc
127
128dircall.obj: dircall.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
129 $(inc)\devsym.inc $(inc)\buffer.inc $(inc)\fastopen.inc
130
131disk.obj: disk.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
132 $(inc)\devsym.inc
133
134disk2.obj: disk2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
135 $(inc)\devsym.inc $(inc)\buffer.inc
136
137disk3.obj: disk3.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
138 $(inc)\devsym.inc
139
140dir.obj: dir.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
141 $(inc)\buffer.inc $(inc)\fastopen.inc
142
143dir2.obj: dir2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
144 $(inc)\buffer.inc $(inc)\fastopen.inc
145
146dev.obj: dev.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
147 $(inc)\devsym.inc
148
149mknode.obj: mknode.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
150 $(inc)\devsym.inc $(inc)\buffer.inc $(inc)\fastopen.inc \
151 $(inc)\filemode.inc
152
153rom.obj: rom.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
154 $(inc)\devsym.inc $(inc)\buffer.inc
155
156fcb.obj: fcb.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
157 $(inc)\devsym.inc
158
159msctrlc.obj: msctrlc.asm mssw.asm ctrlc.asm \
160 $(inc)\dosseg.asm $(inc)\dossym.inc $(inc)\devsym.inc \
161 $(inc)\bugtyp.asm
162
163fat.obj: fat.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
164 $(inc)\devsym.inc $(inc)\buffer.inc $(inc)\curdir.inc
165
166buf.obj: buf.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
167 $(inc)\devsym.inc $(inc)\buffer.inc
168
169proc.obj: proc.asm \
170 $(inc)\dosseg.asm $(inc)\dossym.inc $(inc)\devsym.inc \
171 $(inc)\curdir.inc \
172 exec.asm
173
174alloc.obj: alloc.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
175 $(inc)\devsym.inc
176
177srvcall.obj: srvcall.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
178 $(inc)\devsym.inc
179
180util.obj: util.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
181 $(inc)\devsym.inc
182
183macro.obj: macro.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
184 $(inc)\devsym.inc $(inc)\curdir.inc
185
186macro2.obj: macro2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
187 $(inc)\devsym.inc $(inc)\curdir.inc
188
189handle.obj: handle.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
190 $(inc)\devsym.inc $(inc)\bugtyp.asm
191
192file.obj: file.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
193 $(inc)\devsym.inc $(inc)\bugtyp.asm $(inc)\fastopen.inc \
194 $(inc)\filemode.inc
195
196lock.obj: lock.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
197 $(inc)\devsym.inc
198
199share.obj: share.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
200 $(inc)\devsym.inc
201
202extattr.obj: extattr.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
203 $(inc)\devsym.inc $(inc)\ea.inc $(inc)\buffer.inc
204
205ifs.obj: ifs.asm $(inc)\dosseg.asm $(inc)\dossym.inc \
206 $(inc)\devsym.inc $(inc)\doscntry.inc $(inc)\buffer.inc
207
208msdos.sys: msdos.cl1 $(inc)\nibdos.obj $(inc)\const2.obj \
209 $(inc)\msdata.obj mscode.obj $(inc)\msdosme.obj time.obj getset.obj \
210 parse.obj misc.obj misc2.obj crit.obj cpmio.obj cpmio2.obj \
211 $(inc)\mstable.obj msdisp.obj fcbio.obj fcbio2.obj \
212 search.obj path.obj ioctl.obj delete.obj rename.obj finfo.obj \
213 dup.obj create.obj open.obj dinfo.obj isearch.obj buf.obj \
214 abort.obj close.obj dircall.obj disk.obj disk2.obj disk3.obj dir.obj \
215 dir2.obj dev.obj mknode.obj rom.obj fcb.obj msctrlc.obj fat.obj \
216 proc.obj alloc.obj srvcall.obj util.obj macro.obj macro2.obj ifs.obj \
217 handle.obj file.obj lock.obj share.obj extattr.obj \
218 makefile msdos.lnk
219 link @msdos.lnk
220 exe2bin msdos.exe msdos.sys
221 del msdos.exe
diff --git a/v4.0/src/DOS/MISC.ASM b/v4.0/src/DOS/MISC.ASM
new file mode 100644
index 0000000..e169f32
--- /dev/null
+++ b/v4.0/src/DOS/MISC.ASM
@@ -0,0 +1,572 @@
1; SCCSID = @(#)misc.asm 1.1 85/04/10
2TITLE MISC - Miscellanious routines for MS-DOS
3NAME MISC
4;
5; Miscellaneous system calls most of which are CAVEAT
6;
7; $SLEAZEFUNC
8; $SLEAZEFUNCDL
9; $GET_INDOS_FLAG
10; $GET_IN_VARS
11; $GET_DEFAULT_DPB
12; $GET_DPB
13; $DISK_RESET
14; $SETDPB
15; $Dup_PDB
16; $CREATE_PROCESS_DATA_BLOCK
17; SETMEM
18; FETCHI_CHECK
19; $GSetMediaID
20;
21; Revision history:
22;
23; Created: ARR 30 March 1983
24;
25; A000 version 4.00 Jan. 1988
26; A001 D490 -- Change IOCTL subfunctions from 63h, 43h to 66h , 46h
27
28.xlist
29;
30; get the appropriate segment definitions
31;
32include dosseg.asm
33
34CODE SEGMENT BYTE PUBLIC 'CODE'
35 ASSUME SS:DOSGROUP,CS:DOSGROUP
36
37.xcref
38INCLUDE DOSSYM.INC
39INCLUDE DEVSYM.INC
40.cref
41.list
42
43ENTRYPOINTSEG EQU 0CH
44MAXDIF EQU 0FFFH
45SAVEXIT EQU 10
46
47 i_need LASTBUFFER,DWORD
48 i_need BuffHead,DWORD
49 i_need INDOS,BYTE
50 i_need SYSINITVAR,BYTE
51 i_need CurrentPDB,WORD
52 i_need CreatePDB,BYTE
53 i_need FATBYTE,BYTE
54 i_need THISCDS,DWORD
55 i_need THISSFT,DWORD
56 i_need FETCHI_TAG,WORD ; for TAG CHECK
57 i_need BUF_HASH_COUNT,WORD ;AN000; number of Hash Entries
58 i_need HIGH_SECTOR,WORD ;AN000; high word of sector #
59 i_need DOS34_FLAG,WORD ;AN000;
60if debug
61 I_need BugLev,WORD
62 I_need BugTyp,WORD
63include bugtyp.asm
64endif
65
66BREAK <SleazeFunc -- get a pointer to media byte>
67
68;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
69; C A V E A T P R O G R A M M E R ;
70; ;
71; Inputs:
72; None
73; Function:
74; Return Stuff sort of like old get fat call
75; Outputs:
76; DS:BX = Points to FAT ID byte (IBM only)
77; GOD help anyone who tries to do ANYTHING except
78; READ this ONE byte.
79; DX = Total Number of allocation units on disk
80; CX = Sector size
81; AL = Sectors per allocation unit
82; = -1 if bad drive specified
83
84 procedure $SLEAZEFUNC,NEAR
85ASSUME DS:NOTHING,ES:NOTHING
86
87 MOV DL,0
88
89entry $SLEAZEFUNCDL
90;Same as above except drive passed in DL (0=default, 1=A, 2=B, ...)
91
92 context DS
93 MOV AL,DL
94 invoke GETTHISDRV ; Get CDS structure
95SET_AL_RET:
96; MOV AL,error_invalid_drive ; Assume error ;AC000;
97 JC BADSLDRIVE
98 invoke DISK_INFO
99 JC SET_AL_RET ; User FAILed to I 24
100 MOV [FATBYTE],AH
101; NOTE THAT A FIXED MEMORY CELL IS USED --> THIS CALL IS NOT
102; RE-ENTRANT. USERS BETTER GET THE ID BYTE BEFORE THEY MAKE THE
103; CALL AGAIN
104 MOV DI,OFFSET DOSGROUP:FATBYTE
105 XOR AH,AH ; AL has sectors/cluster
106 invoke get_user_stack
107ASSUME DS:NOTHING
108 MOV [SI.user_CX],CX
109 MOV [SI.user_DX],BX
110 MOV [SI.user_BX],DI
111 MOV [SI.user_DS],CS ; stash correct pointer
112 return
113BADSLDRIVE:
114 transfer FCB_Ret_ERR
115EndProc $SLEAZEFUNC
116; ;
117; C A V E A T P R O G R A M M E R ;
118;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
119
120BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
121;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
122; C A V E A T P R O G R A M M E R ;
123; ;
124; Inputs:
125; None
126; Function:
127; Returns location of DOS status for interrupt routines
128; Returns:
129; Flag location in ES:BX
130
131 procedure $GET_INDOS_FLAG,NEAR
132ASSUME DS:NOTHING,ES:NOTHING
133
134 invoke get_user_stack
135 MOV [SI.user_BX],OFFSET DOSGROUP:INDOS
136 MOV [SI.user_ES],SS
137 return
138EndProc $GET_INDOS_FLAG
139; ;
140; C A V E A T P R O G R A M M E R ;
141;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
142
143BREAK <$Get_IN_VARS -- Return a pointer to DOS variables>
144;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
145; C A V E A T P R O G R A M M E R ;
146; ;
147; Return a pointer to interesting DOS variables This call is version
148; dependent and is subject to change without notice in future versions.
149; Use at risk.
150 procedure $GET_IN_VARS,NEAR
151 invoke get_user_stack
152 MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR
153 MOV [SI.user_ES],SS
154 return
155EndProc $GET_IN_VARS
156; ;
157; C A V E A T P R O G R A M M E R ;
158;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
159
160
161BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
162;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
163; C A V E A T P R O G R A M M E R ;
164; ;
165; Inputs:
166; None
167; Function:
168; Return pointer to drive parameter table for default drive
169; Returns:
170; DS:BX points to the DPB
171; AL = 0 If OK, = -1 if bad drive (call 50 only)
172
173 procedure $GET_DEFAULT_DPB,NEAR
174ASSUME DS:NOTHING,ES:NOTHING
175
176 MOV DL,0
177
178 entry $GET_DPB
179; Same as above only drive passed in DL (0=default, 1=A, 2=B, ...)
180
181 context DS
182 MOV AL,DL
183 invoke GETTHISDRV ; Get CDS structure
184 JC ISNODRV ; no valid drive
185 LES DI,[THISCDS] ; check for net CDS
186 TEST ES:[DI.curdir_flags],curdir_isnet
187 JNZ ISNODRV ; No DPB to point at on NET stuff
188 EnterCrit CritDisk
189 invoke FATRead_CDS ; Force Media Check and return DPB
190 LeaveCrit CritDisk
191 JC ISNODRV ; User FAILed to I 24, only error we
192 ; have.
193 invoke get_user_stack
194ASSUME DS:NOTHING
195 MOV [SI.user_BX],BP
196 MOV [SI.user_DS],ES
197 XOR AL,AL
198 return
199
200ISNODRV:
201 MOV AL,-1
202 return
203EndProc $GET_Default_dpb
204; ;
205; C A V E A T P R O G R A M M E R ;
206;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
207
208
209BREAK <$Disk_Reset -- Flush out all dirty buffers>
210
211 procedure $DISK_RESET,NEAR
212ASSUME DS:NOTHING,ES:NOTHING
213
214; Inputs:
215; None
216; Function:
217; Flush and invalidate all buffers
218; Returns:
219; Nothing
220
221 MOV AL,-1
222 entry $DISK_RESET2
223 context DS
224 EnterCrit critDisk
225 OR [DOS34_FLAG],FROM_DISK_RESET ;AN000;
226 invoke FLUSHBUF
227 AND [DOS34_FLAG],NO_FROM_DISK_RESET ;AN000;
228;
229; We will "ignore" any errors on the flush, and go ahead and invalidate. This
230; call doesn't return any errors and it is supposed to FORCE a known state, so
231; let's do it.
232;
233; Invalidate 'last-buffer' used
234;
235 MOV BX,-1
236 MOV WORD PTR [LASTBUFFER+2],BX
237 MOV WORD PTR [LASTBUFFER],BX
238;
239; TEST [DOS34_FLAG],IFS_DRIVE_RESET ;AN000;;IFS. from ifs call back ?
240; JZ FreeDone ;AN000;;IFS. no
241; AND [DOS34_FLAG],NO_IFS_DRIVE_RESET ;AN000;;IFS. clear the flag
242; LeaveCrit critDisk ;AN000;;IFS.
243; return ;AN000;;IFS. return
244FreeDone:
245 LeaveCrit critDisk
246 MOV AX,-1
247 CallInstall NetFlushBuf,multNET,32
248 return
249EndProc $DISK_RESET
250
251BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
252;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
253; C A V E A T P R O G R A M M E R ;
254; ;
255 procedure $SETDPB,NEAR
256ASSUME DS:NOTHING,ES:NOTHING
257
258; Inputs:
259; ES:BP Points to DPB
260; DS:SI Points to BPB
261; Function:
262; Build a correct DPB from the BPB
263; Outputs:
264; ES:BP and DS preserved all others destroyed
265
266 MOV DI,BP
267 ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
268 LODSW
269 STOSW ; dpb_sector_size
270 CMP BYTE PTR [SI.BPFTCNT-2],0 ; FAT file system drive ;AN000;
271 JNZ yesfat ; yes ;AN000;
272 MOV BYTE PTR ES:[DI.dpb_FAT_count-4],0
273 JMP setend ; NO ;AN000;
274yesfat:
275 MOV DX,AX
276 LODSB
277 DEC AL
278 STOSB ; dpb_cluster_mask
279 INC AL
280 XOR AH,AH
281LOG2LOOP:
282 TEST AL,1
283 JNZ SAVLOG
284 INC AH
285 SHR AL,1
286 JMP SHORT LOG2LOOP
287SAVLOG:
288 MOV AL,AH
289 STOSB ; dpb_cluster_shift
290 MOV BL,AL
291 MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
292 LODSB
293 STOSB ; dpb_FAT_count Number of FATs
294; OR AL,AL ; NONFAT ? ;AN000;
295; JZ setend ; yes, don't do anything ;AN000;
296 MOV BH,AL
297 LODSW
298 STOSW ; dpb_root_entries Number of directory entries
299 MOV CL,5
300 SHR DX,CL ; Directory entries per sector
301 DEC AX
302 ADD AX,DX ; Cause Round Up
303 MOV CX,DX
304 XOR DX,DX
305 DIV CX
306 MOV CX,AX ; Number of directory sectors
307 INC DI
308 INC DI ; Skip dpb_first_sector
309 MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
310 LODSB
311 MOV ES:[BP.dpb_media],AL ; Media byte
312 LODSW ; Number of sectors in a FAT
313 STOSW ;AC000;;>32mb dpb_FAT_size
314 MOV DL,BH ;AN000;;>32mb
315 XOR DH,DH ;AN000;;>32mb
316 MUL DX ;AC000;;>32mb Space occupied by all FATs
317 ADD AX,ES:[BP.dpb_first_FAT]
318 STOSW ; dpb_dir_sector
319 ADD AX,CX ; Add number of directory sectors
320 MOV ES:[BP.dpb_first_sector],AX
321
322 MOV CL,BL ;F.C. >32mb ;AN000;
323 CMP WORD PTR ES:[BP.DSKSIZ],0 ;F.C. >32mb ;AN000;
324 JNZ normal_dpb ;F.C. >32mb ;AN000;
325 XOR CH,CH ;F.C. >32mb ;AN000;
326 MOV BX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack] ;AN000;
327 MOV DX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack+2] ;AN000;
328 SUB BX,AX ;AN000;;F.C. >32mb
329 SBB DX,0 ;AN000;;F.C. >32mb
330 OR CX,CX ;AN000;;F.C. >32mb
331 JZ norot ;AN000;;F.C. >32mb
332rott: ;AN000;;F.C. >32mb
333 CLC ;AN000;;F.C. >32mb
334 RCR DX,1 ;AN000;;F.C. >32mb
335 RCR BX,1 ;AN000;;F.C. >32mb
336 LOOP rott ;AN000;;F.C. >32mb
337norot: ;AN000;
338 MOV AX,BX ;AN000;;F.C. >32mb
339 JMP setend ;AN000;;F.C. >32mb
340normal_dpb:
341 SUB AX,ES:[BP.DSKSIZ]
342 NEG AX ; Sectors in data area
343;; MOV CL,BL ; dpb_cluster_shift
344 SHR AX,CL ; Div by sectors/cluster
345setend:
346 INC AX
347 MOV ES:[BP.dpb_max_cluster],AX
348 MOV ES:[BP.dpb_next_free],0 ; Init so first ALLOC starts at
349 ; begining of FAT
350 MOV ES:[BP.dpb_free_cnt],-1 ; current count is invalid.
351 return
352EndProc $SETDPB
353; ;
354; C A V E A T P R O G R A M M E R ;
355;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
356
357BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block>
358;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
359; C A V E A T P R O G R A M M E R ;
360; ;
361;
362; Inputs: DX is new segment address of process
363; SI is end of new allocation block
364;
365 procedure $Dup_PDB,NEAR
366ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
367 MOV CreatePDB,0FFH ; indicate a new process
368 MOV DS,CurrentPDB
369 PUSH SI
370 JMP SHORT CreateCopy
371EndProc $Dup_PDB
372
373 procedure $CREATE_PROCESS_DATA_BLOCK,NEAR
374ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
375
376; Inputs:
377; DX = Segment number of new base
378; Function:
379; Set up program base and copy term and ^C from int area
380; Returns:
381; None
382; Called at DOS init
383
384 CALL get_user_stack
385 MOV DS,[SI.user_CS]
386 PUSH DS:[PDB_Block_len]
387CreateCopy:
388 MOV ES,DX
389 XOR SI,SI ; copy all 80h bytes
390 MOV DI,SI
391 MOV CX,80H
392 REP MOVSW
393; DOS 3.3 7/9/86
394
395 MOV CX,FilPerProc ; copy handles in case of
396 MOV DI,PDB_JFN_Table ; Set Handle Count has been issued
397 PUSH DS
398 LDS SI,DS:[PDB_JFN_Pointer]
399 REP MOVSB
400 POP DS
401
402; DOS 3.3 7/9/86
403 TEST CreatePDB,0FFh ; Shall we create a process?
404 JZ Create_PDB_cont ; nope, old style call
405;
406; Here we set up for a new process...
407;
408
409 PUSH CS ; Called at DOSINIT time, NO SS
410 POP DS
411 DOSAssume CS,<DS>,"MISC/Create_Copy"
412 XOR BX,BX ; dup all jfns
413 MOV CX,FilPerProc ; only 20 of them
414
415Create_dup_jfn:
416 PUSH ES ; save new PDB
417 invoke SFFromHandle ; get sf pointer
418 MOV AL,-1 ; unassigned JFN
419 JC CreateStash ; file was not really open
420 TEST ES:[DI].sf_flags,sf_no_inherit
421 JNZ CreateStash ; if no-inherit bit is set, skip dup.
422;
423; We do not inherit network file handles.
424;
425 MOV AH,BYTE PTR ES:[DI].sf_mode
426 AND AH,sharing_mask
427 CMP AH,sharing_net_fcb
428 jz CreateStash
429;
430; The handle we have found is duplicatable (and inheritable). Perform
431; duplication operation.
432;
433 MOV WORD PTR [THISSFT],DI
434 MOV WORD PTR [THISSFT+2],ES
435 invoke DOS_DUP ; signal duplication
436;
437; get the old sfn for copy
438;
439 invoke pJFNFromHandle ; ES:DI is jfn
440 MOV AL,ES:[DI] ; get sfn
441;
442; Take AL (old sfn or -1) and stash it into the new position
443;
444CreateStash:
445 POP ES
446 MOV ES:[BX].PDB_JFN_Table,AL; copy into new place!
447 INC BX ; next jfn...
448 LOOP create_dup_jfn
449
450 MOV BX,CurrentPDB ; get current process
451 MOV ES:[PDB_Parent_PID],BX ; stash in child
452 MOV [CurrentPDB],ES
453 ASSUME DS:NOTHING
454 MOV DS,BX
455;
456; end of new process create
457;
458Create_PDB_cont:
459 MOV BYTE PTR [CreatePDB],0h ; reset flag
460 POP AX
461
462 entry SETMEM
463ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
464
465; Inputs:
466; AX = Size of memory in paragraphs
467; DX = Segment
468; Function:
469; Completely prepares a program base at the
470; specified segment.
471; Called at DOS init
472; Outputs:
473; DS = DX
474; ES = DX
475; [0] has INT int_abort
476; [2] = First unavailable segment
477; [5] to [9] form a long call to the entry point
478; [10] to [13] have exit address (from int_terminate)
479; [14] to [17] have ctrl-C exit address (from int_ctrl_c)
480; [18] to [21] have fatal error address (from int_fatal_abort)
481; DX,BP unchanged. All other registers destroyed.
482
483 XOR CX,CX
484 MOV DS,CX
485 MOV ES,DX
486 MOV SI,addr_int_terminate
487 MOV DI,SAVEXIT
488 MOV CX,6
489 REP MOVSW
490 MOV ES:[2],AX
491 SUB AX,DX
492 CMP AX,MAXDIF
493 JBE HAVDIF
494 MOV AX,MAXDIF
495HAVDIF:
496 SUB AX,10H ; Allow for 100h byte "stack"
497 MOV BX,ENTRYPOINTSEG ; in .COM files
498 SUB BX,AX
499 MOV CL,4
500 SHL AX,CL
501 MOV DS,DX
502 MOV WORD PTR DS:[PDB_CPM_Call+1],AX
503 MOV WORD PTR DS:[PDB_CPM_Call+3],BX
504 MOV DS:[PDB_Exit_Call],(int_abort SHL 8) + mi_INT
505 MOV BYTE PTR DS:[PDB_CPM_Call],mi_Long_CALL
506 MOV WORD PTR DS:[PDB_Call_System],(int_command SHL 8) + mi_INT
507 MOV BYTE PTR DS:[PDB_Call_System+2],mi_Long_RET
508 MOV WORD PTR DS:[PDB_JFN_Pointer],PDB_JFN_Table
509 MOV WORD PTR DS:[PDB_JFN_Pointer+2],DS
510 MOV WORD PTR DS:[PDB_JFN_Length],FilPerProc
511;
512; The server runs several PDB's without creating them VIA EXEC. We need to
513; enumerate all PDB's at CPS time in order to find all references to a
514; particular SFT. We perform this by requiring that the server link together
515; for us all sub-PDB's that he creates. The requirement for us, now, is to
516; initialize this pointer.
517;
518 MOV word ptr DS:[PDB_Next_PDB],-1
519 MOV word ptr DS:[PDB_Next_PDB+2],-1
520 return
521
522EndProc $CREATE_PROCESS_DATA_BLOCK
523
524; ;
525; C A V E A T P R O G R A M M E R ;
526;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
527 procedure FETCHI_CHECK,NEAR
528ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
529 PUSHF
530 CMP CS:[FETCHI_TAG],22642
531 JZ TAG_OK
532 invoke DOSINIT ; go to hell
533TAG_OK:
534 POPF
535 return
536EndProc FETCHI_CHECK
537
538BREAK <$GSetMediaID -- get set media ID>
539; Inputs:
540; BL= drive number as defined in IOCTL
541; AL= 0 get media ID
542; 1 set media ID
543; DS:DX= buffer containing information
544; DW 0 info level (set on input)
545; DD ? serial #
546; DB 11 dup(?) volume id
547; DB 8 dup(?) file system type
548; Function:
549; Get or set media ID
550; Returns:
551; carry clear, DS:DX is filled
552; carry set, error
553
554 procedure $GSetMediaID,NEAR ;AN000;
555ASSUME DS:NOTHING,ES:NOTHING ;AN000;
556
557 MOV CX,0866H ;AN000;MS.; assume get for IOCTL
558 CMP AL,0 ;AN001;MS.; get ?
559 JZ doioctl ;AN000;MS.; yes
560 CMP AL,1 ;AN000;MS.; set ?
561 JNZ errorfunc ;AN000;MS.; no
562 MOV CX,0846H ;AN001;MS.;
563doioctl: ;AN000;
564 MOV AL,0DH ;AN000;MS.; generic IOCTL
565 invoke $IOCTL ;AN000;MS.; let IOCTL take care of it
566 return ;AN000;MS.;
567errorfunc: ;AN000;
568 error error_invalid_function;AN000;MS. ; invalid function
569EndProc $GSetMediaID ;AN000;
570
571CODE ENDS
572END
diff --git a/v4.0/src/DOS/MISC2.ASM b/v4.0/src/DOS/MISC2.ASM
new file mode 100644
index 0000000..c8860bb
--- /dev/null
+++ b/v4.0/src/DOS/MISC2.ASM
@@ -0,0 +1,594 @@
1; SCCSID = @(#)misc2.asm 1.1 85/04/10
2TITLE MISC2 - Miscellanious routines for MS-DOS
3NAME MISC2
4;
5; Miscellaneous useful routines
6;
7; StrCpy
8; StrCmp
9; Ucase
10; StrLen
11; DStrLen
12; Idle
13; TableDispatch
14; FastInit ; DOS 4.0
15; FastRet ; DOS 4.0
16; NLS_OPEN ; DOS 4.0
17; NLS_LSEEK ; DOS 4.0
18; Fake_User_Stack ; DOS 4.0
19; GetDevList ; DOS 4.0
20; NLS_IOCTL ; DOS 4.0
21; NLS_GETEXT ; DOS 4.0
22; MSG_RETRIEVAL ; DOS 4.0
23; Fake_Version ; DOS 4.0
24;
25; Revision history:
26;
27; Created: ARR 30 March 1983
28;
29; A000 version 4.0 Jan. 1988
30; A001 DCR 486 - Share installation for >32mb drives
31; A006 DCR 503 - fake version number for IBMCACHE
32
33.xlist
34;
35; get the appropriate segment definitions
36;
37include dosseg.asm
38
39CODE SEGMENT BYTE PUBLIC 'CODE'
40 ASSUME SS:DOSGROUP,CS:DOSGROUP
41
42.xcref
43include dossym.inc
44include fastseek.inc ;AN000;
45include fastxxxx.inc ;AN000;
46.cref
47.list
48
49 i_need THISCDS,DWORD
50 I_Need RetryLoop,WORD
51 I_need fSharing,BYTE ; TRUE => server-issued call
52 I_need FastTable,BYTE ;AN000;
53 I_need FastFlg,BYTE ;AN000;
54 I_need User_SP_2F,WORD ;AN000;
55 I_need User_SP,WORD ;AN000;
56 I_need User_SS,WORD ;AN000;
57 I_need SysInitTable,BYTE ;AN000;
58 I_need EXTERR,WORD ;AN000;
59 I_need MSG_EXTERROR,DWORD ;AN000;
60 I_need fshare,byte ;AN001;
61 I_need Special_version,WORD ;AN006;
62if debug
63 I_need BugLev,WORD
64 I_need BugTyp,WORD
65include bugtyp.asm
66endif
67
68Break <STRCMP - compare two ASCIZ strings DS:SI to ES:DI>
69
70;
71; Strcmp - compare ASCIZ DS:SI to ES:DI. Case INSENSITIVE. '/' = '\'
72; Strings of different lengths don't match.
73; Inputs: DS:SI - pointer to source string ES:DI - pointer to dest string
74; Outputs: Z if strings same, NZ if different
75; Registers modified: NONE
76
77Procedure StrCmp,NEAR
78 ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING
79 SaveReg <SI,DI,AX>
80Cmplp:
81 LODSB
82 IF DBCS ;AN000;
83 invoke testkanj ;AN000;; 2/13/KK
84 jz notkanj1 ;AN000;; 2/13/KK
85 dec si ;AN000;; Do source again 2/13/KK
86 cmpsb ;AN000;; First byte 2/13/KK
87 JNZ PopRet ;AN000;; Strings dif 2/13/KK
88 cmpsb ;AN000;; Second byte of kanji char 2/13/KK
89 JNZ PopRet ;AN000;; Strings dif 2/13/KK
90 mov al,byte ptr [SI-1] ;AN000;; Need last byte in AL 2/13/KK
91 jmp short Tend ;AN000;
92notkanj1: ;AN000;; 2/13/KK
93 ENDIF ;AN000;
94 CALL uCase ; convert to upper case
95 Invoke PathChrCmp ; convert / to \
96 MOV AH,AL
97 MOV AL,ES:[DI]
98 INC DI
99 CALL uCase ; convert to upper case
100 Invoke PathChrCmp ; convert / to \
101 CMP AH,AL
102 JNZ PopRet ; Strings dif
103Tend:
104 OR AL,AL
105 JNZ Cmplp ; More string
106PopRet:
107 RestoreReg <AX,DI,SI>
108 return
109EndProc StrCmp
110
111Break <STRCPY - copy ASCIZ string from DS:SI to ES:DI>
112
113;
114; Strcpy - copy an ASCIZ string from DS:SI to ES:DI and make uppercase
115; FStrcpy - copy an ASCIZ string from DS:SI to ES:DI. no modification of
116; characters.
117;
118; Inputs: DS:SI - pointer to source string
119; ES:DI - pointer to destination string
120; Outputs: ES:DI point byte after nul byte at end of dest string
121; DS:SI point byte after nul byte at end of source string
122; Registers modified: SI,DI
123
124Procedure StrCpy,NEAR
125 ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING
126 SaveReg <AX>
127CPYLoop:
128 LODSB
129 IF DBCS ;AN000;
130 invoke testkanj ;AN000;; 2/13/KK
131 jz notkanj2 ;AN000;; 2/13/KK
132 STOSB ;AN000;; 2/13/KK
133 LODSB ;AN000;; 2/13/KK
134 STOSB ;AN000;; 2/13/KK
135 jmp short CPYLoop ;AN000;; 3/31/KK
136
137notkanj2: ;AN000;; 2/13/KK
138 ENDIF ;AN000;
139 CALL uCase ; convert to upper case
140 Invoke PathChrCmp ; convert / to \
141 STOSB
142Tend2:
143 OR AL,AL
144 JNZ CPYLoop
145 RestoreReg <AX>
146 return
147EndProc StrCpy
148
149Procedure FStrCpy,NEAR
150 ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING
151 SaveReg <AX>
152FCPYLoop:
153 LODSB
154 STOSB
155 OR AL,AL
156 JNZ FCPYLoop
157 RestoreReg <AX>
158 return
159EndProc FStrCpy
160
161;
162; Upper case the letter in AL. Most chars are non lowercase.
163;
164Procedure uCase,NEAR
165; CMP AL,'a'
166; JAE Maybe
167; return
168;Maybe:
169; CMP AL,'z'
170; JA CaseRet
171; ADD AL,'A'-'a'
172;CaseRet:
173;;; 10/31/86 let's do file upper case for all DOS file names
174 invoke GetLet2
175;;; 10/31/86 let's do file upper case for all DOS file names
176 return
177EndProc uCase
178
179Break <StrLen - compute length of string ES:DI>
180
181;
182; StrLen - Compute length of string ES:DI
183; Inputs: ES:DI - pointer to string
184; Outputs: CX is size of string INCLUDING the NUL
185; Registers modified: CX
186
187Procedure StrLen,NEAR
188 ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING
189 PUSH DI
190 PUSH AX
191 MOV CX,-1
192 XOR AL,AL
193 REPNE SCASB
194 NOT CX
195 POP AX
196 POP DI
197 return
198EndProc StrLen
199
200;
201; DStrLen - Compute length of string DS:SI
202; Inputs: DS:SI - pointer to string
203; Outputs: CX is size of string INCLUDING the NUL
204; Registers modified: CX
205Procedure DStrLen,NEAR
206 CALL XCHGP
207 CALL StrLen
208 CALL XCHGP
209 return
210EndProc DStrLen
211
212Break <XCHGP - exchange source and destination pointers>
213
214Procedure XCHGP,NEAR
215 SaveReg <DS,ES>
216 RestoreReg <DS,ES>
217 XCHG SI,DI
218 return
219EndProc XCHGP
220
221Break <Idle - wait for a specified amount of time>
222
223;
224; Idle - when retrying an operation due to a lock/sharing violation, we spin
225; until RetryLoop is exhausted.
226;
227; Inputs: RetryLoop is the number of times we spin
228; Outputs: Wait
229; Registers modified: none
230
231Procedure Idle,NEAR
232 ASSUME CS:DOSGroup,SS:DOSGROUP,DS:NOTHING,ES:NOTHING
233 TEST fSharing,-1
234 retnz
235 SaveReg <CX>
236 MOV CX,RetryLoop
237 JCXZ Idle3
238Idle1: PUSH CX
239 XOR CX,CX
240Idle2: LOOP Idle2
241 POP CX
242 LOOP Idle1
243Idle3: RestoreReg <CX>
244 return
245EndProc Idle
246
247Break <TableDispatch - dispatch to a table>
248
249;
250; TableDispatch - given a table and an index, jmp to the approptiate
251; routine. Preserve all input registers to the routine.
252;
253; Inputs: Push return address
254; Push Table address
255; Push index (byte)
256; Outputs: appropriate routine gets jumped to.
257; return indicates invalid index
258; Registers modified: none.
259
260TableFrame STRUC
261OldBP DW ?
262OldRet DW ?
263Index DB ?
264Pad DB ?
265Tab DW ?
266NewRet DW ?
267TableFrame ENDS
268
269procedure TableDispatch,NEAR
270 ASSUME CS:DOSGroup,DS:NOTHING,SS:NOTHING,SS:NOTHING
271 PUSH BP
272 MOV BP,SP
273 PUSH BX ; save BX
274 MOV BX,[BP.Tab] ; get pointer to table
275 MOV BL,CS:[BX] ; maximum index
276 CMP [BP.Index],BL ; table error?
277 JAE TableError ; yes
278 MOV BL,[BP.Index] ; get desired table index
279 XOR BH,BH ; convert to word
280 SHL BX,1 ; convert to word pointer
281 INC BX ; point past first length byte
282 ADD BX,[BP.Tab] ; get real offset
283 MOV BX,CS:[BX] ; get contents of table entry
284 MOV [BP.Tab],BX ; put table entry into return address
285 POP BX ; restore BX
286 POP BP ; restore BP
287 ADD SP,4 ; clean off Index and our return addr
288 return ; do operation
289TableError:
290 POP BX ; restore BX
291 POP BP ; restore BP
292 RET 6 ; clean off Index, Table and RetAddr
293EndProc TableDispatch
294
295Break <TestNet - determine if a CDS is for the network>
296
297;
298; TestNet - examine CDS pointed to by ThisCDS and see if it indicates a
299; network CDS. This will handle NULL cds also.
300;
301; Inputs: ThisCDS points to CDS or NULL
302; Outputs: ES:DI = ThisCDS
303; carry Set => network
304; carry Clear => local
305; Registers modified: none.
306
307Procedure TestNet,NEAR
308 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
309 LES DI,ThisCDS
310 CMP DI,-1
311 JZ CMCRet ; UNC? carry is clear
312 TEST ES:[DI].curdir_flags,curdir_isnet
313 JNZ CMCret ; jump has carry clear
314 return ; carry is clear
315CMCRet: CMC
316 return
317
318EndProc TestNet
319
320Break <IsSFTNet - see if an sft is for the network>
321
322;
323; IsSFTNet - examine SF pointed to by ES:DI and see if it indicates a
324; network file.
325;
326; Inputs: ES:DI point to SFT
327; Outputs: Zero set if not network sft
328; zero reset otherwise
329; Carry CLEAR!!!
330; Registers modified: none.
331
332Procedure IsSFTNet,NEAR
333 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
334 TEST ES:[DI].sf_flags,sf_isnet
335 return
336EndProc IsSFTNet
337
338Break <FastInit - Initialize FastTable entries >
339
340; DOS 4.00 2/9/87
341; FastInit - initialize the FASTXXX routine entry
342; in the FastTable
343;
344; Inputs: BX = FASTXXX ID ( 1=fastopen, 2=fastseek,,,,)
345; DS:SI = address of FASTXXX routine entry
346; SI = -1 for query only
347; Outputs: Carry flag clear, if success
348; Carry flag set, if failure
349;
350;
351
352Procedure FastInit,NEAR ;AN000;
353 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000;
354
355 MOV DI,OFFSET DOSGROUP:FastTable + 2 ;AN000;FO. points to fastxxx entry
356 DEC BX ;AN000;FO.;; decrement index
357 MOV DX,BX ;AN000;FO.;; save bx
358 SHL BX,1 ;AN000;FO.;; times 4 , each entry is DWORD
359 SHL BX,1 ;AN000;FO.
360 ADD DI,BX ;AN000;FO. index to the entry
361 MOV AX,WORD PTR CS:[DI+2] ;AN000;FO. get entry segment
362fcheck: ;AN000;
363 MOV CX,CS ;AN000;FO.;; get DOS segment
364 CMP AX,CX ;AN000;FO.;; first time installed ?
365 JZ ok_install ;AN000;FO.;; yes
366 OR AX,AX ;AN000;FO.;
367 JZ ok_install ;AN000;FO.;
368 STC ;AN000;FO.;; already installed !
369 JMP SHORT FSret ;AN000;FO. set carry
370ok_install: ;AN000;
371 CMP SI,-1 ;AN000;FO.; Query only ?
372 JZ FSret ;AN000;FO.; yes
373 MOV CX,DS ;AN000;FO.; get FASTXXX entry segment
374 MOV CX,DS ;AN000;FO.;; get FASTXXX entry segment
375 MOV WORD PTR CS:[DI+2],CX ;AN000;FO.;; initialize routine entry
376 MOV WORD PTR CS:[DI],SI ;AN000;FO.;; initialize routine offset
377 MOV DI,OFFSET DOSGROUP:FastFlg ;AN000;FO.; get addr of FASTXXX flags
378 ADD DI,DX ;AN000;FO.; index to a FASTXXX flag
379 OR byte ptr CS:[DI],Fast_yes ;AN000;FO.; indicate installed
380
381FSret: ;AN000;
382 return ;AN000;FO.
383EndProc FastInit ;AN000;FO.
384
385Break <FastRet - initial routine in FastOpenTable >
386
387; DOS 3.3 6/10/86
388; FastRet - indicate FASTXXXX not in memory
389;
390; Inputs: None
391; Outputs: AX = -1 and carry flag set
392;
393; Registers modified: none.
394
395Procedure FastRet,FAR
396 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
397 MOV AX,-1
398 STC
399 RET
400EndProc FastRet
401
402Break <NLS_OPEN - do $open for NLSFUNC >
403
404; DOS 3.3 6/10/86
405; NLS_OPEN - call $OPEN for NLSFUNC
406;
407; Inputs: Same input as $OPEN except CL = mode
408; Outputs: same output as $OPEN
409;
410
411Procedure NLS_OPEN,NEAR
412 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
413
414; MOV BL,[CPSWFLAG] ; disable code page matching logic
415; MOV [CPSWFLAG],0
416; PUSH BX ; save current state
417
418 MOV AL,CL ; set up correct interface for $OPEN
419 invoke $OPEN
420
421 ; POP BX ; restore current state
422 ; MOV [CPSWFLAG],BL
423 RET
424EndProc NLS_OPEN
425
426Break <NLS_LSEEK - do $LSEEK for NLSFUNC >
427
428; DOS 3.3 6/10/86
429; NLS_LSEEK - call $LSEEK for NLSFUNC
430;
431; Inputs: BP = open mode
432; Outputs: same output as $LSEEK
433;
434
435Procedure NLS_LSEEK,NEAR
436 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
437
438 PUSH [user_SP] ; save user stack
439 PUSH [user_SS]
440 CALL Fake_User_Stack
441 MOV AX,BP ; set up correct interface for $LSEEK
442 invoke $LSEEK
443 POP [user_SS] ; restore user stack
444 POP [user_SP]
445 RET
446EndProc NLS_LSEEK
447
448
449Break <Fake_User_Stack - save uesr stack >
450
451
452; DOS 3.3 6/10/86
453; Fake_User_Stack - save user stack pointer
454;
455
456Procedure Fake_User_Stack,NEAR
457 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
458
459 MOV AX,[User_SP_2F] ; replace with INT 2F stack
460 MOV [user_SP],AX
461
462 MOV AX,CS
463 MOV [user_SS],AX ; DOSGROUP
464
465 RET
466EndProc Fake_User_Stack
467
468;
469Break <GetDevList - get device header list pointer>
470
471
472; DOS 3.3 7/25/86
473; GetDevList - get device header list pointer
474;
475; Output: AX:BX points to the device header list
476
477Procedure GetDevList,NEAR
478 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
479
480 MOV SI,OFFSET DOSGROUP:SysInitTable
481 LDS SI,CS:[SI.SYSI_InitVars]
482
483 MOV AX,WORD PTR DS:[SI.SYSI_DEV]
484 MOV BX,WORD PTR DS:[SI.SYSI_DEV+2]
485
486 RET
487EndProc GetDevList
488
489Break <NLS_IOCTL - do $IOCTL for NLSFUNC >
490
491; DOS 3.3 7/25/86
492; NLS_IOCTL - call $IOCTL for NLSFUNC
493;
494; Inputs: BP = function code 0CH
495; Outputs: same output as generic $IOCTL
496;
497
498Procedure NLS_IOCTL,NEAR
499 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
500
501 PUSH [user_SP] ; save user stack
502 PUSH [user_SS]
503 CALL Fake_User_Stack
504 MOV AX,BP ; set up correct interface for $LSEEK
505 invoke $IOCTL
506 POP [user_SS] ; restore user stack
507 POP [user_SP]
508 RET
509EndProc NLS_IOCTL
510
511Break <NLS_GETEXT- get extended error for NLSFUNC>
512
513; DOS 3.3 7/25/86
514; NLS_GETEXT -
515;
516; Inputs: none
517; Outputs: AX = extended error
518;
519
520Procedure NLS_GETEXT,NEAR
521 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
522
523 MOV AX,CS:[EXTERR] ; return extended error
524 RET
525EndProc NLS_GETEXT
526
527Break <MSG_RETRIEVAL- get beginning addr of system and parser messages>
528
529; DOS 4.00
530;
531; Inputs: DL=0 get extended error message addr
532; =1 set extended error message addr
533; =2 get parser error message addr
534; =3 set parser error message addr
535; =4 get critical error message addr
536; =5 set critical error message addr
537; =6 get file system error message addr
538; =7 set file system error message addr
539; =8 get address for code reduction
540; =9 set address for code reduction
541; Function: get/set message address
542; Outputs: ES:DI points to addr when get
543;
544
545Procedure MSG_RETRIEVAL,NEAR ;AN000;
546 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000;
547
548 PUSH AX ;AN000;;MS. save regs
549 PUSH SI ;AN000;;MS. save regs
550 MOV AX,DX ;AN000;;MS.
551 MOV SI,OFFSET DOSGROUP:MSG_EXTERROR ;AN000;;MS.
552 TEST AL,1 ;AN000;;MS. get ?
553 JZ toget ;AN000;;MS. yes
554 DEC AL ;AN000;;MS.
555toget: ;AN000;
556 SHL AL,1 ;AN000;;MS. times 2
557 XOR AH,AH ;AN000;;MS.
558 ADD SI,AX ;AN000;;MS. position to the entry
559 TEST DL,1 ;AN000;;MS. get ?
560 JZ getget ;AN000;;MS. yes
561 MOV WORD PTR CS:[SI],DI ;AN000;;MS. set MSG
562 MOV WORD PTR CS:[SI+2],ES ;AN000;;MS. address to ES:DI
563 JMP SHORT MSGret ;AN000;;MS. exit
564getget: ;AN000;
565 LES DI,DWORD PTR CS:[SI] ;AN000;;MS. get msg addr
566MSGret: ;AN000;
567 POP SI ;AN000;;MS.
568 POP AX ;AN000;;MS.
569 return ;AN000;;MS. exit
570
571EndProc MSG_RETRIEVAL ;AN000;
572
573
574Break <Fake_version - set/reset version flag>
575
576;
577; Inputs: DL=0 current version number
578; <>0 special version number
579; Function: set special version number
580; Outputs: version number is changed
581;
582
583Procedure Fake_version,NEAR ;AN000;
584 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000;
585
586 MOV [Special_version],DX ;AN006;MS.
587 return ;AN006;;MS. exit
588
589EndProc Fake_version ;AN006;;MS.
590
591
592
593CODE ENDS
594 END
diff --git a/v4.0/src/DOS/MKNODE.ASM b/v4.0/src/DOS/MKNODE.ASM
new file mode 100644
index 0000000..968c8eb
--- /dev/null
+++ b/v4.0/src/DOS/MKNODE.ASM
@@ -0,0 +1,890 @@
1; SCCSID = @(#)mknode.asm 1.5 85/08/29
2TITLE MKNODE - Node maker
3NAME MKNODE
4; Low level routines for making a new local file system node
5; and filling in an SFT from a directory entry
6;
7; BUILDDIR
8; SETDOTENT
9; MakeNode
10; NEWENTRY
11; FREEENT
12; NEWDIR
13; DOOPEN
14; RENAME_MAKE
15; CHECK_VIRT_OPEN
16;
17; Revision history:
18;
19; AN000 version 4.0 Jan. 1988
20; A004 PTM 3680 --- Make SFT NAME field offset same as 3.30
21
22;
23; get the appropriate segment definitions
24;
25.xlist
26include dosseg.asm
27include fastopen.inc
28
29CODE SEGMENT BYTE PUBLIC 'CODE'
30 ASSUME SS:DOSGROUP,CS:DOSGROUP
31
32.xcref
33include dossym.inc
34include devsym.inc
35.cref
36.list
37
38 i_need EntFree,WORD
39 i_need DirStart,WORD
40 i_need LastEnt,WORD
41 i_need ClusNum,WORD
42 i_need CurBuf,DWORD
43 i_need Attrib,BYTE
44 i_need VolID,BYTE
45 i_need Name1,BYTE
46 i_need ThisDPB,DWORD
47 i_need EntLast,WORD
48 i_need Creating,BYTE
49 i_need SecClusPos,BYTE
50 i_need ClusFac,BYTE
51 i_need NxtClusNum,WORD
52 i_need DirSec,WORD
53 i_need NoSetDir,BYTE
54 i_need THISSFT,DWORD
55 i_need SATTRIB,BYTE
56 i_need ALLOWED,BYTE
57 i_need FAILERR,BYTE
58 i_need VIRTUAL_OPEN
59 I_need FastOpen_Ext_info,BYTE ; DOS 3.3
60 I_need FastOpenFlg,BYTE ; DOS 3.3
61 I_need CPSWFLAG,BYTE ;FT. DOS 3.4 ;AN000;
62 I_need EXTOPEN_ON,BYTE ;FT. DOS 3.4 ;AN000;
63 I_need EXTOPEN_FLAG,WORD ;FT. DOS 3.4 ;AN000;
64 I_need EXTOPEN_IO_MODE,WORD ;FT. DOS 3.4 ;AN000;
65 I_need HIGH_SECTOR,WORD ;>32mb ;AN000;
66 I_need ACT_PAGE,WORD ;>32mb ;AN000;
67
68Break <BUILDDIR,NEWDIR -- ALLOCATE DIRECTORIES>
69
70; Inputs:
71; ES:BP Points to DPB
72; [THISSFT] Set if using NEWDIR entry point
73; (used by ALLOCATE)
74; [LASTENT] current last valid entry number in directory if no free
75; entries
76; [DIRSTART] Points to first cluster of dir (0 means root)
77; Function:
78; Grow directory if no free entries and not root
79; Outputs:
80; CARRY SET IF FAILURE
81; ELSE
82; AX entry number of new entry
83; If a new dir [DIRSTART],[CLUSFAC],[CLUSNUM],[DIRSEC] set
84; AX = first entry of new dir
85; GETENT should be called to set [LASTENT]
86
87 procedure BUILDDIR,NEAR
88 DOSAssume CS,<DS>,"BuildDir"
89 ASSUME ES:NOTHING
90
91 MOV AX,[ENTFREE]
92 CMP AX,-1
93 JZ CHECK_IF_ROOT
94 CLC
95 return
96
97CHECK_IF_ROOT:
98 CMP [DIRSTART],0
99 JNZ NEWDIR
100 STC
101 return ; Can't grow root
102
103 entry NEWDIR
104 MOV BX,[DIRSTART]
105 OR BX,BX
106 JZ NULLDIR
107 invoke GETEOF
108 retc ; Screw up
109NULLDIR:
110 MOV CX,1
111 invoke ALLOCATE
112 retc
113 MOV DX,[DIRSTART]
114 OR DX,DX
115 JNZ ADDINGDIR
116 invoke SETDIRSRCH
117 retc
118 MOV [LASTENT],-1
119 JMP SHORT GOTDIRREC
120ADDINGDIR:
121 PUSH BX
122 MOV BX,[ClusNum]
123 Invoke IsEof
124 POP BX
125 JB NOTFIRSTGROW
126;;;; 10/17/86 update CLUSNUM in the fastopen cache
127 MOV [CLUSNUM],BX
128 PUSH CX
129 PUSH AX
130 PUSH BP
131 MOV AH,1 ; CLUSNUM update
132 MOV DL,ES:[BP.dpb_drive] ; drive #
133 MOV CX,[DIRSTART] ; first cluster #
134 MOV BP,BX ; CLUSNUM
135 invoke FastOpen_Update
136 POP BP
137 POP AX
138 POP CX
139
140;;;; 10/17/86 update CLUSNUM in the fastopen cache
141NOTFIRSTGROW:
142 MOV DX,BX
143 XOR BL,BL
144 invoke FIGREC
145GOTDIRREC:
146 MOV CL,ES:[BP.dpb_cluster_mask]
147 INC CL
148 XOR CH,CH
149ZERODIR:
150 PUSH CX
151 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
152 MOV AL,0FFH
153 invoke GETBUFFR
154 JNC GET_SSIZE
155 POP CX
156 return
157
158GET_SSIZE:
159 MOV CX,ES:[BP.dpb_sector_size]
160 PUSH ES
161 LES DI,[CURBUF]
162 OR ES:[DI.buf_flags],buf_isDIR
163 PUSH DI
164 ADD DI,BUFINSIZ
165 XOR AX,AX
166 SHR CX,1
167 REP STOSW
168 JNC EVENZ
169 STOSB
170EVENZ:
171 POP DI
172
173 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
174 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
175 invoke INC_DIRTY_COUNT ;LB. ;AN000;
176 OR ES:[DI.buf_flags],buf_dirty
177yesdirty:
178 POP ES
179 POP CX
180 INC DX
181 LOOP ZERODIR
182 MOV AX,[LASTENT]
183 INC AX
184 CLC
185 return
186
187EndProc BUILDDIR
188
189;
190; set up a . or .. directory entry for a directory.
191;
192; Inputs: ES:DI point to the beginning of a directory entry.
193; AX contains ". " or ".."
194; DX contains first cluster of entry
195;
196 procedure SETDOTENT,NEAR
197 DOSAssume CS,<DS>,"SetDotEnt"
198;
199; Fill in name field
200;
201 STOSW
202 MOV CX,4
203 MOV AX," "
204 REP STOSW
205 STOSB
206;
207; Set up attribute
208;
209 MOV AL,attr_directory
210 errnz dir_attr-(dir_name+11)
211 STOSB
212;
213; Initialize time and date of creation
214;
215 ADD DI,10
216 MOV SI,WORD PTR [THISSFT]
217 MOV AX,[SI.sf_time]
218 errnz dir_time-(dir_attr+1+10)
219 STOSW
220 MOV AX,[SI.sf_date]
221 errnz dir_date-(dir_time+2)
222 STOSW
223;
224; Set up first cluster field
225;
226 MOV AX,DX
227 errnz dir_first-(dir_date+2)
228 STOSW
229;
230; 0 file size
231;
232 XOR AX,AX
233 errnz dir_size_l-(dir_first+2)
234 STOSW
235 STOSW
236 errnz <(size dir_entry)-(dir_size_l+4)>
237 return
238EndProc SETDOTENT
239
240Break <MAKENODE -- CREATE A NEW NODE>
241
242; Inputs:
243; AL - attribute to create
244; AH = 0 if it is ok to truncate a file already by this name
245; AH = Non 0 if this is an error
246; (AH ignored on dirs and devices)
247; NOTE: When making a DIR or volume ID, AH need not be set since
248; a name already existant is ALWAYS an error in these cases.
249; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
250; terminated)
251; [CURR_DIR_END] Points to end of Current dir part of string
252; ( = -1 if current dir not involved, else
253; Points to first char after last "/" of current dir part)
254; [THISCDS] Points to CDS being used
255; [THISSFT] Points to an empty SFT. EXCEPT sf_mode filled in.
256; Function:
257; Make a new node
258; Outputs:
259; Sets EXTERR_LOCUS = errLOC_Disk or errLOC_Unk via GetPathNoset
260; CARRY SET IF ERROR
261; AX = 1 A node by this name exists and is a directory
262; AX = 2 A new node could not be created
263; AX = 3 A node by this name exists and is a disk file
264; (AH was NZ on input)
265; AX = 4 Bad Path
266; SI return from GetPath maintained
267; AX = 5 Attribute mismatch
268; AX = 6 Sharing Violation
269; (INT 24 generated ALWAYS since create is always compat mode
270; AX = 7 file not found for Extended Open (not exists and fails)
271; ELSE
272; AX = 0 Disk Node
273; AX = 3 Device Node (error in some cases)
274; [DIRSTART],[DIRSEC],[CLUSFAC],[CLUSNUM] set to directory
275; containing new node.
276; [CURBUF+2]:BX Points to entry
277; [CURBUF+2]:SI Points to entry.dir_first
278; [THISSFT] is filled in
279; sf_mode = unchanged.
280; Attribute byte in entry is input AL
281; DS preserved, others destroyed
282
283 procedure MakeNode,NEAR
284 DOSAssume CS,<DS>,"MakeNode"
285 ASSUME ES:NOTHING
286
287 MOV WORD PTR [CREATING],0E5FFH ; Creating, not DEL *.*
288 PUSH AX ; Save AH value
289 MOV [NoSetDir],0
290 MOV [SATTRIB],AL
291 invoke GetPathNoSet
292 MOV DL,CL ; Save CL info
293 MOV CX,AX ; Device ID to CH
294 POP AX ; Get back AH
295 JNC make_exists ; File existed
296 JNZ make_err_4 ; Path bad
297 CMP DL,80H ; Check "CL" return from GETPATH
298 JZ make_type ; Name simply not found, and no metas
299make_err_4:
300 MOV AL,4 ; case 1 bad path
301make_err_ret:
302 XOR AH,AH
303 STC
304 return
305
306 entry RENAME_MAKE ; Used by DOS_RENAME to "copy" a node
307
308make_type:
309;Extended Open hooks
310 TEST [EXTOPEN_ON],ext_open_on ;FT. from extended open ;AN000;
311 JZ make_type2 ;FT. no ;AN000;
312 OR [EXTOPEN_ON],ext_file_not_exists ;FT. set for extended open ;AN000;
313 TEST [EXTOPEN_FLAG],0F0H ;FT. not exists and fails ;AN000;
314 JNZ make_type2 ;FT. no ;AN000;
315 STC ;FT. set carry ;AN000;
316 MOV AX,7 ;FT. file not found ;AN000;
317 return ;FT. ;AN000;
318make_type2:
319;Extended Open hooks
320 LES DI,[THISSFT]
321; MOV ES:[DI.sf_mode],sharing_compat + open_for_both
322 XOR AX,AX ; nothing exists Disk Node
323 STC ; Not found
324 JMP make_new
325
326;
327; The node exists. It may be either a device, directory or file:
328; Zero set => directory
329; High bit of CH on => device
330; else => file
331make_exists:
332 JZ make_exists_dir
333 MOV AL,3 ; file exists type 3 (error or device node)
334 TEST BYTE PTR [ATTRIB],(attr_volume_id+attr_directory)
335 JNZ make_err_ret_5 ; Cannot already exist as Disk or Device Node
336 ; if making DIR or Volume ID
337 OR CH,CH
338 JS make_share ; No further checks on attributes if device
339 OR AH,AH
340 JNZ make_err_ret ; truncating NOT OK (AL = 3)
341 PUSH CX ; Save device ID
342 MOV ES,WORD PTR [CURBUF+2]
343 MOV CH,ES:[BX+dir_attr] ; Get file attributes
344 TEST CH,attr_read_only
345 JNZ make_err_ret_5P ; Cannot create on read only files
346 invoke MatchAttributes
347 POP CX ; Devid back in CH
348 JNZ make_err_ret_5 ; Attributes not ok
349 XOR AL,AL ; AL = 0, Disk Node
350make_share:
351 XOR AH,AH
352 PUSH AX ; Save Disk or Device node
353 PUSH CX ; Save Device ID
354 MOV AH,CH ; Device ID to AH
355 CALL DOOPEN ; Fill in SFT for share check
356 LES DI,[THISSFT]
357; MOV ES:[DI.sf_mode],sharing_compat + open_for_both
358 SaveReg <SI,BX> ; Save CURBUF pointers
359 invoke ShareEnter
360 jnc MakeEndShare
361;
362; User failed request.
363;
364 RestoreReg <BX,SI,CX,AX>
365Make_Share_ret:
366 MOV AL,6
367 JMP make_err_ret
368
369make_err_ret_5P:
370 POP CX ; Get back device ID
371make_err_ret_5:
372 MOV AL,5 ; Attribute mismatch
373 JMP make_err_ret
374
375make_exists_dir:
376 MOV AL,1 ; exists as directory, always an error
377 JMP make_err_ret
378
379make_save:
380 PUSH AX ; Save whether Disk or File
381 MOV AX,CX ; Device ID to AH
382 CALL NewEntry
383 POP AX ; 0 if Disk, 3 if File
384 retnc
385 MOV AL,2 ; create failed case 2
386 return
387
388make_new:
389 call make_save
390 retc ; case 2 fail
391 TEST BYTE PTR [ATTRIB],attr_directory
392 retnz ; Don't "open" directories, so don't
393 ; tell the sharer about them
394 SaveReg <AX,BX,SI> ; Save AL code
395 invoke ShareEnter
396 RestoreReg <SI,BX,AX>
397 retnc
398;
399; We get here by having the user FAIL a share problem. Typically a failure of
400; this nature is an out-of-space or an internal error. We clean up as best as
401; possible: delete the newly created directory entry and return share_error.
402;
403 PUSH AX
404 LES DI,CurBuf
405 MOV BYTE PTR ES:[BX],0E5H ; nuke newly created entry.
406
407 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
408 JNZ yesdirty2 ;LB. don't increment dirty count ;AN000;
409 invoke INC_DIRTY_COUNT ;LB. ;AN000;
410 OR ES:[DI].buf_flags,buf_dirty ; flag buffer as dirty
411yesdirty2:
412 LES BP,ThisDPB
413 MOV AL,ES:[BP].DPB_Drive ; get drive for flush
414 Invoke FlushBuf ; write out buffer.
415 POP AX
416 jmp make_Share_ret
417;
418; We have found an existing file. We have also entered it into the share set.
419; At this point we need to call newentry to correctly address the problem of
420; getting rid of old data (create an existing file) or creating a new
421; directory entry (create a new file). Unfortunately, this operation may
422; result in an INT 24 that the user doesn't return from, thus locking the file
423; irretrievably into the share set. The correct solution is for us to LEAVE
424; the share set now, do the operation and then reassert the share access.
425;
426; We are allowed to do this! There is no window! After all, we are in
427; critDisk here and for someone else to get in, they must enter critDisk also.
428;
429MakeEndShare:
430 LES DI,ThisSFT ; grab SFT
431 XOR AX,AX
432 EnterCrit critSFT
433 XCHG AX,ES:[DI].sf_ref_count
434 SaveReg <AX,DI,ES>
435 PUSHF
436 invoke ShareEnd ; remove sharing
437 POPF
438 RestoreReg <ES,DI,ES:[DI].sf_ref_count>
439 LeaveCrit critSFT
440 RestoreReg <BX,SI,CX,AX>
441 CALL make_save
442;
443; If the user failed, we do not reenter into the sharing set.
444;
445 retc ; bye if error
446 SaveReg <AX,BX,SI>
447 PUSHF
448 invoke ShareEnter
449 POPF
450 RestoreReg <SI,BX,AX>
451;
452; If Share_check fails, then we have an internal ERROR!!!!!
453;
454 return
455EndProc MakeNode
456
457; Inputs:
458; [THISSFT] set
459; [THISDPB] set
460; [LASTENT] current last valid entry number in directory if no free
461; entries
462; [VOLID] set if a volume ID was found during search
463; [ATTRIB] Contains attributes for new file
464; [DIRSTART] Points to first cluster of dir (0 means root)
465; CARRY FLAG INDICATES STATUS OF SEARCH FOR FILE
466; NC means file existed (device)
467; C means file did not exist
468; AH = Device ID byte
469; If FILE
470; [CURBUF+2]:BX points to start of directory entry
471; [CURBUF+2]:SI points to dir_first of directory entry
472; If device
473; DS:BX points to start of "fake" directory entry
474; DS:SI points to dir_first of "fake" directory entry
475; (has DWORD pointer to device header)
476; Function:
477; Make a new directory entry
478; If an old one existed it is truncated first
479; Outputs:
480; Carry set if error
481; Can't grow dir, atts didn't match, attempt to make 2nd
482; vol ID, user FAILed to I 24
483; else
484; outputs of DOOPEN
485; DS, BX, SI preserved (meaning on SI BX, not value), others destroyed
486
487 procedure NEWENTRY,NEAR
488 DOSAssume CS,<DS>,"NewEntry"
489 ASSUME ES:NOTHING
490
491 LES BP,[THISDPB]
492ASSUME ES:NOTHING
493 JNC EXISTENT
494 CMP [FAILERR],0
495 STC
496 retnz ; User FAILed, node might exist
497 CALL BUILDDIR ; Try to build dir
498 retc ; Failed
499 invoke GETENT ; Point at that free entry
500 retc ; Failed
501 JMP SHORT FREESPOT
502
503ERRRET3:
504 STC
505 return
506
507EXISTENT:
508 DOSAssume CS,<DS>,"MKNODE/ExistEnt"
509 OR AH,AH ; Check if file is I/O device
510 JNS NOT_DEV1
511 JMP DOOPEN ; If so, proceed with open
512
513NOT_DEV1:
514 invoke FREEENT ; Free cluster chain
515 retc ; Failed
516FREESPOT:
517 TEST BYTE PTR [ATTRIB],attr_volume_id
518 JZ NOTVOLID
519 CMP BYTE PTR [VOLID],0
520 JNZ ERRRET3 ; Can't create a second volume ID
521NOTVOLID:
522 MOV ES,WORD PTR [CURBUF+2]
523 MOV DI,BX
524 MOV SI,OFFSET DOSGROUP:NAME1
525 MOV CX,5
526 REP MOVSW
527 MOVSB ; Move name into dir entry
528 MOV AL,[ATTRIB]
529 errnz dir_attr-(dir_name+11)
530 STOSB ; Attributes
531;; File Tagging for Create DOS 4.00
532 MOV CL,5 ;FT. assume normal ;AN000;
533; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000;
534; JZ NORMFT ;FT. no, make null code page ;AN000;
535; invoke Get_Global_CdPg ;FT. get global code page ;AN000;
536; STOSW ;FT. tag this file with global code page ;AN000;
537; DEC CL ;FT. only 4 ;AN000;
538;NORMFT: ;FT. ;AN000;
539
540;; File Tagging for Create DOS 4.00
541 XOR AX,AX
542 REP STOSW ; Zero pad
543 invoke DATE16
544 XCHG AX,DX
545 errnz dir_time-(dir_attr+1+2*5)
546 STOSW ; dir_time
547 XCHG AX,DX
548 errnz dir_date-(dir_time+2)
549 STOSW ; dir_date
550 XOR AX,AX
551 PUSH DI ; Correct SI input value (recomputed for new buffer)
552
553 errnz dir_first-(dir_date+2)
554 STOSW ; Zero dir_first and size
555 errnz dir_size_l-(dir_first+2)
556 STOSW
557 STOSW
558updnxt:
559 errnz <(size dir_entry)-(dir_size_l+4)>
560 MOV SI,WORD PTR [CURBUF]
561
562 TEST ES:[SI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
563 JNZ yesdirty3 ;LB. don't increment dirty count ;AN000;
564 invoke INC_DIRTY_COUNT ;LB. ;AN000;
565 OR ES:[SI.buf_flags],buf_dirty
566yesdirty3:
567 LES BP,[THISDPB]
568 MOV AL,ES:[BP.dpb_drive] ; Sets AH value again (in AL)
569 PUSH AX
570 PUSH BX
571; If we have a file, we need to increment the open ref. count so that
572; we have some protection against invalid media changes if an Int 24
573; error occurs.
574; Do nothing for a device.
575 SaveReg <ES,DI>
576 LES DI,[THISSFT]
577 test es:[di.sf_flags],devid_device
578 jnz GotADevice
579 SaveReg <DS,BX>
580 LDS BX,[THISDPB]
581 MOV word ptr ES:[DI.sf_devptr],BX
582 MOV BX,DS
583 MOV word ptr ES:[DI.sf_devptr+2],BX
584 RestoreReg <BX,DS> ; need to use DS for segment later on
585 invoke Dev_Open_SFT ; increment ref. count
586 mov [VIRTUAL_OPEN],1; set flag
587GotADevice:
588 RestoreReg <DI,ES>
589
590 PUSH [ACT_PAGE] ;LB. save EMS page for curbuf ;AN000;
591 invoke FLUSHBUF
592 POP BX ;LB. restore EMS page for curbuf ;AN000;
593 PUSHF ;LB. save flushbuf falg ;AN000;
594 CMP BX,-1 ;BL-NETWORK PTM #-?
595 JE Page_ok ;BL-NETWORK PTM #-?
596 invoke SET_MAP_PAGE ;LB. remap curbuf ;AN000;
597Page_ok: ;BL-NETWORK PTM #-?
598 POPF ;LB. restore flush flag ;AN000;
599 Call CHECK_VIRT_OPEN ; decrement ref. count ;AN000;
600 POP BX
601 POP AX
602 POP SI ; Get SI input back
603 MOV AH,AL ; Get I/O driver number back
604 retc ; Failed
605
606
607;NOTE FALL THROUGH
608
609; Inputs:
610; [THISDPB] points to DPB if file
611; [THISSFT] points to SFT being used
612; AH = Device ID byte
613; If FILE
614; [CURBUF+2]:BX points to start of directory entry
615; [CURBUF+2]:SI points to dir_first of directory entry
616; If device
617; DS:BX points to start of "fake" directory entry
618; DS:SI points to dir_first of "fake" directory entry
619; (has DWORD pointer to device header)
620; Function:
621; Fill in SFT from dir entry
622; Outputs:
623; CARRY CLEAR
624; sf_ref_count and sf_mode fields not altered
625; sf_flags high byte = 0
626; sf_flags low byte = AH except
627; sf_flags Bit 6 set (not dirty or not EOF)
628; sf_attr sf_date sf_time sf_name set from entry
629; sf_position = 0
630; If device
631; sf_devptr = dword at dir_first (pointer to device header)
632; sf_size = 0
633; If file
634; sf_firclus sf_size set from entry
635; sf_devptr = [THISDPB]
636; sf_cluspos = 0
637; sf_lstclus = sf_firclus
638; sf_dirsec sf_dirpos set
639; DS,SI,BX preserved, others destroyed
640
641 entry DOOPEN
642 DOSAssume CS,<DS>,"DoOpen"
643 ASSUME ES:NOTHING
644
645;
646; Generate and store attribute
647;
648 MOV DH,AH ; AH to different place
649 LES DI,[THISSFT]
650 ADD DI,sf_attr ; Skip ref_count and mode fields
651 XOR AL,AL ; Assume it's a device, devices have an
652 ; attribute of 0 (for R/O testing etc).
653 OR DH,DH ; See if our assumption good.
654 JS DEV_SFT1 ; If device DS=DOSGROUP
655 MOV DS,WORD PTR [CURBUF+2]
656ASSUME DS:NOTHING
657 MOV AL,[BX.dir_attr] ; If file, get attrib from dir entry
658DEV_SFT1:
659 STOSB ; sf_attr, ES:DI -> sf_flags
660;
661; Generate and store flags word
662;
663 XOR AX,AX
664 MOV AL,DH
665 OR AL,devid_file_clean
666 STOSW ; sf_flags, ES:DI -> sf_devptr
667;
668; Generate and store device pointer
669;
670 PUSH DS
671 LDS AX,DWORD PTR [BX.dir_first] ; Assume device
672 OR DH,DH
673 JS DEV_SFT2
674 LDS AX,[THISDPB] ; Was file
675DEV_SFT2:
676 STOSW ; store offset
677 MOV AX,DS
678 POP DS
679 STOSW ; store segment
680 ; ES:DI -> sf_firclus
681;
682; Generate pointer to, generate and store first cluster (irrelevant for
683; devices)
684;
685 PUSH SI ; Save pointer to dir_first
686 MOVSW ; dir_first -> sf_firclus
687 ; DS:SI -> dir_size_l, ES:DI -> sf_time
688;
689; Copy time/date of last modification
690;
691 SUB SI,dir_size_l - dir_time ; DS:SI->dir_time
692 MOVSW ; dir_time -> sf_time
693 ; DS:SI -> dir_date, ES:DI -> sf_date
694 MOVSW ; dir_date -> sf_date
695 ; DS:SI -> dir_first, ES:DI -> sf_size
696;
697; Generate and store file size (0 for devices)
698;
699 LODSW ; skip dir_first, DS:SI -> dir_size_l
700 LODSW ; dir_size_l in AX , DS:SI -> dir_size_h
701 MOV CX,AX ; dir_size_l in CX
702 LODSW ; dir_size_h (size AX:CX), DS:SI -> ????
703 OR DH,DH
704 JNS FILE_SFT1
705 XOR AX,AX
706 MOV CX,AX ; Devices are open ended
707FILE_SFT1:
708 XCHG AX,CX
709 STOSW ; Low word of sf_size
710 XCHG AX,CX
711 STOSW ; High word of sf_size
712 ; ES:DI -> sf_position
713;
714; Initialize position to 0
715;
716 XOR AX,AX
717 STOSW
718 STOSW ; sf_position
719 ; ES:DI -> sf_cluspos
720;
721; Generate cluster optimizations for files
722;
723 OR DH,DH
724 JS DEV_SFT3
725 STOSW ; sf_cluspos
726 MOV AX,[BX.dir_first]
727;;;; STOSW ; sf_lstclus
728 PUSH DI ;AN004; save dirsec offset
729 SUB DI,sf_dirsec ;AN004; es:di -> SFT
730 MOV ES:[DI.sf_lstclus],AX ;AN004; save it
731 POP DI ;AN004; restore dirsec offset
732
733
734
735; DOS 3.3 FastOpen 6/13/86
736
737 PUSH DS
738 context DS
739 TEST [FastOpenFlg],Special_Fill_Set
740 JZ Not_FastOpen
741 MOV SI,OFFSET DOSGROUP:FastOpen_Ext_Info
742 MOV AX,WORD PTR [SI.FEI_dirsec]
743 STOSW ; sf_dirsec
744 MOV AX,WORD PTR [SI.FEI_dirsec+2] ;;; changed for >32mb
745 STOSW ; sf_dirsec
746 MOV AL,[SI.FEI_dirpos]
747 STOSB ; sf_dirpos
748 POP DS
749 JMP Next_Name
750
751; DOS 3.3 FastOpen 6/13/86
752
753Not_FastOpen:
754 POP DS ; normal path
755ASSUME DS:NOTHING
756 MOV SI,WORD PTR [CURBUF] ; DS:SI->buffer header
757 MOV AX,WORD PTR [SI.buf_sector] ;F.C. >32mb ;AN000;
758 STOSW ; sf_dirsec ;F.C. >32mb ;AN000;
759 MOV AX,WORD PTR [SI.buf_sector+2] ;F.C. >32mb ;AN000;
760 STOSW ; sf_dirsec ;F.C. >32mb ;AN000;
761 MOV AX,BX
762 ADD SI,BUFINSIZ ; DS:SI-> start of data in buffer
763 SUB AX,SI ; AX = BX relative to start of sector
764 MOV CL,SIZE dir_entry
765 DIV CL
766 STOSB ; sf_dirpos
767
768Next_Name:
769 errnz sf_name-(sf_dirpos+1)
770 JMP SHORT FILE_SFT2
771
772DEV_SFT3:
773 ADD DI,sf_name - sf_cluspos
774FILE_SFT2:
775;
776; Copy in the object's name
777;
778 MOV SI,BX ; DS:SI points to dir_name
779 MOV CX,11
780 REP MOVSB ; sf_name
781 POP SI ; recover DS:SI -> dir_first
782;; File tagging , code page and XA cluster must be after name
783; MOV AX,[BX.dir_CODEPG] ;FT. set file's code page ;AN000;
784; STOSW ;FT. ;AN000;
785; MOV AX,[BX.dir_EXTCLUSTER] ;FT. set XA cluster ;AN000;
786; STOSW ;FT. ;AN000;
787; MOV AX,[EXTOPEN_IO_MODE] ;FT. extended open ;AN000;
788; STOSW ;FT. ;AN000;
789; MOV AL,[BX.dir_attr2] ;FT. high attribute ;AN000;
790; STOSB ;FT. ;AN000;
791
792;; File tagging , code page and XA cluster must be after name
793
794 context DS
795 CLC
796 return
797
798EndProc NEWENTRY
799
800; Inputs:
801; ES:BP -> DPB
802; [CURBUF] Set
803; [CURBUF+2]:BX points to directory entry
804; [CURBUF+2]:SI points to above dir_first
805; Function:
806; Free the cluster chain for the entry if present
807; Outputs:
808; Carry set if error (currently user FAILed to I 24)
809; (NOTE dir_firclus and dir_size_l/h are wrong)
810; DS BX SI ES BP preserved (BX,SI in meaning, not value) others destroyed
811
812 procedure FREEENT,NEAR
813 DOSAssume CS,<DS>,"FreeEnt"
814 ASSUME ES:NOTHING
815
816 PUSH DS
817 LDS DI,[CURBUF]
818ASSUME DS:NOTHING
819 MOV CX,[SI] ; Get pointer to clusters
820 MOV DX,WORD PTR [DI.buf_sector+2] ;F.C. >32mb ;AN000;
821 MOV [HIGH_SECTOR],DX ;F.C. >32mb ;AN000;
822 MOV DX,WORD PTR [DI.buf_sector]
823 POP DS
824 DOSAssume CS,<DS>,"MKNODE/FreeEnt"
825 CMP CX,2
826 JB RET1 ; Was 0 length file (or mucked Firclus if CX=1)
827 CMP CX,ES:[BP.dpb_max_cluster]
828 JA RET1 ; Treat like zero length file (firclus mucked)
829 SUB BX,DI
830 PUSH BX ; Save offset
831 PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000;
832 PUSH DX ; Save sector number
833
834 MOV BX,CX
835 invoke Delete_FSeek ; FS. delete Fastseek Clusters ;AN000;
836 invoke RELEASE ; Free any data allocated
837 POP DX
838 POP [HIGH_SECTOR] ;F.C. >32mb ;AN000;
839 JNC GET_BUF_BACK
840 POP BX
841 return ; Screw up
842
843GET_BUF_BACK:
844
845 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
846 XOR AL,AL
847 invoke GETBUFFR ; Get sector back
848 POP BX ; Get offset back
849 retc
850 invoke SET_BUF_AS_DIR
851 ADD BX,WORD PTR [CURBUF] ; Correct it for new buffer
852 MOV SI,BX
853 ADD SI,dir_first ; Get corrected SI
854RET1:
855 CLC
856 return
857EndProc FREEENT
858
859;
860; CHECK_VIRT_OPEN checks to see if we had performed a "virtual open" (by
861; examining the flag [VIRTUAL_OPEN] to see if it is 1). If we did, then
862; it calls Dev_Close_SFT to decrement the ref. count. It also resets the
863; flag [VIRTUAL_OPEN].
864; No registers affected (including flags).
865; On input, [THISSFT] points to current SFT.
866;
867 Procedure CHECK_VIRT_OPEN,NEAR
868 DOSAssume CS,<DS>,"Check_Virt_Open"
869
870 PUSH AX
871 lahf ; preserve flags
872 CMP [VIRTUAL_OPEN],0
873 JZ ALL_CLOSED
874 mov [VIRTUAL_OPEN],0 ; reset flag
875 SaveReg <ES,DI>
876 LES DI,[THISSFT]
877 INVOKE DEV_CLOSE_SFT
878 RestoreReg <DI,ES>
879
880ALL_CLOSED:
881 sahf ; restore flags
882 POP AX
883 return
884
885EndProc CHECK_VIRT_OPEN
886
887
888CODE ENDS
889 END
890 \ No newline at end of file
diff --git a/v4.0/src/DOS/MSCODE.ASM b/v4.0/src/DOS/MSCODE.ASM
new file mode 100644
index 0000000..74668c9
--- /dev/null
+++ b/v4.0/src/DOS/MSCODE.ASM
@@ -0,0 +1,16 @@
1; SCCSID = @(#)ibmcode.asm 1.1 85/04/10
2TITLE MISC DOS ROUTINES - Int 25 and 26 handlers and other
3NAME IBMCODE
4
5;
6; System call dispatch code.
7;
8
9.xlist
10.xcref
11include mssw.asm
12.cref
13.list
14
15include ms_code.asm
16 END
diff --git a/v4.0/src/DOS/MSCONST.ASM b/v4.0/src/DOS/MSCONST.ASM
new file mode 100644
index 0000000..126f322
--- /dev/null
+++ b/v4.0/src/DOS/MSCONST.ASM
@@ -0,0 +1,153 @@
1; SCCSID = @(#)msconst.asm 1.4 85/09/12
2; Revision history
3; AN000 version 4.00 Jan. 1988
4; AN007 fake version check for IBMCACHE.COM
5include mshead.asm
6include version.inc
7
8CODE SEGMENT BYTE PUBLIC 'CODE'
9 Extrn LeaveDOS:NEAR
10 Extrn BadCall:FAR, OKCall:FAR
11CODE ENDS
12
13Break <Initialized data and data used at DOS initialization>
14
15;
16; We need to identify the parts of the data area that are relevant to tasks
17; and those that are relevant to the system as a whole. Under 3.0, the system
18; data will be gathered with the system code. The process data under 2.x will
19; be available for swapping and under 3.0 it will be allocated per-process.
20;
21; The data that is system data will be identified by [SYSTEM] in the comments
22; describing that data item.
23;
24
25 AsmVars <Kanji, Debug, Redirector, ShareF>
26
27CONSTANTS SEGMENT WORD PUBLIC 'CONST'
28
29 extrn sfTabl:DWORD
30
31 ORG 0
32
33 EVEN
34;
35; WANGO!!! The following word is used by SHARE and REDIR to determin data
36; area compatability. This location must be incremented EACH TIME the data
37; area here gets mucked with.
38;
39; Also, do NOT change this position relative to DOSGROUP:0.
40;
41Public MSCT001S,MSCT001E
42MSCT001S:
43 I_am DataVersion,WORD,<1> ;AC000; [SYSTEM] version number for DOS DATA
44
45%out WARNING!!! Debug fields are being included!!!
46 DB "BUG " ; THIS FIELD MUST BE EVEN # OF BYTES
47 I_am BugTyp,WORD,<0>
48 I_am BugLev,WORD,<0>
49include bugtyp.asm
50
51 I_am MYNUM,WORD,<0> ; [SYSTEM] A number that goes with MYNAME
52 I_am FCBLRU,WORD,<0> ; [SYSTEM] LRU count for FCB cache
53 I_am OpenLRU,WORD,<0> ; [SYSTEM] LRU count for FCB cache opens
54; NOTE: We include the decl of OEM_HANDLER in IBM DOS even though it is not used.
55; This allows the REDIRector to work on either IBM or MS-DOS.
56 PUBLIC OEM_HANDLER
57OEM_HANDLER DD -1 ; [SYSTEM] Pointer to OEM handler code
58 I_am LeaveAddr,WORD,<<OFFSET DOSGroup:LeaveDOS>> ; [SYSTEM]
59 I_am RetryCount,WORD,<3> ; [SYSTEM] Share retries
60 I_am RetryLoop,WORD,<1> ; [SYSTEM] Share retries
61 I_am LastBuffer,DWORD,<-1,-1>; [SYSTEM] Buffer queue recency pointer
62 I_am CONTPOS,WORD ; [SYSTEM] location in buffer of next read
63 I_am arena_head,WORD ; [SYSTEM] Segment # of first arena in memory
64; The following block of data is used by SYSINIT. Do not change the order or
65; size of this block
66 PUBLIC SYSINITVAR ; [SYSTEM]
67SYSINITVAR LABEL WORD ; [SYSTEM]
68 I_am DPBHEAD,DWORD ; [SYSTEM] Pointer to head of DPB-FAT list
69 I_am sft_addr,DWORD,<<OFFSET DosGroup:sfTabl>,?> ; [SYSTEM] Pointer to first SFT table
70 I_am BCLOCK,DWORD ; [SYSTEM] The CLOCK device
71 I_am BCON,DWORD ; [SYSTEM] Console device entry points
72 I_am MAXSEC,WORD,<128> ; [SYSTEM] Maximum allowed sector size
73 I_am BUFFHEAD,DWORD ; [SYSTEM] Pointer to head of buffer queue
74 I_am CDSADDR,DWORD ; [SYSTEM] Pointer to curdir structure table
75 I_am sftFCB,DWORD ; [SYSTEM] pointer to FCB cache table
76 I_am KeepCount,WORD ; [SYSTEM] count of FCB opens to keep
77 I_am NUMIO,BYTE ; [SYSTEM] Number of disk tables
78 I_am CDSCOUNT,BYTE ; [SYSTEM] Number of CDS structures in above
79; A fake header for the NUL device
80 I_am NULDEV,DWORD ; [SYSTEM] Link to rest of device list
81 DW DEVTYP OR ISNULL ; [SYSTEM] Null device attributes
82 short_addr SNULDEV ; [SYSTEM] Strategy entry point
83 short_addr INULDEV ; [SYSTEM] Interrupt entry point
84 DB "NUL " ; [SYSTEM] Name of null device
85 I_am Splices,BYTE,<0> ; [SYSTEM] TRUE => splices being done
86 I_am Special_Entries,WORD,<0>; [SYSTEM] address of specail entries ;AN000;
87 I_am IFS_DOS_CALL,DWORD ; [SYSTEM] entry for IFS DOS service ;AN000;
88 I_am IFS_HEADER,DWORD ; [SYSTEM] IFS header chain ;AN000;
89 I_am BUFFERS_PARM1,WORD,<0> ; [SYSTEM] value of BUFFERS= ,m ;AN000;
90 I_am BUFFERS_PARM2,WORD,<0> ; [SYSTEM] value of BUFFERS= ,n ;AN000;
91 I_am BOOTDRIVE,BYTE ; [SYSTEM] the boot drive ;AN000;
92 I_am DDMOVE,BYTE,<0> ; [SYSTEM] 1 if we need DWORD move ;AN000;
93 I_am EXT_MEM_SIZE,WORD,<0> ; [SYSTEM] extended memory size ;AN000;
94
95 PUBLIC HASHINITVAR ; [SYSTEM] ;AN000;
96HASHINITVAR LABEL WORD ; [SYSTEM] ;AN000;
97 I_am BUF_HASH_PTR,DWORD ; [SYSTEM] buffer Hash table addr ;AN000;
98 I_am BUF_HASH_COUNT,WORD,<1> ; [SYSTEM] number of Hash entries ;AN000;
99 I_am SC_CACHE_PTR,DWORD ; [SYSTEM] secondary cache pointer ;AN000;
100 I_am SC_CACHE_COUNT,WORD,<0> ; [SYSTEM] secondary cache count ;AN000;
101
102IF BUFFERFLAG
103
104 I_am BUF_EMS_SAFE_FLAG,BYTE,<1> ; indicates whether the page used by buffers is safe or not
105 I_am BUF_EMS_LAST_PAGE,4,<0,0,0,0> ; holds the last page above 640k
106 I_am BUF_EMS_FIRST_PAGE,4,<0,0,0,0> ; holds the first page above 640K
107 I_am BUF_EMS_NPA640,WORD,<0> ; holds the number of pages above 640K
108
109ENDIF
110
111 I_am BUF_EMS_MODE,BYTE,<-1> ; [SYSTEM] EMS mode ;AN000;
112 I_am BUF_EMS_HANDLE,WORD ; [SYSTEM] buffer EMS handle ;AN000;
113 I_am BUF_EMS_PAGE_FRAME,WORD ,<-1>;[SYSTEM] EMS page frame number ;AN000;
114 I_am BUF_EMS_SEG_CNT,WORD,<1>; [SYSTEM] EMS seg count ;AN000;
115 I_am BUF_EMS_PFRAME,WORD ; [SYSTEM] EMS page frame seg address ;AN000;
116 I_am BUF_EMS_RESERV,WORD,<0> ; [SYSTEM] reserved ;AN000;
117
118IF BUFFERFLAG
119 I_am BUF_EMS_MAP_BUFF,1,<0> ; this is not used to save the state of the
120 ; of the buffers page. this one byte is
121 ; retained to keep the size of this data
122 ; block the same.
123ELSE
124 I_am BUF_EMS_MAP_BUFF,12,<0,0,0,0,0,0,0,0,0,0,0,0> ; map buufer ;AN000;
125ENDIF
126
127; End of SYSINITVar block
128
129;
130; Sharer jump table
131;
132PUBLIC JShare
133 EVEN
134JShare LABEL DWORD
135 DW OFFSET DOSGROUP:BadCall, 0
136 DW OFFSET DOSGROUP:OKCall, 0 ; 1 MFT_enter
137 DW OFFSET DOSGROUP:OKCall, 0 ; 2 MFTClose
138 DW OFFSET DOSGROUP:BadCall, 0 ; 3 MFTclU
139 DW OFFSET DOSGROUP:BadCall, 0 ; 4 MFTCloseP
140 DW OFFSET DOSGROUP:BadCall, 0 ; 5 MFTCloN
141 DW OFFSET DOSGROUP:BadCall, 0 ; 6 set_block
142 DW OFFSET DOSGROUP:BadCall, 0 ; 7 clr_block
143 DW OFFSET DOSGROUP:OKCall, 0 ; 8 chk_block
144 DW OFFSET DOSGROUP:BadCall, 0 ; 9 MFT_get
145 DW OFFSET DOSGROUP:BadCall, 0 ; 10 ShSave
146 DW OFFSET DOSGROUP:BadCall, 0 ; 11 ShChk
147 DW OFFSET DOSGROUP:OKCall , 0 ; 12 ShCol
148 DW OFFSET DOSGROUP:BadCall, 0 ; 13 ShCloseFile
149 DW OFFSET DOSGROUP:BadCall, 0 ; 14 ShSU
150
151MSCT001E:
152CONSTANTS ENDS
153 \ No newline at end of file
diff --git a/v4.0/src/DOS/MSCPMIO.ASM b/v4.0/src/DOS/MSCPMIO.ASM
new file mode 100644
index 0000000..53656ff
--- /dev/null
+++ b/v4.0/src/DOS/MSCPMIO.ASM
@@ -0,0 +1,17 @@
1; SCCSID = @(#)ibmcpmio.asm 1.1 85/04/10
2;
3; Standard device IO for MSDOS (first 12 function calls)
4;
5
6.xlist
7.xcref
8include mssw.asm
9include dosseg.asm
10.cref
11.list
12
13TITLE IBMCPMIO - device IO for MSDOS
14NAME IBMCPMIO
15
16include cpmio.asm
17 \ No newline at end of file
diff --git a/v4.0/src/DOS/MSCTRLC.ASM b/v4.0/src/DOS/MSCTRLC.ASM
new file mode 100644
index 0000000..8343b08
--- /dev/null
+++ b/v4.0/src/DOS/MSCTRLC.ASM
@@ -0,0 +1,16 @@
1; SCCSID = @(#)ibmctrlc.asm 1.1 85/04/10
2;
3; ^C and error handler for MSDOS
4;
5
6.xlist
7.xcref
8include mssw.asm
9.cref
10.list
11
12TITLE Control C detection, Hard error and EXIT routines
13NAME IBMCTRLC
14
15include ctrlc.asm
16 \ No newline at end of file
diff --git a/v4.0/src/DOS/MSDISP.ASM b/v4.0/src/DOS/MSDISP.ASM
new file mode 100644
index 0000000..a0f069e
--- /dev/null
+++ b/v4.0/src/DOS/MSDISP.ASM
@@ -0,0 +1,17 @@
1; SCCSID = @(#)ibmdisp.asm 1.1 85/04/10
2TITLE IBM DOS DISPATCHER - System call dispatch code
3NAME DISP
4
5;
6; System call dispatch code
7;
8
9.xlist
10.xcref
11include mssw.asm
12.cref
13.list
14
15include disp.asm
16 END
17 \ No newline at end of file
diff --git a/v4.0/src/DOS/MSDOS.LNK b/v4.0/src/DOS/MSDOS.LNK
new file mode 100644
index 0000000..2d43bdb
--- /dev/null
+++ b/v4.0/src/DOS/MSDOS.LNK
@@ -0,0 +1,59 @@
1..\inc\nibdos.obj +
2..\inc\const2.obj +
3..\inc\msdata.obj +
4..\inc\mstable.obj +
5 msdisp.obj +
6 mscode.obj +
7..\inc\msdosme.obj +
8 time.obj +
9 getset.obj +
10 parse.obj +
11 misc.obj +
12 misc2.obj +
13 crit.obj +
14 cpmio.obj +
15 cpmio2.obj +
16 fcbio.obj +
17 fcbio2.obj +
18 search.obj +
19 path.obj +
20 ioctl.obj +
21 delete.obj +
22 rename.obj +
23 finfo.obj +
24 dup.obj +
25 create.obj +
26 open.obj +
27 dinfo.obj +
28 isearch.obj +
29 abort.obj +
30 close.obj +
31 dircall.obj +
32 disk.obj +
33 disk2.obj +
34 disk3.obj +
35 dir.obj +
36 dir2.obj +
37 dev.obj +
38 mknode.obj +
39 rom.obj +
40 fcb.obj +
41 msctrlc.obj +
42 fat.obj +
43 buf.obj +
44 proc.obj +
45 alloc.obj +
46 srvcall.obj +
47 util.obj +
48 handle.obj +
49 macro.obj +
50 macro2.obj +
51 file.obj +
52 lock.obj +
53 share.obj +
54 extattr.obj +
55 ifs.obj
56MSDOS.EXE
57MSDOS.MAP /M
58;
59
diff --git a/v4.0/src/DOS/MSDOS.SKL b/v4.0/src/DOS/MSDOS.SKL
new file mode 100644
index 0000000..c76c224
--- /dev/null
+++ b/v4.0/src/DOS/MSDOS.SKL
@@ -0,0 +1,17 @@
1
2:class 1
3; This was taken from DEVMES.INC IN G:USA\ ...
4; DIVMES DB 13,10,"Divide overflow",13,10
5
6:use 001 msdos DIVMES
7
8:class 3
9
10;This is for Yes No check
11:use 205 command NLS_YES
12:use 206 command NLS_NO
13:use 002 msdos NLS_yes2
14:use 003 msdos NLS_no2
15
16:end
17 \ No newline at end of file
diff --git a/v4.0/src/DOS/MSHALO.ASM b/v4.0/src/DOS/MSHALO.ASM
new file mode 100644
index 0000000..dc6c64a
--- /dev/null
+++ b/v4.0/src/DOS/MSHALO.ASM
@@ -0,0 +1,247 @@
1; SCCSID = @(#)ibmhalo.asm 1.1 85/04/10
2; On 2K (800h) boundaries beginning at address C0000h and ending at EF800h
3; there is a header that describes a block of rom program. This header
4; contains information needed to initialize a module and to provide PCDOS
5; with a set of reserved names for execution.
6;
7; This header has the following format:
8;
9; rom_header STRUC
10; Signature1 DB 55h
11; Signature2 DB AAh
12; rom_length DB ? ; number of 512 byte pieces
13; init_jmp DB 3 dup (?)
14; name_list name_struc <>
15; rom_header ENDS
16;
17; name_struc STRUC
18; name_len DB ?
19; name_text DB ? DUP (?)
20; name_jmp DB 3 DUP (?)
21; name_struc ENDS
22;
23; The name list is a list of names that are reserved by a particular section
24; of a module. This list of names is terminated by a null name (length
25; is zero).
26;
27; Consider now, the PCDOS action when a user enters a command:
28;
29; COMMAND.COM has control.
30; o If location FFFFEh has FDh then
31; o Start scanning at C0000h, every 800h for a byte 55h followed
32; by AAh, stop scan if we get above or = F0000H
33; o When we've found one, compare the name entered by the user
34; with the one found in the rom. If we have a match, then
35; set up the environment for execution and do a long jump
36; to the near jump after the found name.
37; o If no more names in the list, then continue scanning the module
38; for more 55h followed by AAh.
39; o We get to this point only if there is no matching name in the
40; rom. We now look on disk for the command.
41;
42; This gives us the flexibility to execute any rom cartridge without having
43; to 'hard-code' the name of the cartridge into PCDOS. Rom modules that
44; want to be invisible to the DOS should not have any names in their lists
45; (i.e. they have a single null name).
46;
47; Consider a new release of BASIC, say, that patches bugs in the ROM version.
48; Clearly this version will be available on disk. How does a user actually
49; invoke this new BASIC?? He cannot call it BASIC on the disk because the
50; EXEC loader will execute the ROM before it even looks at the disk! Only
51; solution:
52;
53; o Keep things consistent and force the user to have his software named
54; differently from the ROM names (BASIC1, BASIC2, etc).
55
56rom_header STRUC
57 Signature1 DB ?
58 Signature2 DB ?
59 rom_length DB ?
60 init_jmp DB 3 dup (?)
61 name_list DB ?
62rom_header ENDS
63
64name_struc STRUC
65 name_len DB ?
66 name_text DB 1 DUP (?)
67 name_jmp DB 3 DUP (?)
68name_struc ENDS
69
70ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
71
72;
73; Check for IBM HALO rom cartrides. DS:DX is a pointer to name
74;
75ROM_SCAN:
76 PUSH ES
77 PUSH SI
78 PUSH DI
79 PUSH CX
80 PUSH AX
81 PUSH BX
82;
83; check for halo signature in rom
84;
85 MOV AX,0F000h
86 MOV ES,AX
87 CMP BYTE PTR ES:[0FFFEh],0FDh
88 JZ SCAN_IT
89NO_ROM:
90 CLC
91ROM_RET:
92 POP BX
93 POP AX
94 POP CX
95 POP DI
96 POP SI
97 POP ES
98 RET
99SCAN_IT:
100;
101; start scanning at C000
102;
103 MOV AX,0C000h
104SCAN_ONE:
105 MOV ES,AX
106 XOR DI,DI
107SCAN_MODULE:
108;
109; check for a valid header
110;
111 CMP WORD PTR ES:[DI],0AA55h
112 JZ SCAN_LIST
113 ADD AX,080h
114SCAN_END:
115 CMP AX,0F000h
116 JB SCAN_ONE
117 JMP NO_ROM
118;
119; trundle down list of names
120;
121SCAN_LIST:
122 MOV BL,ES:[DI].rom_length ; number of 512-byte jobbers
123 XOR BH,BH ; nothing in the high byte
124 SHL BX,1
125 SHL BX,1 ; number of paragraphs
126 ADD BX,7Fh
127 AND BX,0FF80h ; round to 2k
128
129 MOV DI,name_list
130SCAN_NAME:
131 MOV CL,ES:[DI] ; length of name
132 INC DI ; point to name
133 XOR CH,CH
134 OR CX,CX ; zero length name
135 JNZ SCAN_TEST ; nope... compare
136 ADD AX,BX ; yep, skip to next block
137 JMP SCAN_END
138;
139; compare a single name
140;
141SCAN_TEST:
142 MOV SI,DX
143 INC SI
144 REPE CMPSB ; compare name
145 JZ SCAN_FOUND ; success!
146SCAN_NEXT:
147 ADD DI,CX ; failure, next name piece
148 ADD DI,3
149 JMP SCAN_NAME
150;
151; found a name. save entry location
152;
153SCAN_FOUND:
154 CMP BYTE PTR DS:[SI],'?'
155 JZ SCAN_SAVE
156 CMP BYTE PTR DS:[SI],' '
157 JNZ SCAN_NEXT
158SCAN_SAVE:
159 MOV [rom_cs],ES
160 MOV [ROM_ip],DI
161 STC
162 JMP ROM_RET
163
164;
165; execute a rom-placed body of code. allocate largest block
166;
167ROM_EXEC:
168 MOV BX,0FFFFh
169 MOV AH,ALLOC
170 INT int_command
171 MOV AH,ALLOC
172 INT int_command
173 PUSH BX
174 PUSH AX
175;
176; set terminate addresses
177;
178 MOV AX,(set_interrupt_vector SHL 8) + int_terminate
179 PUSH DS
180 MOV DS,[RESSEG]
181 ASSUME DS:RESGROUP
182 MOV DX,OFFSET RESGROUP:EXEC_WAIT
183 INT int_command
184 MOV DX,DS
185 MOV ES,DX
186 ASSUME ES:RESGROUP
187 POP DS
188 ASSUME DS:NOTHING
189;
190; and create program header and dup all jfn's
191;
192 POP DX
193 MOV AH,DUP_PDB
194 INT int_command
195;
196; set up dma address
197;
198 MOV DS,DX
199 MOV DX,080h
200 MOV AH,SET_DMA
201 INT int_command
202;
203; copy in environment info
204;
205 MOV AX,[ENVIRSEG]
206 MOV DS:[PDB_environ],AX
207;
208; set up correct size of block
209;
210 POP BX ; BX has size, DS has segment
211 MOV DX,DS
212 ADD DX,BX
213 MOV DS:[PDB_block_len],DX
214;
215; change ownership of block
216;
217 MOV DX,DS
218 DEC DX
219 MOV DS,DX
220 INC DX
221 MOV DS:[arena_owner],DX
222 MOV DS,DX
223;
224; set up correct stack
225;
226 CMP BX,1000h
227 JB GOT_STACK
228 XOR BX,BX
229GOT_STACK:
230 MOV CL,4
231 SHL BX,CL
232 MOV DX,DS
233 MOV SS,DX
234 MOV SP,BX
235 XOR AX,AX
236 PUSH AX
237;
238; set up initial registers and go to the guy
239;
240 NOT AX
241 PUSH [ROM_CS]
242 PUSH [ROM_IP]
243 MOV ES,DX
244ASSUME ES:NOTHING
245FOOBAR PROC FAR
246 RET
247FOOBAR ENDP
diff --git a/v4.0/src/DOS/MSINIT.ASM b/v4.0/src/DOS/MSINIT.ASM
new file mode 100644
index 0000000..cbd9eaf
--- /dev/null
+++ b/v4.0/src/DOS/MSINIT.ASM
@@ -0,0 +1,667 @@
1; SCCSID = @(#)msinit.asm 1.2 85/07/23
2; TITLE MSINIT.ASM -- MS-DOS INITIALIZATION CODE
3; AN000 version 4.0 Jan. 1988
4; AN007 PTM 3957 - fake version for IBMCACHE.COM
5; AN008 PTM 4070 - fake version for MS WINDOWS
6include sysvar.inc
7include doscntry.inc
8include fastopen.inc
9
10 I_need DMAAdd,DWORD ; current dma address
11 I_need DPBHead,DWORD ; long pointer to DPB chain
12 I_need SFT_Addr,DWORD ; pointer to open file list
13 I_need NumIO,BYTE ; number of physical drives
14 I_need BuffHead,DWORD ; pointer to buffer chain
15 I_need EndMem,WORD ; first unavailable address in memory
16 I_need CurrentPDB,WORD ; current process ID
17 I_need CreatePDB,BYTE ; TRUE => create a new PDB
18 I_need Arena_Head,WORD ; paragraph address of head of arena
19 I_need sfTabl,BYTE ; internal file table
20 I_need SysInitVar,BYTE ; label for internal structures
21 I_need NulDev,DWORD ; long pointer to device chain
22 I_need BCon,DWORD ; pointer to console device
23 I_need BClock,DWORD ; pointer to clock device
24 I_need CallUnit,BYTE ; unit field in dd packet
25 I_need CallBPB,DWORD ; returned BPB from DD
26 I_need Maxsec,WORD
27 I_need Dskchret,BYTE
28 I_need Devcall,BYTE
29 i_need Header,BYTE
30 I_need JShare,DWORD
31 I_need COUNTRY_CDPG,BYTE ; country info table, DOS 3.3
32 I_need SysInitTable,BYTE ; sys init table for SYSINIT
33 I_need FastOpenTable,BYTE ; table for FASTOPEN
34 I_need FETCHI_TAG,WORD ; TAG CHECK
35 I_need Special_Entries,WORD ; address of special entries ;AN007;
36 I_need IFS_DOS_CALL,DWORD ; IFS IBMDOS CALL entry ;AN000;
37 I_need HASHINITVAR,WORD ; hash table variables ;AN000;
38 I_need Packet_Temp,WORD ; used for initial Hash table;AN000;
39 I_need BUF_HASH_PTR,DWORD ; used for initial Hash table;AN000;
40 I_need SWAP_ALWAYS_AREA,DWORD ; swap always area addr ;AN000;
41 I_need SWAP_ALWAYS_AREA_LEN,WORD; swap always area length ;AN000;
42 I_need SWAP_IN_DOS,DWORD ; swap in dos area ;AN000;
43 I_need SWAP_IN_DOS_LEN,WORD ; swap in dos area length ;AN000;
44 I_need SWAP_AREA_LEN,WORD ; swap area length ;AN000;
45 I_need SWAP_START,BYTE ; swap start addr ;AN000;
46 I_need SWAP_ALWAYS,BYTE ; swap always addr ;AN000;
47 I_need Hash_Temp,WORD ; temporary Hash table ;AN000;
48
49CODE SEGMENT BYTE PUBLIC 'CODE'
50 Extrn IRETT:NEAR,INT2F:NEAR,CALL_ENTRY:NEAR,QUIT:NEAR,IFS_DOSCALL:FAR
51 Extrn COMMAND:NEAR,ABSDRD:NEAR,ABSDWRT:NEAR
52CODE ENDS
53
54DATA SEGMENT WORD PUBLIC 'DATA'
55 ORG 0 ; reset to beginning of data segment
56
57Public MSINI001S,MSINI001E
58MSINI001S label byte
59INITBLOCK DB 110H DUP(0) ; Allow for segment round up
60
61INITSP DW ?
62INITSS DW ?
63MSINI001E label byte
64
65ASSUME CS:DOSGROUP,SS:NOTHING
66
67MOVDPB:
68 DOSAssume CS,<DS,ES>,"MovDPB"
69; This section of code is safe from being overwritten by block move
70 MOV SS,CS:[INITSS]
71 MOV SP,CS:[INITSP]
72 REP MOVS BYTE PTR [DI],[SI]
73 CLD
74 MOV WORD PTR ES:[DMAADD+2],DX
75 MOV SI,WORD PTR [DPBHEAD] ; Address of first DPB
76 MOV WORD PTR ES:[DPBHEAD+2],ES
77 MOV WORD PTR ES:[sft_addr+2],ES
78 MOV CL,[NUMIO] ; Number of DPBs
79 XOR CH,CH
80SETFINDPB:
81 MOV WORD PTR ES:[SI.dpb_next_dpb+2],ES
82 MOV ES:[SI.dpb_first_access],-1 ; Never accessed before
83 ADD SI,DPBSIZ ; Point to next DPB
84 LOOP SETFINDPB
85 SUB SI,DPBSIZ
86 MOV WORD PTR ES:[SI.dpb_next_dpb+2],-1
87
88;; PUSH ES
89;; MOV DI,OFFSET DOSGroup:SYSBUF + 0Fh
90;; RCR DI,1
91;; SHR DI,1
92;; SHR DI,1
93;; SHR DI,1
94;; MOV AX,ES
95;; ADD AX,DI
96;; MOV ES,AX
97;; ASSUME ES:NOTHING
98;; XOR DI,DI
99
100; MOV DI,OFFSET DOSGroup:SYSBUF ; Set up one default buffer
101; MOV WORD PTR [BUFFHEAD+2],ES
102; MOV WORD PTR [BUFFHEAD],DI
103;; MOV WORD PTR [Hash_Temp+4],ES ;LB. intitialize one Hash entry ;AN000;
104;; MOV WORD PTR [Hash_Temp+2],DI ;LB. ;AN000;
105;; MOV WORD PTR [Hash_Temp+6],0 ;LB. dirty count =0 ;AN000;
106;; MOV WORD PTR ES:[DI.buf_ID],00FFH
107;; MOV WORD PTR ES:[DI.buf_next],DI ;;;1/19/88
108;; MOV WORD PTR ES:[DI.buf_prev],DI ;;;1/19/88
109
110;; POP ES
111 MOV SI,OFFSET DOSGROUP:Version_Fake_Table ;MS.;AN007;move special
112 MOV DI,ES:[Special_Entries] ;MS.;AN007;entries
113 MOV CX,ES:[Temp_Var] ;MS.;AN007;
114 REP MOVSB ;MS.;AN007;
115
116 ASSUME ES:DOSGroup
117
118 PUSH ES
119 INC DX ; Leave enough room for the ARENA
120 MOV SI,EndMem
121 invoke $Dup_PDB
122; MOV BYTE PTR [CreatePDB],0FFh ; create jfns and set CurrentPDB
123; invoke $CREATE_PROCESS_DATA_BLOCK ; Set up segment
124ASSUME DS:NOTHING,ES:NOTHING
125 POP ES
126 DOSAssume CS,<ES>,"INIT/CreateProcess"
127;
128; set up memory arena
129;SPECIAL NOTE FOR HIGHMEM VERSION
130; At this point a process header has been built where the start of the CONSTANTS
131; segment as refed by CS is. From this point until the return below be careful
132; about references off of CS.
133;
134 MOV AX,[CurrentPDB]
135 MOV ES:[CurrentPDB],AX ; Put it in the REAL location
136 MOV BYTE PTR ES:[CreatePDB],0h ; reset flag in REAL location
137 DEC AX
138 MOV ES:[arena_head],AX
139 PUSH DS
140 MOV DS,AX
141 MOV DS:[arena_signature],arena_signature_end
142 MOV DS:[arena_owner],arena_owner_system
143 SUB AX,ES:[ENDMEM]
144 NEG AX
145 DEC AX
146 MOV DS:[arena_size],AX
147 POP DS
148
149 MOV DI,OFFSET DOSGROUP:sftabl + SFTable ; Point to sft 0
150 MOV AX,3
151 STOSW ; Adjust Refcount
152 MOV DI,OFFSET DOSGROUP:SySInitTable
153
154 IF NOT Installed
155 invoke NETWINIT
156; ELSE
157; invoke NETWINIT
158; %OUT Random NETWINIT done at install
159 ENDIF
160
161procedure XXX,FAR
162 RET
163EndProc XXX
164DATA ENDS
165
166; the next segment defines a new class that MUST appear last in the link map.
167; This defines several important locations for the initialization process that
168; must be the first available locations of free memory.
169
170LAST SEGMENT PARA PUBLIC 'LAST'
171 PUBLIC SYSBUF
172 PUBLIC MEMSTRT
173
174SYSBUF LABEL WORD
175ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
176
177INITIRET: ; Temp IRET instruction
178 IRET
179
180 entry DOSINIT
181 CLI
182 CLD
183 MOV [ENDMEM],DX
184 MOV [INITSP],SP
185 MOV [INITSS],SS
186 MOV AX,CS
187 MOV SS,AX
188ASSUME SS:DOSGROUP
189 MOV SP,OFFSET DOSGROUP:INITSTACK
190 MOV WORD PTR [NULDEV+2],DS
191 MOV WORD PTR [NULDEV],SI ; DS:SI Points to CONSOLE Device
192
193 PUSH DS ; Need Crit vector inited to use DEVIOCALL
194 XOR AX,AX
195 MOV DS,AX
196 MOV AX,OFFSET DOSGROUP:INITIRET
197 MOV DS:[addr_int_IBM],AX
198 MOV AX,CS
199 MOV DS:[addr_int_IBM+2],AX
200 POP DS
201
202 CALL CHARINIT
203 PUSH SI ; Save pointer to header
204 PUSH CS
205 POP ES
206 ASSUME ES:DOSGROUP
207 MOV DI,OFFSET DOSGROUP:sftabl + SFTable ; Point to sft 0
208 MOV AX,3
209 STOSW ; Refcount
210 DEC AL
211 errnz sf_mode-(sf_ref_count+2)
212 STOSW ; Access rd/wr, compatibility
213 XOR AL,AL
214 errnz sf_attr-(sf_mode+2)
215 STOSB ; attribute
216 MOV AL,devid_device_EOF OR devid_device OR ISCIN OR ISCOUT
217 errnz sf_flags-(sf_attr+1)
218 STOSW ; Flags
219 MOV AX,SI
220 errnz sf_devptr-(sf_flags+2)
221 STOSW ; Device pointer in devptr
222 MOV AX,DS
223 STOSW
224 XOR AX,AX
225 errnz sf_firclus-(sf_devptr+4)
226 STOSW ; firclus
227 errnz sf_time-(sf_firclus+2)
228 STOSW ; time
229 errnz sf_date-(sf_time+2)
230 STOSW ; date
231 DEC AX
232 errnz sf_size-(sf_date+2)
233 STOSW ; size
234 STOSW
235 INC AX
236 errnz sf_position-(sf_size+4)
237 STOSW ; position
238 STOSW
239 ADD DI,sf_name - sf_cluspos ;Point at name
240 ADD SI,SDEVNAME ; Point to name
241 MOV CX,4
242 REP MOVSW ; Name
243 MOV CL,3
244 MOV AL," "
245 REP STOSB ; Extension
246 POP SI ; Get back pointer to header
247 OR BYTE PTR [SI.SDEVATT],ISCIN OR ISCOUT
248 MOV WORD PTR [BCON],SI
249 MOV WORD PTR [BCON+2],DS
250CHAR_INIT_LOOP:
251 LDS SI,DWORD PTR [SI] ; AUX device
252 CALL CHARINIT
253 TEST BYTE PTR [SI.SDEVATT],ISCLOCK
254 JZ CHAR_INIT_LOOP
255 MOV WORD PTR [BCLOCK],SI
256 MOV WORD PTR [BCLOCK+2],DS
257 MOV BP,OFFSET DOSGROUP:MEMSTRT ; ES:BP points to DPB
258PERDRV:
259 LDS SI,DWORD PTR [SI] ; Next device
260 CMP SI,-1
261 JZ CONTINIT
262 CALL CHARINIT
263 TEST [SI.SDEVATT],DEVTYP
264 JNZ PERDRV ; Skip any other character devs
265 MOV CL,[CALLUNIT]
266 XOR CH,CH
267 MOV [SI.SDEVNAME],CL ; Number of units in name field
268 MOV DL,[NUMIO]
269 XOR DH,DH
270 ADD [NUMIO],CL
271 PUSH DS
272 PUSH SI
273 LDS BX,[CALLBPB]
274PERUNIT:
275 MOV SI,[BX] ; DS:SI Points to BPB
276 INC BX
277 INC BX ; On to next BPB
278 MOV ES:[BP.dpb_drive],DL
279 MOV ES:[BP.dpb_UNIT],DH
280 PUSH BX
281 PUSH CX
282 PUSH DX
283 invoke $SETDPB
284 MOV AX,ES:[BP.dpb_sector_size]
285 CMP AX,[MAXSEC]
286 JBE NOTMAX
287 MOV [MAXSEC],AX
288NOTMAX:
289
290 POP DX
291 POP CX
292 POP BX
293 MOV AX,DS ; Save DS
294 POP SI
295 POP DS
296 MOV WORD PTR ES:[BP.dpb_driver_addr],SI
297 MOV WORD PTR ES:[BP.dpb_driver_addr+2],DS
298 PUSH DS
299 PUSH SI
300 INC DH
301 INC DL
302 MOV DS,AX
303 ADD BP,DPBSIZ
304 LOOP PERUNIT
305 POP SI
306 POP DS
307 JMP PERDRV
308
309CONTINIT:
310 PUSH CS
311 POP DS
312ASSUME DS:DOSGROUP
313;
314; BP has the current offset to the allocated DPBs. Calculate true address of
315; buffers, FATs, free space
316;
317 MOV DI,BP ; First byte after current DPBs
318;
319; Compute location of first buffer. If we are to make buffers paragraph
320; aligned, change this code to make sure that AX = 0 mod 16 and change the
321; setting of the segment address part of BuffHead to make sure that the offset
322; is zero. Alternatively, this may be done by making segment LAST paragraph
323; aligned.
324;
325;;; MOV BP,[MAXSEC] ; get size of buffer
326 MOV AX,OFFSET DOSGROUP:SYSBUF
327;
328; Compute location of DPBs
329;
330;;; ADD AX,BP ; One I/O buffer
331;;; ADD AX,BUFINSIZ
332 MOV WORD PTR [DPBHEAD],AX ; True start of DPBs
333 MOV DX,AX
334 SUB DX,OFFSET DOSGROUP:SYSBUF
335 MOV BP,DX
336 ADD BP,DI ; Allocate buffer space
337 SUB BP,ADJFAC ; True address of free memory
338 PUSH BP
339 MOV DI,OFFSET DOSGROUP:MEMSTRT ; Current start of DPBs
340 ADD DI,dpb_next_dpb ; Point at dpb_next_dpb field
341 MOV CL,[NUMIO]
342 XOR CH,CH
343TRUEDPBAD:
344 ADD AX,DPBSIZ ; Compute address of next DPB
345 STOSW ; Set the link to next DPB
346 ADD DI,DPBSIZ-2 ; Point at next address
347 LOOP TRUEDPBAD
348 SUB DI,DPBSIZ ; Point at last dpb_next_dpb field
349 MOV AX,-1
350 STOSW ; End of list
351
352 MOV [Special_Entries],BP ;MS.;AN007 save starting address of Special entries
353 MOV SI,OFFSET DOSGROUP:Version_Fake_Table ;MS.;AN007
354 MOV DX,SI ;MS.;AN007
355 XOR AH,AH ;MS.;AN007
356NextEntry: ;MS.;AN007
357 LODSB ;MS.;AN007 get name length
358 OR AL,AL ;MS.;AN007 end of list
359 JZ endlist ;MS.;AN007 yes
360 ADD SI,AX ;MS.;AN007 position to
361 ADD SI,3 ;MS.;AN007 next entry
362 JMP NextEntry ;MS.;AN007
363endlist: ;MS.;AN007
364 SUB SI,DX ;MS.;AN007
365 MOV [Temp_Var],SI ;MS.;AN007 si = total table length
366 ADD BP,SI ;MS.;AN007
367
368
369 ADD BP,15 ; True start of free space (round up to segment)
370 RCR BP,1
371 MOV CL,3
372 SHR BP,CL ; Number of segments for DOS resources
373;;;;;; MOV [IBMDOS_SIZE],BP ;MS. save it for information
374 MOV DX,CS
375 ADD DX,BP ; First free segment
376 MOV BX,0FH
377 MOV CX,[ENDMEM]
378
379 IF HIGHMEM
380 SUB CX,BP
381 MOV BP,CX ; Segment of DOS
382 MOV DX,CS ; Program segment
383 ENDIF
384
385 IF NOT HIGHMEM
386 MOV BP,CS
387 ENDIF
388
389; BP has segment of DOS (whether to load high or run in place)
390; DX has program segment (whether after DOS or overlaying DOS)
391; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM)
392 MOV [ENDMEM],CX
393 MOV ES,BP
394ASSUME ES:DOSGROUP
395
396 IF HIGHMEM
397 XOR SI,SI
398 MOV DI,SI
399 MOV CX,OFFSET DOSGROUP:SYSBUF ;# bytes to move
400 SHR CX,1 ;# words to move (carry set if odd)
401 REP MOVSW ; Move DOS to high memory
402 JNC NOTODD
403 MOVSB
404NOTODD:
405 ENDIF
406
407 MOV WORD PTR ES:[DSKCHRET+3],ES
408 XOR AX,AX
409 MOV DS,AX
410 MOV ES,AX
411ASSUME DS:NOTHING,ES:NOTHING
412 MOV DI,INTBASE+2
413 MOV AX,BP ; Final DOS segment to AX
414
415 EXTRN DIVOV:near
416 MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ; Set default divide trap address
417 MOV DS:[2],AX
418
419; Set vectors 20-28 and 2A-3F to point to IRET.
420
421 MOV CX,17
422 REP STOSW ; Set 9 segments
423 ; Sets segs for INTs 20H-28H
424 ADD DI,6 ; Skip INT 29H vector (FAST CON) as it may
425 ; already be set.
426 MOV CX,43
427 REP STOSW ; Set 22 segments
428 ; Sets segs for vectors 2AH-3FH
429
430 MOV DI,INTBASE
431 MOV AX,OFFSET DOSGROUP:IRETT
432 MOV CX,9 ; Set 9 offsets (skip 2 between each)
433 ; Sets offsets for INTs 20H-28H
434
435ISET1:
436 STOSW
437 ADD DI,2
438 LOOP ISET1
439
440 ADD DI,4 ; Skip vector 29H
441
442 MOV CX,22 ; Set 22 offsets (skip 2 between each)
443 ; Sets offsets for INTs 2AH-3FH
444
445ISET2:
446 STOSW
447 ADD DI,2
448 LOOP ISET2
449
450 MOV AX,BP ; Final DOS segment to AX
451
452IF installed
453; the following two are in the Code segment, thus the CS
454; overrides
455 MOV WORD PTR DS:[02FH * 4],OFFSET DOSGROUP:INT2F
456ENDIF
457
458; Set up entry point call at vectors 30-31H
459 MOV BYTE PTR DS:[ENTRYPOINT],mi_Long_JMP
460 MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:CALL_ENTRY
461 MOV WORD PTR DS:[ENTRYPOINT+3],AX
462
463 IF ALTVECT
464 MOV DI,ALTBASE+2
465 MOV CX,15
466 REP STOSW ; Set 8 segments (skip 2 between each)
467 ENDIF
468
469 MOV WORD PTR DS:[addr_int_abort],OFFSET DOSGROUP:QUIT
470 MOV WORD PTR DS:[addr_int_command],OFFSET DOSGROUP:COMMAND
471 MOV WORD PTR DS:[addr_int_terminate],100H
472 MOV WORD PTR DS:[addr_int_terminate+2],DX
473 MOV WORD PTR DS:[addr_int_disk_read],OFFSET DOSGROUP:ABSDRD ; INT 25
474 MOV WORD PTR DS:[addr_int_disk_write],OFFSET DOSGROUP:ABSDWRT ; INT 26
475 EXTRN Stay_resident:NEAR
476 MOV WORD PTR DS:[addr_int_keep_process],OFFSET DOSGROUP:Stay_resident
477
478 PUSH CS
479 POP DS
480 PUSH CS
481 POP ES
482ASSUME DS:DOSGROUP,ES:DOSGROUP
483;
484; Initialize the jump table for the sharer...
485;
486 MOV DI,OFFSET DOSGroup:JShare
487 MOV AX,CS
488 MOV CX,15
489JumpTabLoop:
490 ADD DI,2 ; skip offset
491 STOSW ; drop in segment
492 LOOP JumpTabLoop
493
494 MOV AX,OFFSET DOSGROUP:INITBLOCK
495 ADD AX,0Fh ; round to a paragraph
496 MOV CL,4
497 SHR AX,CL
498 MOV DI,DS
499 ADD DI,AX
500 INC DI
501 MOV [CurrentPDB],DI
502 PUSH BP
503 PUSH DX ; Save COMMAND address
504 MOV AX,[ENDMEM]
505 MOV DX,DI
506
507 invoke SETMEM ; Basic Header
508ASSUME DS:NOTHING,ES:NOTHING
509 PUSH CS
510 POP DS
511ASSUME DS:DOSGROUP
512 MOV DI,PDB_JFN_Table
513 XOR AX,AX
514 STOSW
515 STOSB ; 0,1 and 2 are CON device
516 MOV AL,0FFH
517 MOV CX,FilPerProc - 3
518 REP STOSB ; Rest are unused
519 PUSH CS
520 POP ES
521ASSUME ES:DOSGROUP
522 MOV WORD PTR [sft_addr+2],DS ; Must be set to print messages
523
524; After this points the char device functions for CON will work for
525; printing messages
526
527 IF (NOT IBM) OR (DEBUG)
528 IF NOT ALTVECT
529 MOV SI,OFFSET DOSGROUP:HEADER
530OUTMES:
531 LODS CS:BYTE PTR [SI]
532 CMP AL,"$"
533 JZ OUTDONE
534 invoke OUT
535 JMP SHORT OUTMES
536OUTDONE:
537 PUSH CS ; OUT stomps on segments
538 POP DS
539 PUSH CS
540 POP ES
541 ENDIF
542 ENDIF
543
544;F.C Modification start DOS 3.3
545 MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG ;F.C. for DOS 3.3 country info
546 ; table address
547 MOV WORD PTR ES:[SI.ccUcase_ptr + 2],ES ; initialize double word
548 MOV WORD PTR ES:[SI.ccFileUcase_ptr + 2],ES ; pointers with DOSGROUP
549 MOV WORD PTR ES:[SI.ccFileChar_ptr + 2],ES
550 MOV WORD PTR ES:[SI.ccCollate_ptr + 2],ES
551 MOV WORD PTR ES:[SI.ccMono_ptr + 2],ES
552 MOV WORD PTR ES:[SI.ccDBCS_ptr + 2],ES ; 2/16/KK
553
554 MOV SI,OFFSET DOSGROUP:SysInitTable
555 MOV WORD PTR ES:[SI.SYSI_Country_Tab + 2],ES
556 MOV WORD PTR ES:[SI.SYSI_InitVars + 2],ES
557
558 MOV WORD PTR ES:[BUFFHEAD+2],ES ;LB. DOS 4.00 buffer head pointer ;AN000;
559 MOV SI,OFFSET DOSGROUP:HASHINITVAR ;LB. points to Hashinitvar ;AN000;
560 MOV WORD PTR ES:[BUFFHEAD],SI ;LB. ;AN000;
561 MOV WORD PTR ES:[BUF_HASH_PTR+2],ES ;LB. ;AN000;
562 MOV SI,OFFSET DOSGROUP:Hash_Temp ;LB. ;AN000;
563 MOV WORD PTR ES:[BUF_HASH_PTR],SI ;LB. ;AN000;
564
565 MOV SI,OFFSET DOSGROUP:FastOpenTable
566 MOV WORD PTR ES:[SI.FASTOPEN_NAME_CACHING + 2],ES
567 MOV ES:[FETCHI_TAG],22642 ; TAG for IBM,
568 ; Fetchi's serial # = 822642
569 MOV WORD PTR ES:[IFS_DOS_CALL+2],ES ;IFS. ;AN000;
570 MOV SI,OFFSET DOSGROUP:IFS_DOSCALL ;IFS. ;AN000;
571 MOV WORD PTR ES:[IFS_DOS_CALL],SI ;IFS. ;AN000;
572
573 MOV DI,OFFSET DOSGROUP:SWAP_START ;IFS. ;AN000;
574 MOV CX,OFFSET DOSGROUP:SWAP_END ;IFS. ;AN000;
575 MOV DX,OFFSET DOSGroup:Swap_Always ;IFS. ;AN000;
576 MOV BP,CX ;IFS. ;AN000;
577 SUB BP,DI ;IFS. ;AN000;
578 SHR BP,1 ;IFS. div by 2, remainder in carry ;AN000;
579 ADC BP,0 ;IFS. div by 2 + round up ;AN000;
580 SHL BP,1 ;IFS. round up to 2 boundary. ;AN000;
581 MOV ES:[SWAP_AREA_LEN],BP ;IFS. ;AN000;
582
583 SUB CX,DX ;IFS. ;AN000;
584 SUB DX,DI ;IFS. ;AN000;
585 SHR CX,1 ;IFS. div by 2, remainder in carry ;AN000;
586 ADC CX,0 ;IFS. div by 2 + round up ;AN000;
587 SHL CX,1 ;IFS. round up to 2 boundary. ;AN000;
588 MOV ES:[SWAP_IN_DOS_LEN],CX ;IFS. ;AN000;
589 MOV WORD PTR ES:[SWAP_ALWAYS_AREA],DI ;IFS. ;AN000;
590 MOV WORD PTR ES:[SWAP_ALWAYS_AREA+2],ES ;IFS. ;AN000;
591 OR DX,8000H ;IFS. ;AN000;
592 MOV ES:[SWAP_ALWAYS_AREA_LEN],DX ;IFS. ;AN000;
593 MOV DI,OFFSET DOSGroup:Swap_Always ;IFS. ;AN000;
594 MOV WORD PTR ES:[SWAP_IN_DOS],DI ;IFS. ;AN000;
595 MOV WORD PTR ES:[SWAP_IN_DOS+2],ES ;IFS. ;AN000;
596
597
598
599;F.C Modification end DOS 3.3
600
601; Move the FATs into position
602 POP DX ; Restore COMMAND address
603 POP BP
604 POP CX ; True address of free memory
605 MOV SI,OFFSET DOSGROUP:MEMSTRT ; Place to move DPBs from
606 MOV DI,WORD PTR [DPBHEAD] ; Place to move DPBs to
607 SUB CX,DI ; Total length of DPBs
608 CMP DI,SI
609 JBE MOVJMP ; Are we moving to higher or lower memory?
610 DEC CX ; Move backwards to higher memory
611 ADD DI,CX
612 ADD SI,CX
613 INC CX
614 STD
615MOVJMP:
616 MOV ES,BP
617ASSUME ES:DOSGROUP
618 JMP MOVDPB
619
620CHARINIT:
621ASSUME DS:NOTHING,ES:NOTHING
622; DS:SI Points to device header
623 MOV [DEVCALL.REQLEN],DINITHL
624 MOV [DEVCALL.REQUNIT],0
625 MOV [DEVCALL.REQFUNC],DEVINIT
626 MOV [DEVCALL.REQSTAT],0
627 PUSH ES
628 PUSH BX
629 PUSH AX
630 MOV BX,OFFSET DOSGROUP:DEVCALL
631 PUSH CS
632 POP ES
633 invoke DEVIOCALL2
634 POP AX
635 POP BX
636 POP ES
637 RET
638
639Public MSINI002S,MSINI002E
640MSINI002S label byte
641
642 DB 100H DUP(?)
643INITSTACK LABEL BYTE
644 DW ?
645 DB "ADD SPECIAL ENTRIES",0 ;AN007 tiltle
646;The following entries don't expect version 4.0
647;The entry format: name_length, name, expected version, fake count
648;fake_count: ff means the version will be reset when Abort or Exec is encountered
649; n means the version will be reset after n DOS version calls are issued
650;
651Version_Fake_Table: ;AN007 starting address for special
652 DB 12,"IBMCACHE.COM",3,40,255 ;AN007 ibmcache 1
653 DB 12,"IBMCACHE.SYS",3,40,255 ;AN007 ibmcache 2
654 DB 12,"DXMA0MOD.SYS",3,40,255 ;AN007 lan support 3
655 DB 10,"WIN200.BIN" ,3,40,4 ;AN008 windows 4
656 DB 9,"PSCPG.COM" ,3,40,255 ;AN008 vittoria 5
657 DB 11,"DCJSS02.EXE" ,3,40,255 ;AN008 netview 6
658 DB 8,"ISAM.EXE" ,3,40,255 ;AN008 basic 7
659 DB 9,"ISAM2.EXE" ,3,40,255 ;AN008 basic 8
660 DB 12,"DFIA0MOD.SYS",3,40,255 ;AN008 lan support 9
661 DB 20 dup(0) ;AN007
662
663MEMSTRT LABEL WORD
664MSINI002E label byte
665ADJFAC EQU MEMSTRT-SYSBUF
666
667LAST ENDS
diff --git a/v4.0/src/DOS/MSIOCTL.ASM b/v4.0/src/DOS/MSIOCTL.ASM
new file mode 100644
index 0000000..2117f41
--- /dev/null
+++ b/v4.0/src/DOS/MSIOCTL.ASM
@@ -0,0 +1,5 @@
1; SCCSID = @(#)IBMIOCTL.INC 1.1 85/04/10
2IBM EQU 0FFFFH ;TRUE
3
4INCLUDE IOCTL.INC
5 SCCSID = @(#)IBMIOCTL.INC 1.1 85/04/10
diff --git a/v4.0/src/DOS/MSPROC.ASM b/v4.0/src/DOS/MSPROC.ASM
new file mode 100644
index 0000000..542874f
--- /dev/null
+++ b/v4.0/src/DOS/MSPROC.ASM
@@ -0,0 +1,15 @@
1; SCCSID = @(#)ibmproc.asm 1.1 85/04/10
2;
3; Pseudo EXEC system call for DOS
4;
5
6.xlist
7.xcref
8include mssw.asm
9.cref
10.list
11
12TITLE IBMPROC - process maintenance
13NAME IBMPROC
14
15include proc.asm
diff --git a/v4.0/src/DOS/MSSW.ASM b/v4.0/src/DOS/MSSW.ASM
new file mode 100644
index 0000000..db8eb11
--- /dev/null
+++ b/v4.0/src/DOS/MSSW.ASM
@@ -0,0 +1,27 @@
1; SCCSID = @(#)ibmsw.asm 1.1 85/04/10
2
3include version.inc
4
5IBM EQU ibmver
6WANG EQU FALSE
7
8; Set this switch to cause DOS to move itself to the end of memory
9HIGHMEM EQU FALSE
10
11; Turn on switch below to allow testing disk code with DEBUG. It sets
12; up a different stack for disk I/O (functions > 11) than that used for
13; character I/O which effectively makes the DOS re-entrant.
14
15 IF IBM
16ESCCH EQU 0 ; character to begin escape seq.
17CANCEL EQU 27 ;Cancel with escape
18TOGLPRN EQU TRUE ;One key toggles printer echo
19ZEROEXT EQU TRUE
20 ELSE
21ESCCH EQU 1BH
22CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
23TOGLPRN EQU FALSE ;Separate keys for printer echo on
24 ;and off
25ZEROEXT EQU TRUE
26 ENDIF
27 \ No newline at end of file
diff --git a/v4.0/src/DOS/MS_CODE.ASM b/v4.0/src/DOS/MS_CODE.ASM
new file mode 100644
index 0000000..1bdd4af
--- /dev/null
+++ b/v4.0/src/DOS/MS_CODE.ASM
@@ -0,0 +1,614 @@
1; SCCSID = @(#)mscode.asm 1.2 85/07/23
2;
3; MSCODE.ASM -- MSDOS code
4;
5
6.xlist
7.xcref
8include dossym.inc
9include devsym.inc
10include dosseg.asm
11include ifssym.inc
12include fastopen.inc
13include fastxxxx.inc
14.cref
15.list
16
17AsmVars <Kanji, Debug>
18
19CODE SEGMENT BYTE PUBLIC 'CODE'
20
21ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
22
23 I_need InDos,BYTE ; TRUE => we are in dos, no interrupt
24 I_need OpenBuf,128 ; temp name buffer
25 I_need ExtErr,WORD ; extended error code
26 I_need User_SS,WORD ; stack segment from user
27 I_need User_SP,WORD ; stack pointer from user
28 I_need DskStack,BYTE ; stack segment inside DOS
29 I_need ThisCDS,DWORD ; Currently referenced CDS pointer
30 I_need ThisDPB,DWORD ; Currently referenced DPB pointer
31 I_need Err_Table_21 ; allowed return map table for errors
32 I_need FailErr,BYTE ; TRUE => system call is being failed
33 I_need ExtErr_Action,BYTE ; recommended action
34 I_need ExtErr_Class,BYTE ; error classification
35 I_need ExtErr_Locus,BYTE ; error location
36 I_need I21_Map_E_Tab,BYTE ; mapping extended error table
37 I_need User_In_AX,WORD ; initial input user AX
38 I_need FOO,WORD ; return address for dos 2f dispatch
39 I_need DTAB,WORD ; dos 2f dispatch table
40 I_need HIGH_SECTOR,WORD ; >32mb
41 I_need IFS_DRIVER_ERR,WORD ; >32mb
42 I_need FastOpenFlg,BYTE ;
43 I_need FastSeekFlg,BYTE ;
44 I_need CURSC_DRIVE,BYTE ;
45
46BREAK <NullDev -- Driver for null device>
47
48procedure SNULDEV,FAR
49ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
50 OR ES:[BX.REQSTAT],STDON ; Set done bit
51entry INULDEV
52 RET ; MUST NOT BE A RETURN!
53EndProc SNULDEV
54
55BREAK <AbsDRD, AbsDWRT -- INT int_disk_read, int_disk_write handlers>
56
57
58TABLE SEGMENT
59Public MSC001S,MSC001E
60MSC001S label byte
61 IF IBM
62; Codes returned by BIOS
63ERRIN:
64 DB 2 ; NO RESPONSE
65 DB 6 ; SEEK FAILURE
66 DB 12 ; GENERAL ERROR
67 DB 4 ; BAD CRC
68 DB 8 ; SECTOR NOT FOUND
69 DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK
70ERROUT:
71; DISK ERRORS RETURNED FROM INT 25 and 26
72 DB 80H ; NO RESPONSE
73 DB 40H ; Seek failure
74 DB 2 ; Address Mark not found
75 DB 10H ; BAD CRC
76 DB 4 ; SECTOR NOT FOUND
77 DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK
78
79NUMERR EQU $-ERROUT
80 ENDIF
81MSC001E label byte
82
83TABLE ENDS
84
85; AbsSetup - setup for abs disk functions
86
87Procedure AbsSetup,NEAR
88 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
89 INC INDOS
90 STI
91 CLD
92 PUSH DS
93 Context DS
94 CALL GETBP
95 JC errdriv ;PM. error drive ;AN000;
96 MOV ES:[BP.dpb_free_cnt],-1 ; do not trust user at all.
97errdriv:
98 POP DS
99ASSUME DS:NOTHING
100 retc
101
102 MOV [HIGH_SECTOR],0 ;>32mb from API ;AN000;
103 CALL RW32_CONVERT ;>32mb convert 32bit format to 16bit ;AN000;
104 retc
105
106 invoke SET_RQ_SC_PARMS ;LB. set up SC parms ;AN000;
107 PUSH DS
108 PUSH SI
109 PUSH AX
110 Context DS
111 MOV SI,OFFSET DOSGROUP:OPENBUF
112 MOV [SI],AL
113 ADD BYTE PTR [SI],"A"
114 MOV WORD PTR [SI+1],003AH ; ":",0
115 MOV AX,0300H
116 CLC
117 INT int_IBM ; Will set carry if shared
118 POP AX
119 POP SI
120 POP DS
121ASSUME DS:NOTHING
122 retnc
123 MOV ExtErr,error_not_supported
124 return
125EndProc AbsSetup
126
127; Interrupt 25 handler. Performs absolute disk read.
128; Inputs: AL - 0-based drive number
129; DS:BX point to destination buffer
130; CX number of logical sectors to read
131; DX starting logical sector number (0-based)
132; Outputs: Original flags still on stack
133; Carry set
134; AH error from BIOS
135; AL same as low byte of DI from INT 24
136
137 procedure ABSDRD,FAR
138 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
139
140 CLI
141 MOV [user_SS],SS
142 MOV [user_SP],SP
143 PUSH CS
144 POP SS
145ASSUME SS:DOSGROUP
146 MOV SP,OFFSET DOSGROUP:DSKSTACK
147 invoke Save_World ;>32mb save all regs ;AN000;
148 PUSH ES
149 CALL AbsSetup
150 JC ILEAVE
151if not ibmcopyright
152; Here is a gross temporary fix to get around a serious design flaw in
153; the secondary cache. The secondary cache does not check for media
154; changed (it should). Hence, you can change disks, do an absolute
155; read, and get data from the previous disk. To get around this,
156; we just won't use the secondary cache for absolute disk reads.
157; -mw 8/5/88
158 EnterCrit critDisk
159 MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000;
160 LeaveCrit critDisk
161endif
162 invoke DSKREAD
163TLEAVE:
164 JZ ILEAVE
165
166 IF IBM
167; Translate the error code to ancient 1.1 codes
168 PUSH ES
169 PUSH CS
170 POP ES
171 XOR AH,AH ; Nul error code
172 MOV CX,NUMERR ; Number of possible error conditions
173 MOV DI,OFFSET DOSGROUP:ERRIN ; Point to error conditions
174 REPNE SCASB
175 JNZ LEAVECODE ; Not found
176 MOV AH,ES:[DI+NUMERR-1] ; Get translation
177LEAVECODE:
178 POP ES
179 ENDIF
180 MOV [IFS_DRIVER_ERR],AX ;>32mb save error
181 STC
182ILEAVE:
183 POP ES
184 invoke Restore_World ;>32mb ;AN000;
185 CLI
186 DEC INDOS
187 MOV SS,[user_SS]
188ASSUME SS:NOTHING
189 MOV SP,[user_SP]
190 MOV AX,[IFS_DRIVER_ERR] ;>32mb restore error ;AN000;
191 STI
192 RET ; This must not be a RETURN!
193EndProc ABSDRD
194
195; Interrupt 26 handler. Performs absolute disk write.
196; Inputs: AL - 0-based drive number
197; DS:BX point to source buffer
198; CX number of logical sectors to write
199; DX starting logical sector number (0-based)
200; Outputs: Original flags still on stack
201; Carry set
202; AH error from BIOS
203; AL same as low byte of DI from INT 24
204
205 procedure ABSDWRT,FAR
206ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
207
208 CLI
209 MOV [user_SS],SS
210 MOV [user_SP],SP
211 PUSH CS
212 POP SS
213ASSUME SS:DOSGROUP
214 MOV SP,OFFSET DOSGROUP:DSKSTACK
215 invoke Save_World ;>32mb save all regs ;AN000;
216
217 PUSH ES
218 CALL AbsSetup
219 JC ILEAVE
220
221 EnterCrit critDisk
222 MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000;
223 CALL Fastxxx_Purge ; purge fatopen ;AN000;
224 LeaveCrit critDisk
225
226 invoke DSKWRITE
227 JMP TLEAVE
228EndProc ABSDWRT
229
230; Inputs:
231; AL = Logical unit number (A = 0)
232; Function:
233; Find Drive Parameter Block
234; Outputs:
235; ES:BP points to DPB
236; [THISDPB] = ES:BP
237; Carry set if unit number bad or unit is a NET device.
238; Later case sets extended error error_I24_not_supported
239; No other registers altered
240
241Procedure GETBP,NEAR
242 DOSAssume CS,<DS>,"GetBP"
243 ASSUME ES:NOTHING
244
245 PUSH AX
246 ADD AL,1 ; No increment; need carry flag
247 JC SkipGet
248 invoke GetThisDrv
249 JNC SkipGet ;PM. good drive ;AN000;
250 XOR AH,AH ;DCR. ax= error code ;AN000;
251 CMP AX,error_not_dos_disk ;DCR. is unknown media ? ;AN000;
252 JZ SkipGet ;DCR. yes, let it go ;AN000;
253 STC ;DCR. ;AN000;
254 MOV ExtErr,AX ;PM. invalid drive or Non DOS drive ;AN000;
255 MOV [IFS_DRIVER_ERR],0201H ;PM. other errors/unknown unit ;AN000;
256SkipGet:
257 POP AX
258 retc
259 LES BP,[THISCDS]
260 TEST ES:[BP.curdir_flags],curdir_isnet ; Clears carry
261 JZ GETBP_CDS
262 LES BP,ES:[BP.curdir_ifs_hdr] ;IFS. if remote file ;AN000;
263 TEST ES:[BP.ifs_attribute],IFSREMOTE ;IFS. ;AN000;
264 LES BP,[THISCDS]
265 JZ GETBP_CDS ;IFS. then error ;AN000;
266 MOV ExtErr,error_not_supported
267 STC
268 return
269
270GETBP_CDS:
271 LES BP,ES:[BP.curdir_devptr]
272
273 entry GOTDPB
274 DOSAssume CS,<DS>,"GotDPB"
275; Load THISDPB from ES:BP
276
277 MOV WORD PTR [THISDPB],BP
278 MOV WORD PTR [THISDPB+2],ES
279 return
280EndProc GetBP
281
282BREAK <SYS_RET_OK SYS_RET_ERR CAL_LK ETAB_LK set system call returns>
283
284ASSUME SS:DOSGROUP
285
286;
287; These are the general system call exit mechanisms. All internal system
288; calls will transfer (jump) to one of these at the end. Their sole purpose
289; is to set the user's flags and set his AX register for return.
290;
291
292procedure SYS_RETURN,NEAR
293 ASSUME DS:NOTHING,ES:NOTHING
294entry SYS_RET_OK
295 invoke FETCHI_CHECK ; TAG checking for FETCHI
296 invoke get_user_stack
297 AND [SI.user_F],NOT f_Carry ; turn off user's carry flag
298 JMP SHORT DO_RET ; carry is now clear
299
300entry SYS_RET_ERR
301 XOR AH,AH ; hack to allow for smaller error rets
302 invoke ETAB_LK ; Make sure code is OK, EXTERR gets set
303 CALL ErrorMap
304entry From_GetSet
305 invoke get_user_stack
306 OR [SI.user_F],f_Carry ; signal carry to user
307 STC ; also, signal internal error
308DO_RET:
309 MOV [SI.user_AX],AX ; Really only sets AH
310 return
311
312 entry FCB_RET_OK
313 entry CPMFunc
314 XOR AL,AL
315 return
316
317 entry FCB_RET_ERR
318 XOR AH,AH
319 mov exterr,AX
320 CALL ErrorMap
321 MOV AL,-1
322 return
323
324 entry errorMap
325 PUSH SI
326 MOV SI,OFFSET DOSGROUP:ERR_TABLE_21
327 CMP [FAILERR],0 ; Check for SPECIAL case.
328 JZ EXTENDED_NORMAL ; All is OK.
329 MOV [EXTERR],error_FAIL_I24 ; Ooops, this is the REAL reason
330 MOV SI,OFFSET DOSGROUP:ERR_TABLE_21
331EXTENDED_NORMAL:
332 invoke CAL_LK ; Set CLASS,ACTION,LOCUS for EXTERR
333 POP SI
334 return
335
336EndProc SYS_RETURN
337
338; Inputs:
339; SI is OFFSET in DOSGROUP of CLASS,ACTION,LOCUS Table to use
340; (DS NEED not be DOSGROUP)
341; [EXTERR] is set with error
342; Function:
343; Look up and set CLASS ACTION and LOCUS values for GetExtendedError
344; Outputs:
345; [EXTERR_CLASS] set
346; [EXTERR_ACTION] set
347; [EXTERR_LOCUS] set (EXCEPT on certain errors as determined by table)
348; Destroys SI, FLAGS
349
350 procedure CAL_LK,NEAR
351ASSUME DS:NOTHING,ES:NOTHING
352
353 PUSH DS
354 PUSH AX
355 PUSH BX
356 Context DS ; DS:SI -> Table
357 MOV BX,[EXTERR] ; Get error in BL
358TABLK1:
359 LODSB
360 CMP AL,0FFH
361 JZ GOT_VALS ; End of table
362 CMP AL,BL
363 JZ GOT_VALS ; Got entry
364 ADD SI,3 ; Next table entry
365 JMP TABLK1
366
367GOT_VALS:
368 LODSW ; AL is CLASS, AH is ACTION
369 CMP AH,0FFH
370 JZ NO_SET_ACT
371 MOV [EXTERR_ACTION],AH ; Set ACTION
372NO_SET_ACT:
373 CMP AL,0FFH
374 JZ NO_SET_CLS
375 MOV [EXTERR_CLASS],AL ; Set CLASS
376NO_SET_CLS:
377 LODSB ; Get LOCUS
378 CMP AL,0FFH
379 JZ NO_SET_LOC
380 MOV [EXTERR_LOCUS],AL
381NO_SET_LOC:
382 POP BX
383 POP AX
384 POP DS
385 return
386EndProc CAL_LK
387
388; Inputs:
389; AX is error code
390; [USER_IN_AX] has AH value of system call involved
391; Function:
392; Make sure error code is appropriate to this call.
393; Outputs:
394; AX MAY be mapped error code
395; [EXTERR] = Input AX
396; Destroys ONLY AX and FLAGS
397
398 procedure ETAB_LK,NEAR
399ASSUME DS:NOTHING,ES:NOTHING
400
401 PUSH DS
402 PUSH SI
403 PUSH CX
404 PUSH BX
405 Context DS
406 MOV [EXTERR],AX ; Set EXTERR with "real" error
407 MOV SI,OFFSET DOSGROUP:I21_MAP_E_TAB
408 MOV BH,AL ; Real code to BH
409 MOV BL,BYTE PTR [USER_IN_AX + 1] ; Sys call to BL
410TABLK2:
411 LODSW
412 CMP AL,0FFH ; End of table?
413 JZ NOT_IN_TABLE ; Yes
414 CMP AL,BL ; Found call?
415 JZ GOT_CALL ; Yes
416 XCHG AH,AL ; Count to AL
417 XOR AH,AH ; Make word for add
418 ADD SI,AX ; Next table entry
419 JMP TABLK2
420
421NOT_IN_TABLE:
422 MOV AL,BH ; Restore original code
423 JMP SHORT NO_MAP
424
425GOT_CALL:
426 MOV CL,AH
427 XOR CH,CH ; Count of valid err codes to CX
428CHECK_CODE:
429 LODSB
430 CMP AL,BH ; Code OK?
431 JZ NO_MAP ; Yes
432 LOOP CHECK_CODE
433NO_MAP:
434 XOR AH,AH ; AX is now valid code
435 POP BX
436 POP CX
437 POP SI
438 POP DS
439 return
440
441EndProc ETAB_LK
442
443BREAK <DOS 2F Handler and default NET 2F handler>
444
445IF installed
446
447;
448; SetBad sets up info for bad functions
449;
450Procedure SetBad,NEAR
451 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
452 MOV AX,error_invalid_function ; ALL NET REQUESTS get inv func
453 MOV ExtErr_LOCUS,errLoc_UNK
454 STC
455 ret
456EndProc SetBad
457;
458; BadCall is the initial routine for bad function calls
459;
460procedure BadCall,FAR
461 call SetBad
462 ret
463EndProc BadCall
464;
465; OKCall always sets carry to off.
466;
467Procedure OKCall,FAR
468 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
469 CLC
470 ret
471EndProc OKCall
472
473; INT 2F handler works as follows:
474; PUSH AX
475; MOV AX,multiplex:function
476; INT 2F
477; POP ...
478; The handler itself needs to make the AX available for the various routines.
479
480PUBLIC Int2F
481INT2F PROC FAR
482
483INT2FNT:
484 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
485 STI
486 CMP AH,multNET
487 JNZ INT2FSHR
488TestInstall:
489 OR AL,AL
490 JZ Leave2F
491BadFunc:
492 CALL SetBad
493 entry Leave2F
494 RET 2 ; long return + clear flags off stack
495
496INT2FSHR:
497 CMP AH,multSHARE ; is this a share request
498 JZ TestInstall ; yes, check for installation
499
500INT2FNLS:
501 CMP AH,NLSFUNC ; is this a DOS 3.3 NLSFUNC request
502 JZ TestInstall ; yes check for installation
503
504INT2FDOS:
505 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
506 CMP AH,multDOS
507 JZ DispatchDOS
508 IRET ; This assume that we are at the head
509 ; of the list
510INT2F ENDP
511
512DispatchDOS:
513 PUSH FOO ; push return address
514 PUSH DTab ; push table address
515 PUSH AX ; push index
516 PUSH BP
517 MOV BP,SP
518; stack looks like:
519; 0 BP
520; 2 DISPATCH
521; 4 TABLE
522; 6 RETURN
523; 8 LONG-RETURN
524; c FLAGS
525; e AX
526
527 MOV AX,[BP+0Eh] ; get AX value
528 POP BP
529 Invoke TableDispatch
530 JMP BadFunc ; return indicates invalid function
531
532Procedure INT2F_etcetera,NEAR
533 entry DosGetGroup
534 PUSH CS
535 POP DS
536 return
537
538 entry DOSInstall
539 MOV AL,0FFh
540 return
541EndProc INT2F_etcetera
542
543ENDIF
544;Input: same as ABSDRD and ABSDWRT
545; ES:BP -> DPB
546;Functions: convert 32bit absolute RW input parms to 16bit input parms
547;Output: carry set when CX=-1 and drive is less then 32mb
548; carry clear, parms ok
549;
550Procedure RW32_CONVERT,NEAR
551 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
552 CMP CX,-1 ;>32mb new format ? ;AN000;
553 JZ new32format ;>32mb yes ;AN000;
554 PUSH AX ;>32mb save ax ;AN000;
555 PUSH DX ;>32mb save dx ;AN000;
556 MOV AX,ES:[BP.dpb_max_cluster] ;>32mb get max cluster # ;AN000;
557 MOV DL,ES:[BP.dpb_cluster_mask] ;>32mb ;AN000;
558 CMP DL,0FEH ;>32mb removable ? ;AN000;
559 JZ letold ;>32mb yes ;AN000;
560 INC DL ;>32mb ;AN000;
561 XOR DH,DH ;>32mb dx = sector/cluster ;AN000;
562 MUL DX ;>32mb dx:ax= max sector # ;AN000;
563 OR DX,DX ;>32mb > 32mb ? ;AN000;
564letold:
565 POP DX ;>32mb retore dx ;AN000;
566 POP AX ;>32mb restore ax ;AN000;
567 JZ old_style ;>32mb no ;AN000;
568 MOV [IFS_DRIVER_ERR],0207H ;>32mb error ;AN000;
569 STC ;>32mb ;AN000;
570 return ;>32mb ;AN000;
571new32format:
572 MOV DX,WORD PTR [BX.SECTOR_RBA+2];>32mb ;AN000;
573 MOV [HIGH_SECTOR],DX ;>32mb ;AN000;
574 MOV DX,WORD PTR [BX.SECTOR_RBA] ;>32mb ;AN000;
575 MOV CX,[BX.ABS_RW_COUNT] ;>32mb ;AN000;
576 LDS BX,[BX.BUFFER_ADDR] ;>32mb ;AN000;
577old_style: ;>32mb ;AN000;
578 CLC ;>32mb ;AN000;
579 return ;>32mb ;AN000;
580EndProc RW32_CONVERT
581
582
583;Input: None
584;Functions: Purge Fastopen/seek Cache Buffers
585;Output: None
586;
587;
588Procedure Fastxxx_Purge,NEAR
589 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
590 PUSH AX ; save regs. ;AN000;
591 PUSH SI ;AN000;
592 PUSH DX ;AN000;
593 TEST FastSeekflg,Fast_yes ; fastseek installed ? ;AN000;
594 JZ topen ; no ;AN000;
595 MOV AH,FastSeek_ID ; set fastseek id ;AN000;
596 JMP SHORT dofast ; ;AN000;
597topen:
598 TEST FastOpenflg,Fast_yes ; fastopen installed ? ;AN000;
599 JZ nofast ; no ;AN000;
600 MOV AH,FastOpen_ID ; set fastseek installed ;AN000;
601dofast:
602 MOV AL,FONC_purge ; purge ;AN000;
603 MOV DL,ES:[BP.dpb_drive] ; set up drive number ;AN000;
604 invoke Fast_Dispatch ; call fastopen/seek ;AN000;
605nofast:
606 POP DX ;AN000;
607 POP SI ; restore regs ;AN000;
608 POP AX ; ;AN000;
609
610 return ; exit ;AN000;
611EndProc Fastxxx_Purge
612
613CODE ENDS
614 \ No newline at end of file
diff --git a/v4.0/src/DOS/MS_TABLE.ASM b/v4.0/src/DOS/MS_TABLE.ASM
new file mode 100644
index 0000000..b5ffac7
--- /dev/null
+++ b/v4.0/src/DOS/MS_TABLE.ASM
@@ -0,0 +1,710 @@
1; SCCSID = @(#)mstable.asm 1.3 85/07/25
2; Revision history:
3; A000 version 4.0 Jan. 1988
4; A001 DCR 486 - Share installation for >32mb drives
5; A006 DCR 503 - fake version for IBMCACHE
6; A008 PTM 4070 - fake version for MS WINDOWS
7.xlist
8.xcref
9include dosseg.asm
10include EA.inc ;AN000;; for Extended Attributes
11include fastopen.inc ;AN000;; for Extended Attributes
12include dossym.inc
13.cref
14.list
15
16 AsmVars <Kanji, Debug, Redirector, ShareF>
17
18TABLE SEGMENT BYTE PUBLIC 'TABLE'
19TableZero LABEL BYTE
20
21 PUBLIC MSVERS
22PUBLIC MSTAB001s,MSTAB001e
23MSTAB001S label byte
24
25MSVERS EQU THIS WORD ; MS-DOS version in hex for $GET_VERSION
26MSMAJOR DB MAJOR_VERSION
27MSMINOR DB MINOR_VERSION
28
29 I_am YRTAB,8,<200,166,200,165,200,165,200,165> ; [SYSTEM]
30 I_am MONTAB,12,<31,28,31,30,31,30,31,31,30,31,30,31> ; [SYSTEM]
31
32;
33; This is the error code mapping table for INT 21 errors. This table defines
34; those error codes which are "allowed" for each system call. If the error
35; code ABOUT to be returned is not "allowed" for the call, the correct action
36; is to return the "real" error via Extended error, and one of the allowed
37; errors on the actual call.
38;
39; The table is organized as follows:
40;
41; Each entry in the table is of variable size, but the first
42; two bytes are always:
43;
44; Call#,Cnt of bytes following this byte
45;
46; EXAMPLE:
47; Call 61 (OPEN)
48;
49; DB 61,5,12,3,2,4,5
50;
51; 61 is the AH INT 21 call value for OPEN.
52; 5 indicates that there are 5 bytes after this byte (12,3,2,4,5).
53; Next five bytes are those error codes which are "allowed" on OPEN.
54; The order of these values is not important EXCEPT FOR THE LAST ONE (in
55; this case 5). The last value will be the one returned on the call if
56; the "real" error is not one of the allowed ones.
57;
58; There are a number of calls (for instance all of the FCB calls) for which
59; there is NO entry. This means that NO error codes are returned on this
60; call, so set up an Extended error and leave the current error code alone.
61;
62; The table is terminated by a call value of 0FFh
63
64PUBLIC I21_MAP_E_TAB
65I21_MAP_E_TAB LABEL BYTE
66 DB International,2,error_invalid_function,error_file_not_found
67 DB MKDir,3,error_path_not_found,error_file_not_found,error_access_denied
68 DB RMDir,4,error_current_directory,error_path_not_found
69 DB error_file_not_found,error_access_denied
70 DB CHDir,2,error_file_not_found,error_path_not_found
71 DB Creat,4,error_path_not_found,error_file_not_found
72 DB error_too_many_open_files
73 DB error_access_denied
74 DB Open,6,error_path_not_found,error_file_not_found,error_invalid_access
75 DB error_too_many_open_files
76 DB error_not_dos_disk,error_access_denied
77 DB Close,1,error_invalid_handle
78 DB Read,2,error_invalid_handle,error_access_denied
79 DB Write,2,error_invalid_handle,error_access_denied
80 DB Unlink,3,error_path_not_found,error_file_not_found,error_access_denied
81 DB LSeek,2,error_invalid_handle,error_invalid_function
82 DB CHMod,4,error_path_not_found,error_file_not_found,error_invalid_function
83 DB error_access_denied
84 DB IOCtl,5,error_invalid_drive,error_invalid_data,error_invalid_function
85 DB error_invalid_handle,error_access_denied
86 DB XDup,2,error_invalid_handle,error_too_many_open_files
87 DB XDup2,2,error_invalid_handle,error_too_many_open_files
88 DB Current_Dir,2,error_not_DOS_disk,error_invalid_drive
89 DB Alloc,2,error_arena_trashed,error_not_enough_memory
90 DB Dealloc,2,error_arena_trashed,error_invalid_block
91 DB Setblock,3,error_arena_trashed,error_invalid_block,error_not_enough_memory
92 DB Exec,8,error_path_not_found,error_invalid_function,error_file_not_found
93 DB error_too_many_open_files,error_bad_format,error_bad_environment
94 DB error_not_enough_memory,error_access_denied
95 DB Find_First,3,error_path_not_found,error_file_not_found,error_no_more_files
96 DB Find_Next,1,error_no_more_files
97 DB Rename,5,error_not_same_device,error_path_not_found,error_file_not_found
98 DB error_current_directory,error_access_denied
99 DB File_Times,4,error_invalid_handle,error_not_enough_memory
100 DB error_invalid_data,error_invalid_function
101 DB AllocOper,1,error_invalid_function
102 DB CreateTempFile,4,error_path_not_found,error_file_not_found
103 DB error_too_many_open_files,error_access_denied
104 DB CreateNewFile,5,error_file_exists,error_path_not_found
105 DB error_file_not_found,error_too_many_open_files,error_access_denied
106 DB LockOper,4,error_invalid_handle,error_invalid_function
107 DB error_sharing_buffer_exceeded,error_lock_violation
108 DB GetExtCntry,2,error_invalid_function,error_file_not_found ;DOS 3.3
109 DB GetSetCdPg,2,error_invalid_function,error_file_not_found ;DOS 3.3
110 DB Commit,1,error_invalid_handle ;DOS 3.3
111 DB ExtHandle,3,error_too_many_open_files,error_not_enough_memory
112 DB error_invalid_function
113 DB ExtOpen,10
114 DB error_path_not_found,error_file_not_found,error_invalid_access
115 DB error_too_many_open_files,error_file_exists,error_not_enough_memory
116 DB error_not_dos_disk,error_invalid_data
117 DB error_invalid_function,error_access_denied
118 DB GetSetMediaID,4,error_invalid_drive,error_invalid_data
119 DB error_invalid_function,error_access_denied
120 DB 0FFh
121
122;
123; The following table defines CLASS ACTION and LOCUS info for the INT 21H
124; errors. Each entry is 4 bytes long:
125;
126; Err#,Class,Action,Locus
127;
128; A value of 0FFh indicates a call specific value (ie. should already
129; be set). AN ERROR CODE NOT IN THE TABLE FALLS THROUGH TO THE CATCH ALL AT
130; THE END, IT IS ASSUMES THAT CLASS, ACTION, LOCUS IS ALREADY SET.
131ErrTab Macro err,class,action,locus
132ifidn <locus>,<0FFh>
133 DB error_&err,errCLASS_&class,errACT_&action,0FFh
134ELSE
135 DB error_&err,errCLASS_&class,errACT_&action,errLOC_&locus
136ENDIF
137ENDM
138
139PUBLIC ERR_TABLE_21
140ERR_TABLE_21 LABEL BYTE
141 ErrTab invalid_function, Apperr, Abort, 0FFh
142 ErrTab file_not_found, NotFnd, User, Disk
143 ErrTab path_not_found, NotFnd, User, Disk
144 ErrTab too_many_open_files, OutRes, Abort, Unk
145 ErrTab access_denied, Auth, User, 0FFh
146 ErrTab invalid_handle, Apperr, Abort, Unk
147 ErrTab arena_trashed, Apperr, Panic, Mem
148 ErrTab not_enough_memory, OutRes, Abort, Mem
149 ErrTab invalid_block, Apperr, Abort, Mem
150 ErrTab bad_environment, Apperr, Abort, Mem
151 ErrTab bad_format, BadFmt, User, Unk
152 ErrTab invalid_access, Apperr, Abort, Unk
153 ErrTab invalid_data, BadFmt, Abort, Unk
154 ErrTab invalid_drive, NotFnd, User, Disk
155 ErrTab current_directory, Auth, User, Disk
156 ErrTab not_same_device, Unk, User, Disk
157 ErrTab no_more_files, NotFnd, User, Disk
158 ErrTab file_exists, Already, User, Disk
159 ErrTab sharing_violation, Locked, DlyRet, Disk
160 ErrTab lock_violation, Locked, DlyRet, Disk
161 ErrTab out_of_structures, OutRes, Abort, 0FFh
162 ErrTab invalid_password, Auth, User, Unk
163 ErrTab cannot_make, OutRes, Abort, Disk
164 ErrTab Not_supported, BadFmt, User, Net
165 ErrTab Already_assigned, Already, User, Net
166 ErrTab Invalid_Parameter, BadFmt, User, Unk
167 ErrTab FAIL_I24, Unk, Abort, Unk
168 ErrTab Sharing_buffer_exceeded,OutRes, Abort, Mem
169 ErrTab Handle_EOF, OutRes, Abort, Unk ;AN000;
170 ErrTab Handle_DISK_FULL, OutRes, Abort, Unk ;AN000;
171 ErrTab sys_comp_not_loaded, Unk, Abort, Disk ;AN001;
172 DB 0FFh, 0FFH, 0FFH, 0FFh
173
174;
175; The following table defines CLASS ACTION and LOCUS info for the INT 24H
176; errors. Each entry is 4 bytes long:
177;
178; Err#,Class,Action,Locus
179;
180; A Locus value of 0FFh indicates a call specific value (ie. should already
181; be set). AN ERROR CODE NOT IN THE TABLE FALLS THROUGH TO THE CATCH ALL AT
182; THE END.
183
184PUBLIC ERR_TABLE_24
185ERR_TABLE_24 LABEL BYTE
186 ErrTab write_protect, Media, IntRet, Disk
187 ErrTab bad_unit, Intrn, Panic, Unk
188 ErrTab not_ready, HrdFail, IntRet, 0FFh
189 ErrTab bad_command, Intrn, Panic, Unk
190 ErrTab CRC, Media, Abort, Disk
191 ErrTab bad_length, Intrn, Panic, Unk
192 ErrTab Seek, HrdFail, Retry, Disk
193 ErrTab not_DOS_disk, Media, IntRet, Disk
194 ErrTab sector_not_found, Media, Abort, Disk
195 ErrTab out_of_paper, TempSit, IntRet, SerDev
196 ErrTab write_fault, HrdFail, Abort, 0FFh
197 ErrTab read_fault, HrdFail, Abort, 0FFh
198 ErrTab gen_failure, Unk, Abort, 0FFh
199 ErrTab sharing_violation, Locked, DlyRet, Disk
200 ErrTab lock_violation, Locked, DlyRet, Disk
201 ErrTab wrong_disk, Media, IntRet, Disk
202 ErrTab not_supported, BadFmt, User, Net
203 ErrTab FCB_unavailable, Apperr, Abort, Unk
204 ErrTab Sharing_buffer_exceeded,OutRes, Abort, Mem
205 DB 0FFh, errCLASS_Unk, errACT_Panic, 0FFh
206
207;
208; We need to map old int 24 errors and device driver errors into the new set
209; of errors. The following table is indexed by the new errors
210;
211Public ErrMap24
212ErrMap24 Label BYTE
213 DB error_write_protect ; 0
214 DB error_bad_unit ; 1
215 DB error_not_ready ; 2
216 DB error_bad_command ; 3
217 DB error_CRC ; 4
218 DB error_bad_length ; 5
219 DB error_Seek ; 6
220 DB error_not_DOS_disk ; 7
221 DB error_sector_not_found ; 8
222 DB error_out_of_paper ; 9
223 DB error_write_fault ; A
224 DB error_read_fault ; B
225 DB error_gen_failure ; C
226 DB error_gen_failure ; D RESERVED
227 DB error_gen_failure ; E RESERVED
228 DB error_wrong_disk ; F
229
230Public ErrMap24End
231ErrMap24End LABEL BYTE
232
233
234 PUBLIC DISPATCH,MAXCALL,MAXCOM
235
236MAXCALL DB VAL1
237MAXCOM DB VAL2
238
239; Standard Functions
240DISPATCH LABEL WORD
241 short_addr $ABORT ; 0 0
242 short_addr $STD_CON_INPUT ; 1 1
243 short_addr $STD_CON_OUTPUT ; 2 2
244 short_addr $STD_AUX_INPUT ; 3 3
245 short_addr $STD_AUX_OUTPUT ; 4 4
246 short_addr $STD_PRINTER_OUTPUT ; 5 5
247 short_addr $RAW_CON_IO ; 6 6
248 short_addr $RAW_CON_INPUT ; 7 7
249 short_addr $STD_CON_INPUT_NO_ECHO ; 8 8
250 short_addr $STD_CON_STRING_OUTPUT ; 9 9
251 short_addr $STD_CON_STRING_INPUT ; 10 A
252 short_addr $STD_CON_INPUT_STATUS ; 11 B
253 short_addr $STD_CON_INPUT_FLUSH ; 12 C
254 short_addr $DISK_RESET ; 13 D
255 short_addr $SET_DEFAULT_DRIVE ; 14 E
256 short_addr $FCB_OPEN ; 15 F
257 short_addr $FCB_CLOSE ; 16 10
258 short_addr $DIR_SEARCH_FIRST ; 17 11
259 short_addr $DIR_SEARCH_NEXT ; 18 12
260 short_addr $FCB_DELETE ; 19 13
261 short_addr $FCB_SEQ_READ ; 20 14
262 short_addr $FCB_SEQ_WRITE ; 21 15
263 short_addr $FCB_CREATE ; 22 16
264 short_addr $FCB_RENAME ; 23 17
265 short_addr CPMFUNC ; 24 18
266 short_addr $GET_DEFAULT_DRIVE ; 25 19
267 short_addr $SET_DMA ; 26 1A
268
269;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
270; C A V E A T P R O G R A M M E R ;
271; ;
272 short_addr $SLEAZEFUNC ; 27 1B
273 short_addr $SLEAZEFUNCDL ; 28 1C
274; ;
275; C A V E A T P R O G R A M M E R ;
276;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
277
278 short_addr CPMFUNC ; 29 1D
279 short_addr CPMFUNC ; 30 1E
280;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
281; C A V E A T P R O G R A M M E R ;
282; ;
283 short_addr $GET_DEFAULT_DPB ; 31 1F
284; ;
285; C A V E A T P R O G R A M M E R ;
286;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
287 short_addr CPMFUNC ; 32 20
288 short_addr $FCB_RANDOM_READ ; 33 21
289 short_addr $FCB_RANDOM_WRITE ; 34 22
290 short_addr $GET_FCB_FILE_LENGTH ; 35 23
291 short_addr $GET_FCB_POSITION ; 36 24
292VAL1 = ($-DISPATCH)/2 - 1
293
294; Extended Functions
295 short_addr $SET_INTERRUPT_VECTOR ; 37 25
296;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
297; C A V E A T P R O G R A M M E R ;
298; ;
299 short_addr $CREATE_PROCESS_DATA_BLOCK ; 38 26
300; ;
301; C A V E A T P R O G R A M M E R ;
302;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
303 short_addr $FCB_RANDOM_READ_BLOCK ; 39 27
304 short_addr $FCB_RANDOM_WRITE_BLOCK ; 40 28
305 short_addr $PARSE_FILE_DESCRIPTOR ; 41 29
306 short_addr $GET_DATE ; 42 2A
307 short_addr $SET_DATE ; 43 2B
308 short_addr $GET_TIME ; 44 2C
309 short_addr $SET_TIME ; 45 2D
310 short_addr $SET_VERIFY_ON_WRITE ; 46 2E
311
312; Extended functionality group
313 short_addr $GET_DMA ; 47 2F
314 short_addr $GET_VERSION ; 48 30
315 short_addr $Keep_Process ; 49 31
316;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
317; C A V E A T P R O G R A M M E R ;
318; ;
319 short_addr $GET_DPB ; 50 32
320; ;
321; C A V E A T P R O G R A M M E R ;
322;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
323 short_addr $SET_CTRL_C_TRAPPING ; 51 33
324 short_addr $GET_INDOS_FLAG ; 52 34
325 short_addr $GET_INTERRUPT_VECTOR ; 53 35
326 short_addr $GET_DRIVE_FREESPACE ; 54 36
327 short_addr $CHAR_OPER ; 55 37
328 short_addr $INTERNATIONAL ; 56 38
329; XENIX CALLS
330; Directory Group
331 short_addr $MKDIR ; 57 39
332 short_addr $RMDIR ; 58 3A
333 short_addr $CHDIR ; 59 3B
334; File Group
335 short_addr $CREAT ; 60 3C
336 short_addr $OPEN ; 61 3D
337 short_addr $CLOSE ; 62 3E
338 short_addr $READ ; 63 3F
339 short_addr $WRITE ; 64 40
340 short_addr $UNLINK ; 65 41
341 short_addr $LSEEK ; 66 42
342 short_addr $CHMOD ; 67 43
343 short_addr $IOCTL ; 68 44
344 short_addr $DUP ; 69 45
345 short_addr $DUP2 ; 70 46
346 short_addr $CURRENT_DIR ; 71 47
347; Memory Group
348 short_addr $ALLOC ; 72 48
349 short_addr $DEALLOC ; 73 49
350 short_addr $SETBLOCK ; 74 4A
351; Process Group
352 short_addr $EXEC ; 75 4B
353 short_addr $EXIT ; 76 4C
354 short_addr $WAIT ; 77 4D
355 short_addr $FIND_FIRST ; 78 4E
356; Special Group
357 short_addr $FIND_NEXT ; 79 4F
358; SPECIAL SYSTEM GROUP
359;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
360; C A V E A T P R O G R A M M E R ;
361; ;
362 short_addr $SET_CURRENT_PDB ; 80 50
363 short_addr $GET_CURRENT_PDB ; 81 51
364 short_addr $GET_IN_VARS ; 82 52
365 short_addr $SETDPB ; 83 53
366; ;
367; C A V E A T P R O G R A M M E R ;
368;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
369 short_addr $GET_VERIFY_ON_WRITE ; 84 54
370;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
371; C A V E A T P R O G R A M M E R ;
372; ;
373 short_addr $DUP_PDB ; 85 55
374; ;
375; C A V E A T P R O G R A M M E R ;
376;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
377 short_addr $RENAME ; 86 56
378 short_addr $FILE_TIMES ; 87 57
379 short_addr $AllocOper ; 88 58
380; Network extention system calls
381 short_addr $GetExtendedError ; 89 59
382 short_addr $CreateTempFile ; 90 5A
383 short_addr $CreateNewFile ; 91 5B
384 short_addr $LockOper ; 92 5C
385 short_addr $ServerCall ; 93 5D
386 short_addr $UserOper ; 94 5E
387 short_addr $AssignOper ; 95 5F
388 short_addr $NameTrans ; 96 60
389 short_addr CPMFunc ; 97 61
390 short_addr $Get_Current_PDB ; 98 62
391; the next call is reserved for hangool sys call
392 short_addr $ECS_Call ; 99 63
393;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
394; C A V E A T P R O G R A M M E R ;
395; ;
396 short_addr $Set_Printer_Flag ; 100 64
397; ;
398; C A V E A T P R O G R A M M E R ;
399;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
400 short_addr $GetExtCntry ; 101 65
401 short_addr $GetSetCdPg ; 102 66
402 short_addr $ExtHandle ; 103 67
403 short_addr $Commit ; 104 68
404 short_addr $GSetMediaID ; 105 69 ;AN000;
405 short_addr $Commit ; 106 6A ;AN000;
406 short_addr $IFS_IOCTL ; 107 6B ;AN000;
407 short_addr $Extended_Open ; 108 6C ;AN000;
408;
409VAL2 = ($-DISPATCH)/2 - 1
410
411
412 If Installed
413
414PUBLIC FOO
415FOO LABEL WORD
416 Short_addr Leave2F
417DTab DW OFFSET DOSGroup:DOSTable
418 PUBLIC FOO,DTAB
419
420DOSTable LABEL WORD
421 DB (DOSTableEnd-DOSTable-1)/2
422 Short_addr DOSInstall ; 0 install check
423 Short_addr DOS_CLOSE ; 1 DOS_CLOSE
424 Short_addr RECSET ; 2 RECSET
425 Short_addr DOSGetGroup ; 3 Get DOSGROUP
426 Short_addr PATHCHRCMP ; 4 PATHCHRCMP
427 Short_addr OUTT ; 5 OUT
428 Short_addr NET_I24_ENTRY ; 6 NET_I24_ENTRY
429 Short_addr PLACEBUF ; 7 PLACEBUF
430 Short_addr FREE_SFT ; 8 FREE_SFT
431 Short_addr BUFWRITE ; 9 BUFWRITE
432 Short_addr SHARE_VIOLATION ; 10 SHARE_VIOLATION
433 Short_addr SHARE_ERROR ; 11 SHARE_ERROR
434 Short_addr SET_SFT_MODE ; 12 SET_SFT_MODE
435 Short_addr DATE16 ; 13 DATE16
436 Short_addr idle ; 14 empty slot
437 Short_addr SCANPLACE ; 15 SCANPLACE
438 Short_addr idle ; 16 empty slot
439 Short_addr StrCpy ; 17 StrCpy
440 Short_addr StrLen ; 18 StrLen
441 Short_addr Ucase ; 19 Ucase
442 Short_addr POINTCOMP ; 20 POINTCOMP
443 Short_addr CHECKFLUSH ; 21 CHECKFLUSH
444 Short_addr SFFromSFN ; 22 SFFromSFN
445 Short_addr GetCDSFromDrv ; 23 GetCDSFromDrv
446 Short_addr Get_User_Stack ; 24 Get_User_Stack
447 Short_addr GetThisDrv ; 25 GetThisDrv
448 Short_addr DriveFromText ; 26 DriveFromText
449 Short_addr SETYEAR ; 27 SETYEAR
450 Short_addr DSUM ; 28 DSUM
451 Short_addr DSLIDE ; 29 DSLIDE
452 Short_addr StrCmp ; 30 StrCmp
453 Short_addr InitCDS ; 31 initcds
454 Short_addr pJFNFromHandle ; 32 pJfnFromHandle
455 Short_addr $NameTrans ; 33 $NameTrans
456 Short_addr CAL_LK ; 34 CAL_LK
457 Short_addr DEVNAME ; 35 DEVNAME
458 Short_addr Idle ; 36 Idle
459 Short_addr DStrLen ; 37 DStrLen
460 Short_addr NLS_OPEN ; 38 NLS_OPEN DOS 3.3
461 Short_addr $CLOSE ; 39 $CLOSE DOS 3.3
462 Short_addr NLS_LSEEK ; 40 NLS_LSEEK DOS 3.3
463 Short_addr $READ ; 41 $READ DOS 3.3
464 Short_addr FastInit ; 42 FastInit DOS 3.4 ;AN000;
465 Short_addr NLS_IOCTL ; 43 NLS_IOCTL DOS 3.3
466 Short_addr GetDevList ; 44 GetDevList DOS 3.3
467 Short_addr NLS_GETEXT ; 45 NLS_GETEXT DOS 3.3
468 Short_addr MSG_RETRIEVAL ; 46 MSG_RETRIEVAL DOS 4.0 ;AN000;
469 Short_addr Fake_Version ; 47 Fake_Version DOS 4.0 ;AN006;
470
471DOSTableEnd LABEL BYTE
472
473 ENDIF
474
475; NOTE WARNING: This declaration of HEADER must be THE LAST thing in this
476; module. The reason is so that the data alignments are the same in
477; IBM-DOS and MS-DOS up through header.
478;---------------------------------------Start of Korean support 2/11/KK
479;
480; The varialbes for ECS version are moved here for the same data alignments
481; as IBM-DOS and MS-DOS.
482;
483
484 I_AM InterChar, byte ; Interim character flag ( 1= interim) ;AN000;
485 ;AN000;
486;------- NOTE: NEXT TWO BYTES SOMETIMES USED AS A WORD !! ---------------------
487DUMMY LABEL WORD ;AN000;
488 PUBLIC InterCon ; Console in Interim mode ( 1= interim) ;AN000;
489InterCon db 0 ;AN000;
490 PUBLIC SaveCurFlg ; Print, do not advance cursor flag ;AN000;
491SaveCurFlg db 0 ;AN000;
492;-----------------------------------------End of Korean support 2/11/KK
493
494
495 PUBLIC HEADER
496Header LABEL BYTE
497 IF DEBUG
498 DB 13,10,"Debugging DOS version "
499 DB MAJOR_VERSION + "0"
500 DB "."
501 DB (MINOR_VERSION / 10) + "0"
502 DB (MINOR_VERSION MOD 10) + "0"
503 ENDIF
504
505 IF NOT IBM
506 DB 13,10,"MS-DOS version "
507 DB MAJOR_VERSION + "0"
508 DB "."
509 DB (MINOR_VERSION / 10) + "0"
510 DB (MINOR_VERSION MOD 10) + "0"
511
512 IF HIGHMEM
513 DB "H"
514 ENDIF
515
516 DB 13,10, "Copyright 1981,82,83,84,88 Microsoft Corp.",13,10,"$"
517 ENDIF
518
519IF DEBUG
520 DB 13,10,"$"
521ENDIF
522
523MSTAB001E label byte
524
525include copyrigh.inc ;AN000;
526
527; SYS init extended table, DOS 3.3 F.C. 5/29/86
528;
529 PUBLIC SysInitTable
530 I_need COUNTRY_CDPG,BYTE
531 I_need SYSINITVAR,BYTE
532
533SysInitTable label byte
534 dw OFFSET DOSGROUP:SYSINITVAR ; pointer to sysinit var
535 dw 0 ; segment
536 dw OFFSET DOSGROUP:COUNTRY_CDPG ; pointer to country table
537 dw 0 ; segment of pointer
538; DOS 3.3 F.C. 6/12/86
539
540; FASTOPEN communications area DOS 3.3 F.C. 5/29/86
541;
542 PUBLIC FastOpenTable
543 PUBLIC FastTable ; a better name
544 EXTRN FastRet:FAR ; defined in misc2.asm
545
546FastTable label byte ; a better name
547FastOpenTable label byte
548 dw 2 ; number of entries
549 dw OFFSET DOSGROUP:FastRet ; pointer to ret instr.
550 dw 0 ; and will be modified by
551 dw OFFSET DOSGROUP:FastRet ; FASTxxx when loaded in
552 dw 0 ;
553; DOS 3.3 F.C. 6/12/86
554 PUBLIC FastFlg ;AN000; flags
555FastFlg label byte ;AN000; don't change the following order
556 I_am FastOpenFlg,BYTE,<0> ;AN000;
557 I_am FastSeekFlg,BYTE,<0> ;AN000;
558
559 PUBLIC FastOpen_Ext_Info
560
561; FastOpen_Ext_Info is used as a temporary storage for saving dirpos,dirsec
562; and clusnum which are filled by DOS 3.3 when calling FastOpen Insert
563; or filled by FastOPen when calling FastOpen Lookup
564
565FastOpen_Ext_Info label byte
566 db SIZE FASTOPEN_EXTENDED_INFO dup(0) ;dirpos
567
568; Dir_Info_Buff is a dir entry buffer which is filled by FastOPen
569; when calling FastOpen Lookup
570
571 PUBLIC Dir_Info_Buff
572
573Dir_Info_Buff label byte
574 db SIZE dir_entry dup (0)
575
576
577 I_am Next_Element_Start,WORD ; save next element start offset
578
579; Following 4 variables moved to MSDATA.asm (P4986)
580; I_am FSeek_drive,BYTE ;AN000; fastseek drive #
581; I_am FSeek_firclus,WORD ;AN000; fastseek first cluster #
582; I_am FSeek_logclus,WORD ;AN000; fastseek logical cluster #
583; I_am FSeek_logsave,WORD ;AN000; fastseek returned log clus #
584
585; The following is a stack and its pointer for interrupt 2F which is uesd
586; by NLSFUNC. There is no significant use of this stack, we are just trying
587; not to destroy the INT 21 stack saved for the user.
588
589
590 PUBLIC User_SP_2F
591
592USER_SP_2F LABEL WORD
593 dw OFFSET DOSGROUP:FAKE_STACK_2F
594
595 PUBLIC Packet_Temp
596Packet_Temp label word ; temporary packet used by readtime
597 PUBLIC DOS_TEMP ; temporary word
598DOS_TEMP label word
599FAKE_STACK_2F dw 14 dup (0) ; 12 register temporary storage
600
601 PUBLIC Hash_Temp ;AN000; temporary word
602Hash_Temp label word ;AN000;
603 dw 4 dup (0) ;AN000; temporary hash table during config.sys
604
605 PUBLIC SCAN_FLAG ; flag to indicate key ALT_Q
606SCAN_FLAG label byte
607 db 0
608;;; The following 2 words must be adjacent for IBMDOS reasons
609
610 PUBLIC DATE_FLAG
611DATE_FLAG label word ; flag to
612 dw 0 ; to update the date
613;;;; special tag for IBMDOS
614 PUBLIC FETCHI_TAG
615FETCHI_TAG label word ; TAG to make DOS 3.3 work
616 dw 0 ; must be 22642
617;;; The above 2 words must be adjacent for IBMDOS reasons
618; DOS 3.3 F.C. 6/12/86
619 I_am Del_ExtCluster,WORD ; for dos_delete ;AN000;
620
621 PUBLIC MSG_EXTERROR ; for system message addr ;AN000;
622MSG_EXTERROR label DWORD ;AN000;
623 dd 0 ; for extended error ;AN000;
624 dd 0 ; for parser ;AN000;
625 dd 0 ; for critical errror ;AN000;
626 dd 0 ; for IFS ;AN000;
627 dd 0 ; for code reduction ;AN000;
628
629 PUBLIC SEQ_SECTOR ; last sector read ;AN000;
630SEQ_SECTOR label DWORD ;AN000;
631 dd -1 ;AN000;
632
633 I_am XA_CONDITION,BYTE,<0> ; for Extended Attributes ;AN000;
634; I_am XA_ES,WORD ; for extended find ;AN000;
635; I_am XA_BP,WORD ; for extended find ;AN000;
636; I_am XA_handle,WORD ; for get/set EA ;AN000;
637 I_am XA_type,BYTE ; for get/set EA ;AN000;
638; I_am XA_device,BYTE ; for get/set EA ;AN000;
639 I_am XA_from,BYTE ; for get/set EA ;AN000;
640; I_am XA_VAR,WORD ; for get/set EA ;AN000;
641; I_am XA_TEMP,WORD ; for get/set EA ;AN000;
642; I_am XA_TEMP2,WORD ; for get/set EA ;AN000;
643;
644
645; I_am MAX_EA_SIZE,WORD,<29> ; max EA list size ;AN000;
646; I_am MAX_EANAME_SIZE,WORD,<20> ; max EA name list size ;AN000;
647; I_am XA_COUNT,WORD,<2> ; number of EA entries ;AN000;
648
649
650; PUBLIC XA_TABLE ; for get/set EA ;AN000;
651;
652;XA_TABLE label byte ;AN000;
653; db EAISBINARY ;Code Page ;AN000;
654; dw EASYSTEM ;AN000;
655; db 0,2 ;AN000;
656; dw 2 ;AN000;
657; db 'CP' ;AN000;
658;
659; db EAISBINARY ;File Type ;AN000;
660; dw EASYSTEM ;AN000;
661; db 0,8 ;AN000;
662; dw 1 ;AN000;
663; db 'FILETYPE' ;AN000;
664;
665
666; PUBLIC XA_PACKET ;AN000;
667;XA_PACKET label byte ;AN000;
668;IF DBCS ;AN000;
669; dw 18 ;AN000;
670; db 18 dup(0) ;AN000;
671; PUBLIC DBCS_PACKET ;AN000;
672;DBCS_PACKET label byte ;AN000;
673; db 5 dup(0)
674;ELSE
675; dw 2, 0 ; get/set device code page ;AN000;
676;ENDIF
677 I_am CurHashEntry,DWORD ; current hash buffer entry ;AN000;
678;; I_am ACT_PAGE,WORD,<-1> ;BL ; active EMS page ;AN000;
679 I_am SC_SECTOR_SIZE,WORD ; sector size for SC ;AN000;
680 I_am SC_DRIVE,BYTE ; drive # for secondary cache ;AN000;
681 I_am CurSC_DRIVE,BYTE,<-1> ; current SC drive ;AN000;
682 I_am CurSC_SECTOR,DWORD ; current SC starting sector ;AN000;
683 I_am SC_STATUS,WORD,<0> ; SC status word ;AN000;
684 I_am SC_FLAG,BYTE,<0> ; SC flag ;AN000;
685 I_am IFS_DRIVER_ERR,WORD,<0> ; driver error for IFS ;AN000;
686
687 PUBLIC NO_NAME_ID ;AN000;
688NO_NAME_ID label byte ;AN000;
689 db 'NO NAME ' ; null media id ;AN000;
690
691 PUBLIC SWAP_AREA_TABLE ;AN000;
692SWAP_AREA_TABLE label byte ;AN000;
693 I_am NUM_SWAP_AREA,WORD,<2> ; number of swap areas ;AN000;
694 I_am SWAP_IN_DOS,DWORD ; swap in dos area ;AN000;
695 I_am SWAP_IN_DOS_LEN,WORD ; swap in dos area length ;AN000;
696 I_am SWAP_ALWAYS_AREA,DWORD ; swap always area ;AN000;
697 I_am SWAP_ALWAYS_AREA_LEN,WORD ; swap always area length ;AN000;
698 I_am IFSFUNC_SWAP_IN_DOS,DWORD ; ifsfunc swap in dos area ;AN000;
699 I_am IFSFUNC_SWAP_IN_DOS_LEN,WORD ; ifsfunc swap in dos area length ;AN000;
700
701 I_am SWAP_AREA_LEN,WORD ; swap area length ;AN000;
702 I_am FIRST_BUFF_ADDR,WORD ; first buffer address ;AN000;
703 I_am SPECIAL_VERSION,WORD,<0> ;AN006; used by INT 2F 47H
704 I_am FAKE_COUNT,<255> ;AN008; fake version count
705 I_am OLD_FIRSTCLUS,WORD ;AN011; save old first cluster for fastopen
706
707TABLE ENDS
708
709
710 \ No newline at end of file
diff --git a/v4.0/src/DOS/NSTDOS.ASM b/v4.0/src/DOS/NSTDOS.ASM
new file mode 100644
index 0000000..f35055f
--- /dev/null
+++ b/v4.0/src/DOS/NSTDOS.ASM
@@ -0,0 +1,7 @@
1; SCCSID = @(#)nstdos.asm 1.1 85/04/10
2TITLE MS-DOS
3NAME MSDOS_3
4
5include stdsw.asm
6include msconst.asm
7 END
diff --git a/v4.0/src/DOS/OPEN.ASM b/v4.0/src/DOS/OPEN.ASM
new file mode 100644
index 0000000..ab9b4c1
--- /dev/null
+++ b/v4.0/src/DOS/OPEN.ASM
@@ -0,0 +1,569 @@
1; SCCSID = @(#)open.asm 1.1 85/04/10
2TITLE DOS_OPEN - Internal OPEN call for MS-DOS
3NAME DOS_OPEN
4; Low level routines for openning a file from a file spec.
5; Also misc routines for sharing errors
6;
7; DOS_Open
8; Check_Access_AX
9; SHARE_ERROR
10; SET_SFT_MODE
11; Code_Page_Mismatched_Error ; DOS 4.00
12;
13; Revision history:
14;
15; Created: ARR 30 March 1983
16; A000 version 4.00 Jan. 1988
17;
18
19;
20; get the appropriate segment definitions
21;
22.xlist
23include dosseg.asm
24
25CODE SEGMENT BYTE PUBLIC 'CODE'
26 ASSUME SS:DOSGROUP,CS:DOSGROUP
27
28.xcref
29include dossym.inc
30include devsym.inc
31include fastopen.inc
32include fastxxxx.inc ;AN000;
33include ifssym.inc ;AN000;
34.cref
35.list
36
37Installed = TRUE
38
39 i_need NoSetDir,BYTE
40 i_need THISSFT,DWORD
41 i_need THISCDS,DWORD
42 i_need CURBUF,DWORD
43 i_need CurrentPDB,WORD
44 i_need CURR_DIR_END,WORD
45 I_need RetryCount,WORD
46 I_need Open_Access,BYTE
47 I_need fSharing,BYTE
48 i_need JShare,DWORD
49 I_need FastOpenFlg,byte
50 I_need EXTOPEN_ON,BYTE ;AN000;; DOS 4.00
51 I_need ALLOWED,BYTE ;AN000;; DOS 4.00
52 I_need EXTERR,WORD ;AN000;; DOS 4.00
53 I_need EXTERR_LOCUS,BYTE ;AN000;; DOS 4.00
54 I_need EXTERR_ACTION,BYTE ;AN000;; DOS 4.00
55 I_need EXTERR_CLASS,BYTE ;AN000;; DOS 4.00
56 I_need CPSWFLAG,BYTE ;AN000;; DOS 4.00
57 I_need EXITHOLD,DWORD ;AN000;; DOS 4.00
58 I_need THISDPB,DWORD ;AN000;; DOS 4.00
59 I_need SAVE_CX,WORD ;AN000;; DOS 4.00
60
61Break <DOS_Open - internal file access>
62
63; Inputs:
64; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
65; terminated)
66; [CURR_DIR_END] Points to end of Current dir part of string
67; ( = -1 if current dir not involved, else
68; Points to first char after last "/" of current dir part)
69; [THISCDS] Points to CDS being used
70; (Low word = -1 if NUL CDS (Net direct request))
71; [THISSFT] Points to SFT to fill in if file found
72; (sf_mode field set so that FCB may be detected)
73; [SATTRIB] Is attribute of search, determines what files can be found
74; AX is Access and Sharing mode
75; High NIBBLE of AL (Sharing Mode)
76; sharing_compat file is opened in compatibility mode
77; sharing_deny_none file is opened Multi reader, Multi writer
78; sharing_deny_read file is opened Only reader, Multi writer
79; sharing_deny_write file is opened Multi reader, Only writer
80; sharing_deny_both file is opened Only reader, Only writer
81; Low NIBBLE of AL (Access Mode)
82; open_for_read file is opened for reading
83; open_for_write file is opened for writing
84; open_for_both file is opened for both reading and writing.
85;
86; For FCB SFTs AL should = sharing_compat + open_for_both
87; (not checked)
88; Function:
89; Try to open the specified file
90; Outputs:
91; sf_ref_count is NOT altered
92; CARRY CLEAR
93; THISSFT filled in.
94; CARRY SET
95; AX is error code
96; error_file_not_found
97; Last element of path not found
98; error_path_not_found
99; Bad path (not in curr dir part if present)
100; error_bad_curr_dir
101; Bad path in current directory part of path
102; error_invalid_access
103; Bad sharing mode or bad access mode or bad combination
104; error_access_denied
105; Attempt to open read only file for writting, or
106; open a directory
107; error_sharing_violation
108; The sharing mode was correct but not allowed
109; generates an INT 24 on compatibility mode SFTs
110; DS preserved, others destroyed
111
112 procedure DOS_Open,NEAR
113 DOSAssume CS,<DS>,"DOS_Open"
114 ASSUME ES:NOTHING
115
116 MOV [NoSetDir],0
117 CALL Check_Access_AX
118 retc
119 LES DI,[THISSFT]
120 XOR AH,AH
121; sleaze! move only access/sharing mode in. Leave sf_isFCB unchanged
122 MOV BYTE PTR ES:[DI.sf_mode],AL ; For moment do this on FCBs too
123 PUSH ES
124 LES SI,[THISCDS]
125 CMP SI,-1
126 JNZ TEST_RE_NET
127 POP ES
128;Extended open hooks
129
130 TEST [EXTOPEN_ON],ext_open_on ;FT. from extnded open ;AN000;
131 JZ NOEXTOP ;FT. no, do normal ;AN000;
132IFS_extopen: ;AN000;
133 MOV AL,byte ptr [SAVE_CX] ;FT. al= create attribute ;AN000;
134 PUSH AX ;FT. pass create attr to IFS ;AN000;
135 MOV AX,(multNET SHL 8) OR 46 ;FT. issue extended open verb ;AN000;
136 INT 2FH ;FT. ;AN000;
137 POP BX ;FT. trash bx ;AN000;
138 MOV [EXTOPEN_ON],0 ;FT. ;AN000;
139 JNC update_size ;IFS. file may be opened ;AN000;
140 return ;FT. ;AN000;
141NOEXTOP:
142;Extended open hooks
143
144
145IF NOT Installed
146 transfer NET_SEQ_OPEN
147ELSE
148 PUSH AX
149 MOV AX,(multNET SHL 8) OR 22
150 INT 2FH
151 POP BX ; clean stack
152 return
153ENDIF
154
155TEST_RE_NET:
156 TEST ES:[SI.curdir_flags],curdir_isnet
157 POP ES
158 JZ LOCAL_OPEN
159; CALL IFS_SHARE_CHECK ;IFS. check IFS share,may create share ;AN000;
160; JC nomore ;IFS. share violation ;AN000;
161;Extended open hooks
162
163 TEST [EXTOPEN_ON],ext_open_on ;FT. from extnded open ;AN000;
164 JNZ IFS_extopen ;FT. isuue extended open ;AN000;
165;Extended open hooks
166
167IF NOT Installed
168 transfer NET_OPEN
169ELSE
170 PUSH AX
171 MOV AX,(multNET SHL 8) OR 22
172 INT 2FH
173 POP BX ; clean stack
174; JC nomore ;IFS. error ;AN000;
175update_size: ;AN000;
176; CALL OWN_SHARE ;IFS. IFS owns share ? ;AN000;
177; JZ nomore2 ;IFS. yes ;AN000;
178; MOV AX,3 ;IFS. update file size for all SFT ;AN000;
179; LES DI,ThisSFT ;IFS. ;AN000;
180; call JShare + 14 * 4 ;IFS. call ShSu ;AN000;
181nomore2:
182; CLC
183nomore:
184 return
185ENDIF
186
187LOCAL_OPEN:
188 EnterCrit critDisk
189
190; DOS 3.3 FastOPen 6/16/86
191
192 OR [FastOpenFlg],FastOpen_Set+Special_Fill_Set ; only open can
193 invoke GetPath
194
195
196; DOS 3.3 FastOPen 6/16/86
197
198 JNC Open_found
199 JNZ bad_path
200 OR CL,CL
201 JZ bad_path
202OpenFNF:
203 MOV AX,error_file_not_found
204OpenBadRet:
205 AND BYTE PTR CS:[FastOpenFlg],Fast_yes ;; DOS 3.3
206 STC
207 LeaveCrit critDisk
208 JMP Clear_FastOpen
209
210bad_path:
211 MOV AX,error_path_not_found
212 JMP OpenBadRet
213
214open_bad_access:
215 MOV AX,error_access_denied
216 JMP OpenBadRet
217
218Open_found:
219 JZ Open_Bad_Access ; test for directories
220 OR AH,AH
221 JS open_ok ; Devices don't have attributes
222 MOV ES,WORD PTR [CURBUF+2] ; get buffer location
223 MOV AL,ES:[BX].dir_attr
224 TEST AL,attr_volume_id ; can't open volume ids
225 JNZ open_bad_access
226 TEST AL,attr_read_only ; check write on read only
227 JZ open_ok
228;
229; The file is marked READ-ONLY. We verify that the open mode allows access to
230; the read-only file. Unfortunately, with FCB's and net-FCB's we cannot
231; determine at the OPEN time if such access is allowed. Thus, we defer such
232; processing until the actual write operation:
233;
234; If FCB, then we change the mode to be read_only.
235; If net_FCB, then we change the mode to be read_only.
236; If not open for read then error.
237;
238 SaveReg <DS,SI>
239 LDS SI,[THISSFT]
240 MOV CX,[SI].sf_mode
241 TEST CX,sf_isFCB ; is it FCB?
242 JNZ ResetAccess ; yes, reset the access
243 MOV DL,CL
244 AND DL,sharing_mask
245 CMP DL,sharing_net_FCB ; is it net FCB?
246 JNZ NormalOpen ; no
247ResetAccess:
248 AND CX,NOT access_mask ; clear access
249 errnz open_for_read
250; OR CX,open_for_read ; stick in open_for_read
251 MOV [SI].sf_mode,CX
252 JMP SHORT FillSFT
253;
254; The SFT is normal. See if the requested access is open_for_read
255;
256NormalOpen:
257 AND CL,access_mask ; remove extras
258 CMP CL,open_for_read ; is it open for read?
259 JZ FillSFT
260 RestoreReg <SI,DS>
261 JMP short open_bad_access
262;
263; All done, restore registers and fill the SFT.
264;
265FillSFT:
266 RestoreReg <SI,DS>
267open_ok:
268;;; File Tagging DOS 4.00
269; OR AH,AH ;FT. device ? ;AN000;
270; JS NORM0 ;FT. yes, don't do code page matching ;AN000;
271; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000;
272; JZ NORM0 ;FT. no ;AN000;
273; CMP ES:[BX].dir_CODEPG,0 ;FT. code page 0 ;AN000;
274; JZ NORM0 ;FT. yes do nothing ;AN000;
275; PUSH AX ;FT. ;AN000;
276; invoke Get_Global_CdPg ;FT. get global code page ;AN000;
277; CMP ES:[BX].dir_CODEPG,AX ;FT. equal to global code page ;AN000;
278; JZ NORM1 ;FT. yes ;AN000;
279; call Code_Page_Mismatched_Error ;FT. ;AN000;
280; CMP AL,0 ;FT. ignore ? ;AN000;
281; JZ NORM1 ;FT. ;AN000;
282; POP AX ;FT. ;AN000;
283; JMP open_bad_access ;FT. set carry and return ;AN000;
284NORM1: ;AN000;
285; POP AX ;FT. ;AN000;
286NORM0:
287
288;;; File Tagging DOS 4.00
289 invoke DOOPEN ; Fill in SFT
290 AND BYTE PTR CS:[FastOpenFlg],Fast_yes ;; DOS 3.3
291 CALL DO_SHARE_CHECK ;
292 JNC Share_Ok
293 LeaveCrit critDisk
294 JMP Clear_FastOPen
295
296SHARE_OK:
297 MOV AX,3
298 LES DI,ThisSFT
299if installed
300 call JShare + 14 * 4
301else
302 Call ShSU
303endif
304;; DOS 4.00 10/27/86
305 LES DI,ThisSFT ; if this is a newly ;AN000;
306 CMP ES:[DI.sf_firclus],0 ; created file then ;AN000;
307 JZ no_fastseek ; do nothing ;AN000;
308 MOV CX,ES:[DI.sf_firclus] ; first cluster # ;AN000;
309 LES DI,ES:[DI.sf_devptr] ; pointer to DPB ;AN000;
310 MOV DL,ES:[DI.dpb_drive] ; drive # ;AN000;
311 invoke FastSeek_Open ; call fastseek ;AN000;
312no_fastseek:
313
314;; DOS 4.00 10/27/86
315
316 LeaveCrit critDisk
317
318;
319; Finish SFT initialization for new reference. Set the correct mode.
320;
321; Inputs:
322; ThisSFT points to SFT
323;
324; Outputs:
325; Carry clear
326; Registers modified: AX.
327
328 entry SET_SFT_MODE
329 DOSAssume CS,<DS>,"Set_SFT_Mode"
330 ASSUME ES:NOTHING
331
332 LES DI,ThisSFT
333 invoke DEV_OPEN_SFT
334 TEST ES:[DI.sf_mode],sf_isfcb; Clears carry
335 retz ; sf_mode correct
336 MOV AX,[CurrentPDB]
337 MOV ES:[DI.sf_PID],AX ; For FCB sf_PID=PID
338
339Clear_FastOpen:
340 return ;;;;; DOS 3.3
341
342EndProc DOS_Open
343
344; Called on sharing violations. ES:DI points to SFT. AX has error code
345; If SFT is FCB or compatibility mode gens INT 24 error.
346; Returns carry set AX=error_sharing_violation if user says ignore (can't
347; really ignore). Carry clear
348; if user wants a retry. ES, DI, DS preserved
349
350procedure SHARE_ERROR,NEAR
351 DOSAssume CS,<DS>,"Share_Error"
352 ASSUME ES:NOTHING
353 TEST ES:[DI.sf_mode],sf_isfcb
354 JNZ HARD_ERR
355 MOV CL,BYTE PTR ES:[DI.sf_mode]
356 AND CL,sharing_mask
357 CMP CL,sharing_compat
358 JNE NO_HARD_ERR
359HARD_ERR:
360 invoke SHARE_VIOLATION
361 retnc ; User wants retry
362NO_HARD_ERR:
363 MOV AX,error_sharing_violation
364 STC
365 return
366
367EndProc SHARE_ERROR
368
369
370; Input: THISDPB, WFP_Start, THISSFT set
371; Functions: check file sharing mode is valid
372; Output: carry set, error
373; carry clear, share ok
374
375procedure DO_SHARE_CHECK,NEAR
376 DOSAssume CS,<DS>,"DO_SHARE__CHECK"
377 ASSUME ES:NOTHING
378 EnterCrit critDisk ; enter critical section
379
380OPN_RETRY:
381 MOV CX,RetryCount ; Get # tries to do
382OpenShareRetry:
383 SaveReg <CX> ; Save number left to do
384 invoke SHARE_CHECK ; Final Check
385 RestoreReg <CX> ; CX = # left
386 JNC Share_Ok2 ; No problem with access
387 Invoke Idle
388 LOOP OpenShareRetry ; One more retry used up
389OpenShareFail:
390 LES DI,[ThisSft]
391 invoke SHARE_ERROR
392 JNC OPN_RETRY ; User wants more retry
393Share_Ok2:
394 LeaveCrit critDisk ; leave critical section
395 return
396
397EndProc DO_SHARE_CHECK
398
399
400; Input: ES:DI -> SFT
401; Functions: check if IFS owns SHARE
402; Output: Zero set, use IFS SHARE
403; otherwise, use DOS SHARE
404
405procedure OWN_SHARE,NEAR ;AN000;
406 DOSAssume CS,<DS>,"OWN_SHARE" ;AN000;
407 ASSUME ES:NOTHING ;AN000;
408
409; PUSH DS ;IFS. save reg ;AN000;
410; PUSH SI ;IFS. save reg ;AN000;
411; LDS SI,ES:[DI.sf_IFS_HDR] ;IFS. ds:si-> IFS header ;AN000;
412; TEST [SI.IFS_ATTRIBUTE],IFSUSESHARE ;IFS. save reg ;AN000;
413; POP SI ;IFS. retore reg ;AN000;
414; POP DS ;IFS. restore reg ;AN000;
415 return ;IFS. return ;AN000;
416
417EndProc OWN_SHARE ;AN000;
418
419
420; Input: THISCDS -> CDS
421; Functions: check if IFS owns SHARE
422; Output: Zero set, use IFS SHARE
423; otherwise, use DOS SHARE
424
425procedure OWN_SHARE2,NEAR ;AN000;
426 DOSAssume CS,<DS>,"OWN_SHARE2" ;AN000;
427 ASSUME ES:NOTHING ;AN000;
428
429; CMP WORD PTR [THISCDS],-1 ;IFS. UNC ? ;AN000;
430; JZ ifs_hasit ;IFS. yes ;AN000;
431; PUSH DS ;IFS. save reg ;AN000;
432; PUSH SI ;IFS. save reg ;AN000;
433; LDS SI,[THISCDS] ;IFS. DS:SI -> ThisCDS ;AN000;
434; LDS SI,[SI.curdir_IFS_HDR] ;IFS. ds:si-> IFS header ;AN000;
435; TEST [SI.IFS_ATTRIBUTE],IFSUSESHARE ;IFS. ;AN000;
436; POP SI ;IFS. retore reg ;AN000;
437; POP DS ;IFS. restore reg ;AN000;
438ifs_hasit: ;AN000;
439 return ;IFS. return ;AN000;
440
441EndProc OWN_SHARE2 ;AN000;
442
443
444; Input: ES:DI -> SFT
445; Functions: set THISDPB
446; Output: none
447
448procedure SET_THISDPB,NEAR ;AN000;
449 DOSAssume CS,<DS>,"SET_THISDPB" ;AN000;
450 ASSUME ES:NOTHING ;AN000;
451
452; PUSH DS ;IFS. save reg ;AN000;
453; PUSH SI ;IFS. save reg ;AN000;
454; LDS SI,[THISCDS] ;IFS. ds:si-> CDS ;AN000;
455; LDS SI,[SI.CURDIR_DEVPTR] ;IFS. ds:si-> DPB ;AN000;
456; MOV WORD PTR [THISDPB],SI ;IFS. set THISDPB ;AN000;
457; MOV WORD PTR [THISDPB+2],DS ;IFS. ;AN000;
458; POP SI ;IFS. retore reg ;AN000;
459; POP DS ;IFS. restore reg ;AN000;
460 return ;IFS. return ;AN000;
461
462EndProc SET_THISDPB ;AN000;
463
464
465; Input: ES:DI -> SFT
466; Functions: check IFS share
467; Output: none
468
469procedure IFS_SHARE_CHECK,NEAR ;AN000;
470 DOSAssume CS,<DS>,"IFS_SHARE_CHECK" ;AN000;
471 ASSUME ES:NOTHING ;AN000;
472
473
474; CALL OWN_SHARE ;IFS. IFS owns share ;AN000;
475; JZ IFSSHARE ;IFS. yes ;AN000;
476; PUSH AX ;IFS. save mode ;AN000;
477; CALL SET_THISDPB ;IFS. set THISDPB for SHARE_VIOLATION ;AN000;
478; CALL DO_SHARE_CHECK ;IFS. check share ;AN000;
479; POP AX ;IFS. restore mode and share ok ;AN000;
480IFSSHARE: ;AN000;
481 return ;IFS. return ;AN000;
482
483EndProc IFS_SHARE_CHECK ;AN000;
484
485; Inputs:
486; AX is mode
487; High NIBBLE of AL (Sharing Mode)
488; sharing_compat file is opened in compatibility mode
489; sharing_deny_none file is opened Multi reader, Multi writer
490; sharing_deny_read file is opened Only reader, Multi writer
491; sharing_deny_write file is opened Multi reader, Only writer
492; sharing_deny_both file is opened Only reader, Only writer
493; Low NIBBLE of AL (Access Mode)
494; open_for_read file is opened for reading
495; open_for_write file is opened for writing
496; open_for_both file is opened for both reading and writing.
497; Function:
498; Check this access mode for correctness
499; Outputs:
500; [open_access] = AL input
501; Carry Clear
502; Mode is correct
503; AX unchanged
504; Carry Set
505; Mode is bad
506; AX = error_invalid_access
507; No other registers effected
508
509 procedure Check_Access_AX
510 DOSAssume CS,<DS>,"Check_Access"
511 ASSUME ES:NOTHING
512
513 MOV Open_Access,AL
514 PUSH BX
515;
516; If sharing, then test for special sharing mode for FCBs
517;
518 MOV BL,AL
519 AND BL,sharing_mask
520 CMP fSharing,-1
521 JNZ CheckShareMode ; not through server call, must be ok
522 CMP BL,sharing_NET_FCB
523 JZ CheckAccessMode ; yes, we have an FCB
524CheckShareMode:
525 CMP BL,40h ; is this a good sharing mode?
526 JA Make_Bad_Access
527CheckAccessMode:
528 MOV BL,AL
529 AND BL,access_mask
530 CMP BL,2
531 JA Make_Bad_Access
532 POP BX
533 CLC
534 return
535
536make_bad_access:
537 MOV AX,error_invalid_access
538 POP BX
539 STC
540 return
541
542EndProc Check_Access_AX
543
544; Input: none
545; Function: Issue Code Page Mismatched INT 24 Critical Error
546; OutPut: AL =0 ignore
547; =3 fail
548
549procedure Code_Page_Mismatched_Error,NEAR ;AN000;
550 DOSAssume CS,<DS>,"Code_Page_Mismatched_Error" ;AN000;
551 ASSUME ES:NOTHING ;AN000;
552
553; PUSH DS ;FT. ;AN000;
554; Context DS ;FT. ds=cs ;AN000;
555; MOV AH,0A9H ;FT. fail,ignore,device,write ;AN000;
556; MOV DI,error_I24_gen_failure ;FT. set error ;AN000;
557; MOV [EXTERR],error_Code_Page_Mismatched ;FT. ;AN000;
558; MOV [EXTERR_CLASS],errCLASS_NotFnd ;FT. ;AN000;
559; MOV [EXTERR_ACTION],errACT_Abort ;FT. ;AN000;
560; MOV [EXTERR_LOCUS],errLOC_Unk ;FT. ;AN000;
561; MOV word ptr [EXITHOLD + 2],ES ;FT. save es:bp ;AN000;
562; MOV word ptr [EXITHOLD],BP ;FT. ;AN000;
563; invoke NET_I24_ENTRY ;FT. issue int 24H ;AN000;
564; POP DS ;FT. ;AN000;
565; return ;FT. ;AN000;
566
567EndProc Code_Page_Mismatched_Error ;AN000;
568CODE ENDS
569 END
diff --git a/v4.0/src/DOS/PARSE.ASM b/v4.0/src/DOS/PARSE.ASM
new file mode 100644
index 0000000..f8de345
--- /dev/null
+++ b/v4.0/src/DOS/PARSE.ASM
@@ -0,0 +1,447 @@
1; SCCSID = @(#)parse.asm 1.2 85/07/23
2TITLE PARSE - Parsing system calls for MS-DOS
3NAME PARSE
4;
5; System calls for parsing command lines
6;
7; $PARSE_FILE_DESCRIPTOR
8;
9; Modification history:
10;
11; Created: ARR 30 March 1983
12; EE PathParse 10 Sept 1983
13;
14
15.xlist
16;
17; get the appropriate segment definitions
18;
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xcref
25INCLUDE DOSSYM.INC
26INCLUDE DEVSYM.INC
27.cref
28.list
29
30BOGUS =FALSE
31.lall
32 I_Need chSwitch,BYTE
33
34BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB>
35
36; Inputs:
37; DS:SI Points to a command line
38; ES:DI Points to an empty FCB
39; Bit 0 of AL = 1 At most one leading separator scanned off
40; = 0 Parse stops if separator encountered
41; Bit 1 of AL = 1 If drive field blank in command line - leave FCB
42; = 0 " " " " " " - put 0 in FCB
43; Bit 2 of AL = 1 If filename field blank - leave FCB
44; = 0 " " " - put blanks in FCB
45; Bit 3 of AL = 1 If extension field blank - leave FCB
46; = 0 " " " - put blanks in FCB
47; Function:
48; Parse command line into FCB
49; Returns:
50; AL = 1 if '*' or '?' in filename or extension, 0 otherwise
51; DS:SI points to first character after filename
52
53 procedure $PARSE_FILE_DESCRIPTOR,NEAR
54ASSUME DS:NOTHING,ES:NOTHING
55
56 invoke MAKEFCB
57 PUSH SI
58 invoke get_user_stack
59 POP [SI.user_SI]
60 return
61EndProc $PARSE_FILE_DESCRIPTOR
62
63
64IF BOGUS
65BREAK <$PathParse - Parse a string>
66
67;------------------------------------------------------------------------------
68;
69; Parse is a string parser. It copies the next token into a buffer, updates
70; the string pointer, and builds a flag word which describes the token.
71;
72; ENTRY
73; DS:SI - Points to the beginning of the string to be parsed
74; ES:DI - Points to the buffer which will hold the new token
75;
76; EXIT
77; AX - Flag word
78; DS:SI - String pointer updated to point past the token just found
79; All other registers are unchanged.
80;
81; All of the isXXXX procedures called by the main routine test a character
82; to see if it is of a particular type. If it is, they store the character
83; and return with the ZF set.
84;
85; CALLS
86; isswit issep ispchr ispsep isinval isdot ischrnull dirdot pasep
87;
88;
89; INTERNAL REGISTER USAGE
90; AH - FF/00 to indicate whether a path token can terminated with a
91; slash or not.
92; AL - Used with lodsb/stosb to transfer and test chars from DS:SI
93; BX - Holds flag word
94; CX - Used with loop/rep and as a work var
95; DX - Used to test the length of names and extensions
96;
97; EFFECTS
98; The memory pointed to by DI has the next token copied into it.
99;
100; WARNINGS
101; It is the caller's responsibility to make sure DS:SI does not point
102; to a null string. If it does, SI is incremented, a null byte is
103; stored at ES:DI, and the routine returns.
104;
105;------------------------------------------------------------------------------
106ParseClassMask equ 1110000000000000b ; Token class mask
107ParseSwitch equ 1000000000000000b ; Switch class
108ParseSeparators equ 0100000000000000b ; Separator class
109ParsePathName equ 0010000000000000b ; Path class
110ParsePathNameData equ 0000000000001111b ; Path token data mask
111ParsePathSynErr equ 0000000000000001b ; Path has syntax error
112ParsePathWild equ 0000000000000010b ; Path has wildcards
113ParsePathSeparators equ 0000000000000100b ; Path has pseparators
114ParseInvalidDrive equ 0000000000001000b ; Path has invald drive
115
116
117; Sepchars is a string containing all of the token separator characters
118; and is used to test for separators.
119
120Table segment
121Public PRS001S,PRS001E
122PRS001S label byte
123sepchrs db 9,10,13,' ','+',',',';','=' ; tab cr lf sp + , ; =
124seplen equ $-sepchrs
125PRS001E label byte
126table ends
127
128Procedure $PathParse,NEAR
129 assume ds:nothing,es:nothing
130 xor ah,ah ; initialize registers and flags
131 xor bx,bx
132 cld
133 lodsb ; used the first byte of the token to
134 call isswit ; determine its type and call the routine to
135 je switch ; parse it
136 call issep
137 je separ
138 call ispchr
139 je path
140 call ispsep
141 je path
142 call isdot
143 je path
144 call isinval
145 je inval
146 stosb
147 jmp done
148
149inval: or bx,ParsePathName ; an invalid character/path token
150 or bx,ParsePathSynErr ; was found, set the appropriate
151 call issep ; flag bits and parse the rest of
152 jne icont ; the token
153 dec di
154icont: dec si
155 jmp ptosep
156
157switch: mov bx,ParseSwitch ; found a switch, set flag and parse
158 jmp ptosep ; the rest of it
159
160separ: mov bx,ParseSeparators ; found separator, set flag and parse
161seloop: lodsb ; everything up to the next non
162 call issep ; separator character
163 je seloop
164 jmp bksi
165
166path: or bx,ParsePathName ; found path, set flag
167 mov cx,8 ; set up to parse a file name
168 mov dx,8
169 call pasep ; if the token began with a path
170 jne pcont1 ; separator or . call rcont which
171 not ah ; handles checksfor . and ..
172 jmp rcont
173pcont1: cmp al,'.'
174 jne pcont2
175 dec si
176 dec di
177 jmp rcont
178pcont2: cmp al,'A' ; if token may start with a drive
179 jge drive ; designator, go to drive. otherwise
180 jmp name1 ; parse a file name.
181
182drive: cmp byte ptr [si],':' ; if there is a drive designator, parse
183 jne name1 ; and verify it. otherwise parse a file
184 not ah ; name.
185 cmp al,'Z'
186 jle dcont1
187 sub al,' '
188dcont1: sub al,'@'
189 invoke GetthisDrv
190 lodsb
191 stosb
192 jc dcont2
193 jmp dcont3
194dcont2: or bx,ParseInvalidDrive
195dcont3: dec cx
196 lodsb
197 call ispsep
198 je rcont
199 dec si
200
201repeat: mov al,byte ptr [si-2] ; repeat and rcont test for //, \\, .,
202 call pasep ; and .. and repeatedly calls name
203 jne rcont ; and ext until a path token has
204 inc si ; been completely parsed.
205 jmp inval
206rcont: call dirdot
207 je done
208 jc inval
209 mov cx,8
210 mov dx,8
211 jmp name
212
213name1: dec cx
214name: lodsb ; parse and verify a file name
215 call ispchr
216 jne ncheck
217 xor ah,ah
218nloop: loop name
219 lodsb
220
221ncheck: cmp ah,0
222 jne ncont
223 cmp cx,dx
224 jne ncont
225 jmp inval
226ncont: call isdot
227 je ext
228 jmp dcheck
229
230ext: mov cx,3 ; parse and verify a file extension
231 mov dx,3
232extl: lodsb
233 call ispchr
234 jne echeck
235eloop: loop extl
236 lodsb
237
238echeck: cmp cx,dx
239 jne dcheck
240 jmp inval
241
242dcheck: call ispsep ; do the checks need to make sure
243 je repeat ; a file name or extension ended
244 call issep ; correctly and checks to see if
245 je bkboth ; we're done
246 call ischrnull
247 je done
248 jmp inval
249
250ptosep: lodsb ; parse everything to the next separator
251 call issep
252 je bkboth
253 call ischrnull
254 je done
255 call isinval
256 jne ptcont
257 or bx,ParsePathSynErr
258ptcont: stosb
259 jmp ptosep
260
261bkboth: dec di ; clean up when the end of the token
262bksi: dec si ; is found, stick a terminating null
263done: xor al,al ; byte at the end of buf, and exit
264 stosb
265 push si
266 invoke Get_user_stack
267 mov [si].user_AX,bx
268 pop [si].user_SI
269 Transfer sys_ret_ok
270
271Endproc $PathParse
272
273; Is current character the beginning of a switch?
274
275isswit proc near
276 cmp al,[chSwitch]
277 jne swret
278 stosb
279swret: ret
280isswit endp
281
282
283; Is the current character a separator?
284
285issep proc near
286 push cx
287 push di
288 push es
289 mov cx,cs
290 mov es,cx
291 mov cx,seplen
292 mov di,offset dosgroup:sepchrs
293 repne scasb
294 pop es
295 pop di
296 jne sepret
297sepyes: stosb
298sepret: pop cx
299 ret
300issep endp
301
302
303; Is the current character a path character? If it is a wildcard char too,
304; set that flag.
305
306ispchr proc near
307 cmp al,'!'
308 je pcyes
309 cmp al,'#'
310 jl pcret
311 cmp al,'*'
312 je pcwild
313 jl pcyes
314 cmp al,'-'
315 je pcyes
316 cmp al,'0'
317 jl pcret
318 cmp al,'9'
319 jle pcyes
320 cmp al,'?'
321 je pcwild
322 jl pcret
323 cmp al,'Z'
324 jle pcyes
325 cmp al,'^'
326 jl pcret
327 cmp al,'{'
328 jle pcyes
329 cmp al,'}'
330 je pcyes
331 cmp al,'~'
332 je pcyes
333 jmp pcret
334pcwild: or bx,ParsePathWild
335pcyes: stosb
336 cmp al,al
337pcret: ret
338ispchr endp
339
340
341; Is the current character a path separator? If so, set that flag after
342; storing the byte.
343
344ispsep proc near
345 call pasep
346 jne psret
347 stosb
348 or bx,ParsePathSeparators
349 cmp al,al
350psret: ret
351ispsep endp
352
353
354; Set ZF if the character in AL is a path separator.
355
356pasep proc near
357 cmp chSwitch,'/'
358 je bkslash
359 cmp al,'/'
360 retz
361bkslash:cmp al,'\'
362 ret
363pasep endp
364
365
366; Is the current character invalid?
367
368isinval proc near
369 cmp al,1
370 jl inret
371 cmp al,8
372 jle inyes
373 cmp al,11
374 jl inret
375 cmp al,13
376 jne incont
377 cmp al,0
378 ret
379incont: cmp al,31
380 jle inyes
381 cmp al,'['
382 je inyes
383 cmp al,']'
384 je inyes
385 ret
386inyes: cmp al,al
387inret: ret
388isinval endp
389
390
391; Is the current character a dot?
392
393isdot proc near
394 cmp al,'.'
395 jne dotret
396 stosb
397dotret: ret
398isdot endp
399
400
401; Is the current character null? If so, update SI for exiting.
402
403ischrnull proc near
404 cmp al,0
405 jne nulret
406 dec si
407 cmp al,al
408nulret: ret
409ischrnull endp
410
411
412; Check for . and .. Before returning, CF and ZF are set to indicate whether
413; the token is invalid (found . or .. followed by an invalid char - CF on),
414; we're done (found . or .. followed by null or a separator - ZF on), or the
415; token continues (. and .. not found or found and followed by a path
416; separator - both flags off).
417
418dirdot proc near
419 cmp byte ptr [si], '.'
420 jne diretc
421 lodsb
422 stosb
423 cmp byte ptr [si],'.'
424 jne dicont
425 lodsb
426 stosb
427dicont: lodsb
428 call ispsep
429 je diretc
430 call issep
431 je dibk
432 call ischrnull
433 je diretd
434direti: stc ; Invalid return
435 ret
436dibk: dec si
437 dec di
438diretd: cmp al,al ; Done return
439 ret
440diretc: cmp ah,1 ; Continue return
441 clc
442 ret
443dirdot endp
444ENDIF
445
446CODE ENDS
447 END
diff --git a/v4.0/src/DOS/PATH.ASM b/v4.0/src/DOS/PATH.ASM
new file mode 100644
index 0000000..5deed6c
--- /dev/null
+++ b/v4.0/src/DOS/PATH.ASM
@@ -0,0 +1,363 @@
1; SCCSID = @(#)path.asm 1.1 85/04/10
2TITLE PATH - Directory related system calls
3NAME PATH
4
5;
6; Directory related system calls. These will be passed direct text of the
7; pathname from the user. They will need to be passed through the macro
8; expander prior to being sent through the low-level stuff. I/O specs are
9; defined in DISPATCH. The system calls are:
10;
11; $CURRENT_DIR Written
12; $RMDIR Written
13; $CHDIR Written
14; $MKDIR Written
15;
16;
17; Modification history:
18;
19; Created: ARR 4 April 1983
20; MZ 10 May 1983 CurrentDir implemented
21; MZ 11 May 1983 RmDir, ChDir, MkDir implemented
22; EE 19 Oct 1983 RmDir no longer allows you to delete a
23; current directory.
24; MZ 19 Jan 1983 Brain damaged applications rely on success
25; values of AL.
26.xlist
27;
28; get the appropriate segment definitions
29;
30include dosseg.asm
31
32CODE SEGMENT BYTE PUBLIC 'CODE'
33 ASSUME SS:DOSGroup,CS:DOSGroup
34
35.xcref
36INCLUDE DOSSYM.INC
37INCLUDE DEVSYM.INC
38.cref
39.list
40
41 EXTRN DOS_MkDir:NEAR,DOS_RmDir:NEAR
42
43 I_Need ThisCDS,DWORD ; pointer to Current CDS
44 I_Need WFP_Start,WORD ; pointer to beginning of directory text
45 I_Need Curr_Dir_End,WORD ; offset to end of directory part
46 I_Need OpenBuf,128 ; temp spot for translated name
47 I_need fSplice,BYTE ; TRUE => do splice
48 I_Need NoSetDir,BYTE ; TRUE => no exact match on splice
49 I_Need cMeta,BYTE
50 I_Need DrvErr,BYTE ;AN000;
51
52BREAK <$CURRENT_DIR - dump the current directory into user space>
53;
54; Assembler usage:
55; LDS SI,area
56; MOV DL,drive
57; INT 21h
58; ; DS:SI is a pointer to 64 byte area that contains drive
59; ; current directory.
60; Error returns:
61; AX = error_invalid_drive
62;
63
64 procedure $CURRENT_DIR,NEAR
65 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
66 EnterCrit critDisk
67 MOV AL,DL ; get drive number (0=def, 1=A)
68 Invoke GetVisDrv ; grab it
69 JNC CurrentValidate ; no error -> go and validate dir
70CurdirErr:
71 LeaveCrit critDisk
72 MOV AL,[DrvErr] ;IFS. ;AN000;
73 transfer SYS_RET_ERR ;IFS. make noise ;AN000;
74CurrentValidate:
75 SaveReg <DS,SI> ; save destination
76 LDS SI,ThisCDS
77 TEST [SI].curdir_flags,curdir_isnet
78 JNZ DoCheck
79; Random optimization nuked due to some utilities using GetCurrentDir to do
80; media check.
81; CMP [SI].curdir_id,0
82; JZ GetDst
83DoCheck:
84 MOV NoSetDir,0 ; interested only in contents
85 MOV DI,OFFSET DOSGroup:OpenBuf
86 Invoke ValidateCDS ; output is ES:DI -> CDS
87 SaveReg <ES,DI> ; swap source and destination
88 RestoreReg <SI,DS>
89GetDst:
90 RestoreReg <DI,ES> ; get real destination
91 JC CurdirErr
92 ADD SI,curdir_text
93 ADD SI,[SI.curdir_END]
94 CMP BYTE PTR [SI],'\' ; root or subdirs present?
95 JNZ CurrentCopy
96 INC SI
97CurrentCopy:
98; Invoke FStrCpy
99;; 10/29/86 E5 char
100 PUSH AX
101 LODSB ; get char
102 OR AL,AL
103 JZ FOK
104 CMP AL,05
105 JZ FCHANGE
106 JMP FFF
107FCPYNEXT:
108 LODSB ; get char
109FFF:
110 CMP AL,'\' ; beginning of directory
111 JNZ FOK ; no
112 STOSB ; put into user's buffer
113 LODSB ; 1st char of dir is 05?
114 CMP AL,05H
115 JNZ FOK ; no
116FCHANGE:
117 MOV AL,0E5H ; make it E5
118FOK:
119 STOSB ; put into user's buffer
120 OR AL,AL ; final char
121 JNZ FCPYNEXT ; no
122 POP AX
123
124;; 10/29/86 E5 char
125 xor AL,AL ; MZ 19 Jan 84
126 LeaveCrit critDisk
127 transfer Sys_Ret_OK ; no more, bye!
128EndProc $Current_Dir
129
130BREAK <$RmDir -- Remove a directory>
131
132; Inputs:
133; DS:DX Points to asciz name
134; Function:
135; Delete directory if empty
136; Returns:
137; STD XENIX Return
138; AX = error_path_not_found If path bad
139; AX = error_access_denied If
140; Directory not empty
141; Path not directory
142; Root directory specified
143; Directory malformed (. and .. not first two entries)
144; User tries to delete a current directory
145; AX = error_current_directory
146
147 procedure $RMDIR,NEAR
148 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
149
150 push dx ; Save ptr to name
151 push ds
152 mov si,dx ; Load ptr into si
153 mov di,offset DOSGroup:OpenBuf ; di = ptr to buf for trans name
154 push di
155 Invoke TransPathNoSet ; Translate the name
156 pop di ; di = ptr to buf for trans name
157 jnc rmlset ; If transpath succeeded, continue
158 pop ds
159 pop dx ; Restore the name
160 error error_path_not_found ; Otherwise, return an error
161
162rmlset:
163 CMP cMeta,-1 ; if (cMeta >= 0)
164 Jnz rmerr ; return (-1);
165 Context ES
166 xor al,al ; al = 0 , ie drive a:
167rmloop: Invoke GetCDSFromDrv ; Get curdir for drive in al
168 jc rmcont ; If error, exit loop & cont normally
169 Invoke StrCmp ; Are the 2 paths the same?
170 jz rmerr ; Yes, report error.
171 inc al ; No, inc al to next drive number
172 jmp rmloop ; Go check next drive.
173
174rmerr:
175 pop ds
176 pop dx ; Restore the name
177 error error_current_directory ; error
178
179rmcont:
180 pop ds
181 pop dx ; Restore the name
182 MOV SI,OFFSET DOSGroup:DOS_RmDIR
183 JMP DoDirCall
184EndProc $RMDIR
185
186BREAK <$ChDir -- Change current directory on a drive>
187
188;
189; $ChDir - Top-level change directory system call. This call is responsible
190; for setting up the CDS for the specified drive appropriately. There are
191; several cases to consider:
192;
193; o Local, simple CDS. In this case, we take the input path and convert
194; it into a WFP. We verify the existance of this directory and then
195; copy the WFP into the CDS and set up the ID field to point to the
196; directory cluster.
197; o Net CDS. We form the path from the root (including network prefix)
198; and verify its existance (via DOS_Chdir). If successful, we copy the
199; WFP back into the CDS.
200; o SUBST'ed CDS. This is no different than the local, simple CDS.
201; o JOIN'ed CDS. This is trouble as there are two CDS's at work. If we
202; call TransPath, we will get the PHYSICAL CDS that the path refers to
203; and the PHYSICAL WFP that the input path refers to. This is perfectly
204; good for the validation but not for currency. We call TransPathNoSet
205; to process the path but to return the logical CDS and the logical
206; path. We then copy the logical path into the logical CDS.
207;
208; Inputs:
209; DS:DX Points to asciz name
210; Returns:
211; STD XENIX Return
212; AX = chdir_path_not_found if error
213
214 procedure $CHDIR,NEAR
215 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
216 MOV DI,OFFSET DOSGroup:OpenBuf ; spot for translated name
217 MOV SI,DX ; get source
218 Invoke TransPath ; go munge the path and get real CDS
219 JNC ChDirCrack ; no errors, try path
220ChDirErrP:
221 MOV AL,error_path_not_found
222ChdirErr:
223 transfer SYS_Ret_Err ; oops!
224
225ChDirCrack:
226 Assume DS:DOSGroup
227 CMP cMeta,-1 ; No meta chars allowed.
228 JNZ ChDirErrP
229;
230; We cannot do a ChDir (yet) on a raw CDS. This is treated as a path not
231; found.
232;
233 LES DI,ThisCDS
234 CMP DI,-1 ; if (ThisCDS == NULL)
235 JZ ChDirErrP ; error ();
236 ;
237 ; Find out if the directory exists.
238 ;
239 Invoke DOS_ChDir
240 JC ChDirErr
241;
242; Get back CDS to see if a join as seen. Set the currency pointer (only if
243; not network). If one was seen, all we need to do is copy in the text
244;
245 LES DI,ThisCDS
246 TEST ES:[DI].curdir_flags,curdir_splice
247 JZ GotCDS
248;
249; The CDS was joined. Let's go back and grab the logical CDS.
250;
251 SaveReg <ES,DI,CX> ; save CDS and cluster...
252 Invoke Get_User_Stack ; get original text
253 ASSUME DS:NOTHING
254 MOV DI,[SI.User_DX]
255 MOV DS,[SI.User_DS]
256 MOV SI,OFFSET DOSGroup:OpenBuf ; spot for translated name
257 XCHG SI,DI
258 XOR AL,AL ; do no splicing
259 SaveReg <DI>
260 Invoke TransPathNoSet ; Munge path
261 RestoreReg <SI>
262 Assume DS:DOSGroup
263;
264; There should NEVER be an error here.
265;
266IF FALSE
267 JNC SKipErr
268 fmt <>,<>,<"$p: Internal CHDIR error\n">
269SkipErr:
270ENDIF
271 LES DI,ThisCDS ; get new CDS
272 MOV ES:[DI].curdir_ID,-1 ; no valid cluster here...
273 RestoreReg <CX,DI,ES>
274;
275; ES:DI point to the physical CDS, CX is the ID (local only)
276;
277GotCDS:
278;
279; wfp_start points to the text. See if it is long enough
280;
281 CALL Check_PathLen ;PTM. ;AN000;
282 JA ChDirErrP
283 TEST ES:[DI].curdir_flags,curdir_isnet
284 JNZ SkipRecency
285 TEST ES:[DI].curdir_flags,curdir_splice ;PTM. for Join and Subst ;AN000;
286 JZ setdirclus ;PTM. ;AN000;
287 MOV CX,-1 ;PTM. ;AN000;
288setdirclus:
289 MOV ES:[DI].curdir_id,CX
290 LES DI,ThisCDS ; get logical CDS
291SkipRecency:
292 invoke FStrCpy
293 XOR AL,AL
294 transfer Sys_Ret_OK
295EndProc $CHDIR
296
297BREAK <$MkDir - Make a directory entry>
298; Inputs:
299; DS:DX Points to asciz name
300; Function:
301; Make a new directory
302; Returns:
303; STD XENIX Return
304; AX = mkdir_path_not_found if path bad
305; AX = mkdir_access_denied If
306; Directory cannot be created
307; Node already exists
308; Device name given
309; Disk or directory(root) full
310
311 procedure $MKDIR,NEAR
312 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
313 MOV SI,OFFSET DOSGroup:DOS_MkDir
314DoDirCall:
315 MOV DI,OFFSET DOSGroup:OpenBuf ; spot for translated name
316 SaveReg <SI>
317 MOV SI,DX ; get source
318 Invoke TransPath ; go munge the path
319 RestoreReg <SI>
320 JNC MkDirCrack ; no errors, try path
321MkErrP:
322 MOV AL,error_Path_Not_Found ; oops!
323MkErr:
324 transfer Sys_Ret_Err
325MkDirCrack:
326 CMP cMeta,-1
327 JNZ MkErrP
328
329 PUSH SI ;PTM. ;AN000;
330 CALL Check_PathLen ;PTM. check path len > 67 ? ;AN000;
331 POP SI ;PTM. ;AN000;
332 JBE pathok ;PTM. ;AN000;
333 MOV AL,error_Access_Denied ;PTM. ops!
334 transfer Sys_Ret_Err ;PTM.
335pathok:
336 CALL SI ; go get file
337 ASSUME ES:NOTHING
338 JC MkErr ; no errors
339 transfer Sys_Ret_OK
340EndProc $MKDIR
341
342; Inputs:
343; nothing
344; Function:
345; check if final path length greater than 67
346; Returns:
347; Above flag set if > 67
348
349 procedure Check_PathLen,NEAR
350 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
351
352 MOV SI,Wfp_Start
353 entry Check_PathLen2
354 Context <DS>
355 SaveReg <CX>
356 invoke DStrLen
357 CMP CX,DirStrLen
358 RestoreReg <CX>
359 ret
360EndProc Check_PathLen
361CODE ENDS
362END
363 \ No newline at end of file
diff --git a/v4.0/src/DOS/PRINT.ASM b/v4.0/src/DOS/PRINT.ASM
new file mode 100644
index 0000000..c2bbe55
--- /dev/null
+++ b/v4.0/src/DOS/PRINT.ASM
@@ -0,0 +1,199 @@
1; SCCSID = @(#)print.asm 1.1 85/04/10
2;
3; PFMT - formatted output. Calling sequence:
4; PUSH BP
5; PUSH fmtstr
6; MOV BP,SP
7; PUSH args
8; CALL PFMT
9; ADD SP,n
10; POP BP
11;
12; The format string contains format directives and normal output characters
13; much like the PRINTF for C. We utilize NO format widths. Special chars
14; and strings are:
15;
16; $x output a hex number
17; $s output an offset string
18; $c output a character
19; $S output a segmented string
20; $p output userid/processid
21; \t output a tab
22; \n output a CRLF
23;
24; The format string must be addressable via CS
25;
26
27Procedure PFMT,NEAR
28 SaveReg <AX,BX,DS,SI>
29 MOV AX,8007h
30 INT 2Ah
31 PUSH CS
32 POP DS
33 SUB BP,2
34 Call FMTGetArg
35 MOV SI,AX
36FmtLoop:
37 LODSB
38 OR AL,AL
39 JZ FmtDone
40 CMP AL,'$'
41 JZ FmtOpt
42 CMP AL,'\'
43 JZ FmtChr
44FmtOut:
45 CALL Out
46 JMP FmtLoop
47Out:
48 SaveReg <SI,DI,BP>
49 INT 29h
50 RestoreReg <BP,DI,SI>
51 return
52FmtDone:
53 MOV AX,8107h
54 INT 2Ah
55 RestoreReg <SI,DS,BX,AX>
56 RET
57;
58; \ leads in a special character. See what the next char is.
59;
60FmtChr: LODSB
61 OR AL,AL ; end of string
62 JZ fmtDone
63 CMP AL,'n' ; newline
64 JZ FmtCRLF
65 CMP AL,'t' ; tab
66 JNZ FmtOut
67 MOV AL,9
68 JMP FmtOut
69FmtCRLF:MOV AL,13
70 CALL Out
71 MOV AL,10
72 JMP FmtOut
73;
74; $ leads in a format specifier.
75;
76FmtOpt: LODSB
77 CMP AL,'x' ; hex number
78 JZ FmtX
79 CMP AL,'c' ; single character
80 JZ FmtC
81 CMP AL,'s' ; offset string
82 JZ FmtSoff
83 CMP AL,'S' ; segmented string
84 JZ FmtSseg
85 CMP AL,'p'
86 JZ FmtUPID
87 JMP FmtOut
88FmtX:
89 Call FMTGetArg
90 MOV BX,AX
91 CALL MNUM
92 JMP FmtLoop
93FmtC:
94 Call FmtGetArg
95 CALL Out
96 JMP FmtLoop
97FmtSoff:
98 SaveReg <SI>
99 Call FmtGetArg
100 MOV SI,AX
101 CALL fmtsout
102 RestoreReg <SI>
103 JMP FmtLoop
104FmtSSeg:
105 SaveReg <DS,SI>
106 CALL FMTGetArg
107 MOV DS,AX
108 CALL FMTGetArg
109 MOV SI,AX
110 CALL fmtsout
111 RestoreReg <SI,DS>
112 JMP FmtLoop
113FmtUPID:
114 SaveReg <DS>
115 MOV BX,0
116 MOV DS,BX
117 MOV DS,DS:[82h]
118 ASSUME DS:DOSGroup
119 MOV BX,User_ID
120 CALL MNUM
121 MOV AL,':'
122 CALL OUT
123 MOV BX,Proc_ID
124 CALL MNUM
125 RestoreReg <DS>
126 Assume DS:NOTHING
127 JMP FmtLoop
128EndProc PFMT
129
130Procedure FMTGetArg,NEAR
131 MOV AX,[BP]
132 SUB BP,2
133 return
134EndProc FMTGetArg
135
136Procedure FmtSOut,NEAR
137 LODSB
138 OR AL,AL
139 retz
140 CALL OUT
141 JMP FmtSOut
142EndProc FMTSout
143
144;
145; MOut - output a message via INT 29h
146; Inputs: BX points to bytes to output relative to CS
147; Outputs: message
148; Registers modified: BX
149Procedure MOut,Near
150 ASSUME DS:NOTHING,SS:NOTHING,ES:NOTHING
151 PUSHF
152 SaveReg <DS,SI,AX>
153 PUSH CS
154 POP DS
155 MOV SI,BX
156 Call FMTSout
157 RestoreReg <AX,SI,DS>
158 POPF
159 return
160EndProc MOut
161
162; MNum - output a number in BX
163; Inputs: BX contains a number
164; Outputs: number in hex appears on screen
165; Registers modified: BX
166
167Procedure MNum,NEAR
168 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
169 PUSHF
170 SaveReg <ES,DI,AX,BX,CX,SI,DS>
171 PUSH SS
172 POP ES
173 SUB SP,6
174 MOV DI,SP ; p = MNumBuf;
175 SaveReg <DI>
176 MOV CX,4 ; for (i=0; i < 4; i++)
177DLoop: SaveReg <CX>
178 MOV CX,4 ; rotate(n, 4);
179 ROL BX,CL
180 RestoreReg <CX>
181 MOV AL,BL
182 AND AL,0Fh
183 ADD AL,'0'
184 CMP AL,'9'
185 JBE Nok
186 ADD AL,'A'-'0'-10
187Nok: STOSB ; *p++ = "0123456789ABCDEF"[n];
188 LOOP DLoop
189 XOR AL,AL
190 STOSB ; *p++ = 0;
191 RestoreReg <SI>
192 PUSH ES
193 POP DS
194 CALL FMTSOUT ; mout (mNumBuf);
195 ADD SP,6
196 RestoreReg <DS,SI,CX,BX,AX,DI,ES>
197 POPF
198 return
199EndProc MNum
diff --git a/v4.0/src/DOS/PROC.ASM b/v4.0/src/DOS/PROC.ASM
new file mode 100644
index 0000000..1e54034
--- /dev/null
+++ b/v4.0/src/DOS/PROC.ASM
@@ -0,0 +1,187 @@
1; SCCSID = @(#)proc.asm 1.1 85/04/10
2TITLE IBMPROC - process maintenance
3NAME IBMPROC
4
5;
6; Process related system calls and low level routines for DOS 2.X.
7; I/O specs are defined in DISPATCH.
8;
9; $WAIT
10; $EXEC
11; $Keep_process
12; Stay_resident
13; $EXIT
14; $ABORT
15; abort_inner
16;
17; Modification history:
18;
19; Created: ARR 30 March 1983
20;
21
22.xlist
23;
24; get the appropriate segment definitions
25;
26include dosseg.asm
27
28CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME SS:DOSGROUP,CS:DOSGROUP
30
31.xcref
32INCLUDE DOSSYM.INC
33INCLUDE DEVSYM.INC
34.cref
35.list
36
37SAVEXIT EQU 10
38
39 i_need CurrentPDB,WORD
40 i_need CreatePDB,BYTE
41 i_need Exit_type,BYTE
42 i_need INDOS,BYTE
43 i_need DMAADD,DWORD
44 i_need DidCTRLC,BYTE
45 i_need exit_type,BYTE
46 i_need exit_code,WORD
47 i_need OpenBuf,128
48 I_need EXTERR_LOCUS,BYTE ; Extended Error Locus
49
50SUBTTL $WAIT - return previous process error code
51PAGE
52;
53; process control data
54;
55 i_need exit_code,WORD ; code of exit
56
57;
58; Assembler usage:
59; MOV AH, WaitProcess
60; INT int_command
61; AX has the exit code
62 procedure $WAIT,NEAR
63 ASSUME DS:NOTHING,ES:NOTHING
64 XOR AX,AX
65 XCHG AX,exit_code
66 transfer SYS_RET_OK
67EndProc $WAIT
68
69include exec.asm
70
71SUBTTL Terminate and stay resident handler
72PAGE
73;
74; Input: DX is an offset from CurrentPDB at which to
75; truncate the current block.
76;
77; output: The current block is truncated (expanded) to be [DX+15]/16
78; paragraphs long. An exit is simulated via resetting CurrentPDB
79; and restoring the vectors.
80;
81 procedure $Keep_process,NEAR
82 ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
83
84 PUSH AX ; keep exit code around
85 MOV BYTE PTR [Exit_type],Exit_keep_process
86 MOV ES,[CurrentPDB]
87 CMP DX,6h ; keep enough space around for system
88 JAE Keep_shrink ; info
89 MOV DX,6h
90keep_shrink:
91 MOV BX,DX
92 PUSH BX
93 PUSH ES
94 invoke $SETBLOCK ; ignore return codes.
95 POP DS
96 POP BX
97 JC keep_done ; failed on modification
98 MOV AX,DS
99 ADD AX,BX
100 MOV DS:[PDB_block_len],AX
101
102keep_done:
103 POP AX
104 JMP SHORT exit_inner ; and let abort take care of the rest
105
106EndProc $Keep_process
107
108 procedure Stay_resident,NEAR
109 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
110 MOV AX,(Keep_process SHL 8) + 0 ; Lower part is return code
111 ADD DX,15
112 RCR DX,1
113 MOV CL,3
114 SHR DX,CL
115
116 transfer COMMAND
117EndProc Stay_resident
118
119SUBTTL $EXIT - return to parent process
120PAGE
121;
122; Assembler usage:
123; MOV AL, code
124; MOV AH, Exit
125; INT int_command
126; Error return:
127; None.
128;
129 procedure $EXIT,NEAR
130 ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
131 XOR AH,AH
132 XCHG AH,BYTE PTR [DidCTRLC]
133 OR AH,AH
134 MOV BYTE PTR [Exit_type],exit_terminate
135 JZ exit_inner
136 MOV BYTE PTR [Exit_type],exit_ctrl_c
137
138 entry Exit_inner
139
140 invoke get_user_stack
141 PUSH [CurrentPDB]
142 POP [SI.user_CS]
143 JMP SHORT abort_inner
144EndProc $EXIT
145
146BREAK <$ABORT -- Terminate a process>
147
148; Inputs:
149; user_CS:00 must point to valid program header block
150; Function:
151; Restore terminate and Cntrl-C addresses, flush buffers and transfer to
152; the terminate address
153; Returns:
154; TO THE TERMINATE ADDRESS
155
156 procedure $ABORT,NEAR
157ASSUME DS:NOTHING,ES:NOTHING
158
159 XOR AL,AL
160 MOV [exit_type],exit_abort
161
162;
163; abort_inner must have AL set as the exit code! The exit type is retrieved
164; from exit_type. Also, the PDB at user_CS needs to be correct as the one
165; that is terminating.
166;
167 entry abort_inner
168
169 MOV AH,[exit_type]
170 MOV [exit_code],AX
171 invoke Get_user_stack
172 MOV DS,[SI.user_CS] ; set up old interrupts
173 XOR AX,AX
174 MOV ES,AX
175 MOV SI,SAVEXIT
176 MOV DI,addr_int_terminate
177 MOVSW
178 MOVSW
179 MOVSW
180 MOVSW
181 MOVSW
182 MOVSW
183 transfer reset_environment
184EndProc $ABORT
185
186CODE ENDS
187 END
diff --git a/v4.0/src/DOS/RENAME.ASM b/v4.0/src/DOS/RENAME.ASM
new file mode 100644
index 0000000..c7d6caf
--- /dev/null
+++ b/v4.0/src/DOS/RENAME.ASM
@@ -0,0 +1,434 @@
1; SCCSID = @(#)rename.asm 1.1 85/04/10
2TITLE DOS_RENAME - Internal RENAME call for MS-DOS
3NAME DOS_RENAME
4; Low level routine for renaming files
5;
6; DOS_RENAME
7;
8; Modification history:
9;
10; Created: ARR 30 March 1983
11;
12
13;
14; get the appropriate segment definitions
15;
16.xlist
17include dosseg.asm
18
19CODE SEGMENT BYTE PUBLIC 'CODE'
20 ASSUME SS:DOSGROUP,CS:DOSGROUP
21
22.xcref
23INCLUDE DOSSYM.INC
24INCLUDE DEVSYM.INC
25.cref
26.list
27
28Installed = TRUE
29
30 i_need RENAMEDMA,BYTE
31 i_need AUXSTACK,BYTE
32 i_need DESTSTART,WORD
33 i_need DIRSTART,WORD
34 i_need CURBUF,DWORD
35 I_need NAME1,BYTE
36 i_need NAME2,BYTE
37 i_need WFP_START,WORD
38 i_need REN_WFP,WORD
39 i_need CURR_DIR_END,WORD
40 i_need DMAADD,DWORD
41 i_need THISCDS,DWORD
42 i_need THISDPB,DWORD
43 i_need THISSFT,DWORD
44 i_need CREATING,BYTE
45 i_need THISDRV,BYTE
46 i_need ATTRIB,BYTE
47 i_need FOUND_DEV,BYTE
48 i_need FAILERR,BYTE
49 i_need EXTERR_LOCUS,BYTE
50 i_need SAVE_BX,WORD
51
52; Inputs:
53; [WFP_START] Points to SOURCE WFP string ("d:/" must be first 3
54; chars, NUL terminated)
55; [CURR_DIR_END] Points to end of Current dir part of string [SOURCE]
56; ( = -1 if current dir not involved, else
57; Points to first char after last "/" of current dir part)
58; [REN_WFP] Points to DEST WFP string ("d:/" must be first 3
59; chars, NUL terminated)
60; [THISCDS] Points to CDS being used
61; (Low word = -1 if NUL CDS (Net direct request))
62; [SATTRIB] Is attribute of search, determines what files can be found
63; Function:
64; Rename the specified file(s)
65; NOTE: This routine uses most of AUXSTACK as a temp buffer.
66; Outputs:
67; CARRY CLEAR
68; OK
69; CARRY SET
70; AX is error code
71; error_file_not_found
72; No match for source, or dest path invalid
73; error_not_same_device
74; Source and dest are on different devices
75; error_access_denied
76; Directory specified (not simple rename),
77; Device name given, Destination exists.
78; NOTE: In third case some renames may have
79; been done if metas.
80; error_path_not_found
81; Bad path (not in curr dir part if present)
82; SOURCE ONLY
83; error_bad_curr_dir
84; Bad path in current directory part of path
85; SOURCE ONLY
86; error_sharing_violation
87; Deny both access required, generates an INT 24.
88; DS preserved, others destroyed
89
90 procedure DOS_RENAME,NEAR
91 DOSAssume CS,<DS>,"DOS_Rename"
92 ASSUME ES:NOTHING
93
94 Invoke TestNet
95 JNC LOCAL_RENAME
96; invoke OWN_SHARE2 ;IFS. IFS owns share ? ;AN000;
97; JZ ifsshare ;IFS. yes ;AN000;
98; PUSH WORD PTR [DMAADD+2] ;IFS. save DMAADD ;AN000;
99; PUSH WORD PTR [DMAADD] ;IFS. ;AN000;
100;
101; invoke IFS_SEARCH_FIRST ;IFS. search source name ;AN000;
102; JC nofiles ;IFS. not found ;AN000;
103rename_next_file:
104; invoke IFS_REN_DEL_CHECK ;IFS. do share check ;AN000;
105; JNC share_okok ;IFS. share ok ;AN000;
106; MOV AX,error_sharing_violation ;IFS. share error ;AN000;
107; JMP SHORT nofiles ;IFS. ;AN000;
108share_okok:
109; PUSH CS ;IFS. ;AN000;
110; POP ES ;IFS. ;AN000;
111; MOV SI,[REN_WFP] ;IFS. ds:si -> destination name ;AN000;
112; MOV BX,SI ;IFS. ;AN000;
113fndnxt: ;IFS. ;AN000;
114; LODSB ;IFS. ;AN000;
115; CMP AL,0 ;IFS. ;AN000;
116; JNZ fndnxt ;IFS. ;AN000;
117; MOV DI,SI ;IFS. es:di -> end of destinatio ;AN000;
118; ADD BX,2 ;IFS. ;AN000;
119; invoke SkipBack ;IFS. ;AN000;
120; INC DI ;IFS. es:di -> last component of ;AN000;
121; MOV SI,DI ;IFS. dstination ;AN000;
122; MOV BX,[SAVE_BX] ;IFS. ds:bx -> last component of ;AN000;
123; CALL NEW_RENAME ;IFS. source ;AN000;
124; MOV AX,(multNET SHL 8) OR 17 ;IFS. replace ? chars with ;AN000;
125; INT 2FH ;IFS. source and issue RENAME ;AN000;
126; JC nofiles ;IFS. error ;AN000;
127; invoke DOS_SEARCH_NEXT ;IFS. serch next source ;AN000;
128; JNC rename_next_file ;IFS. rename next ;AN000;
129; CLC ;IFS. no more files ;AN000;
130nofiles:
131; POP WORD PTR [DMAADD] ;IFS. restore DMAADD ;AN000;
132; POP WORD PTR [DMAADD+2] ;IFS. ;AN000;
133; ret ;IFS. return ;AN000;
134ifsshare:
135
136IF NOT Installed
137 transfer NET_RENAME
138ELSE
139 MOV AX,(multNET SHL 8) OR 17
140 INT 2FH
141 return
142ENDIF
143
144LOCAL_RENAME:
145 MOV [EXTERR_LOCUS],errLOC_Disk
146 MOV SI,[WFP_START]
147 MOV DI,[REN_WFP]
148 MOV AL,BYTE PTR [SI]
149 MOV AH,BYTE PTR [DI]
150 OR AX,2020H ; Lower case
151 CMP AL,AH
152 JZ SAMEDRV
153 MOV AX,error_not_same_device
154 STC
155 return
156
157SAMEDRV:
158 PUSH WORD PTR [DMAADD+2]
159 PUSH WORD PTR [DMAADD]
160 MOV WORD PTR [DMAADD+2],DS
161 MOV WORD PTR [DMAADD],OFFSET DOSGROUP:RENAMEDMA
162 MOV [Found_dev],0 ; Rename fails on DEVS, assume not a dev
163 EnterCrit critDisk
164 invoke DOS_SEARCH_FIRST ; Sets [NoSetDir] to 1, [CURBUF+2]:BX
165 ; points to entry
166 JNC Check_Dev
167 CMP AX,error_no_more_files
168 JNZ GOTERR
169 MOV AX,error_file_not_found
170GOTERR:
171 STC
172RENAME_POP:
173 POP WORD PTR [DMAADD]
174 POP WORD PTR [DMAADD+2]
175 LeaveCrit critDisk
176 return
177
178Check_dev:
179 MOV AX,error_access_denied ; Assume error
180
181 PUSH DS ;PTM. ;AN000;
182 LDS SI,[DMAADD] ;PTM. chek if source a dir ;AN000;
183 ADD SI,find_buf_attr ;PTM. ;AN000;
184 TEST [SI.dir_attr],attr_directory ;PTM. ;AN000;
185 JZ notdir ;PTM. ;AN000;
186 MOV SI,[REN_WFP] ;PTM. if yes, make sure path ;AN000;
187 invoke Check_Pathlen2 ;PTM. length < 67 ;AN000;
188notdir:
189 POP DS ;PTM. ;AN000;
190 JA GOTERR ;PTM. ;AN000;
191
192 CMP [Found_dev],0
193 JNZ GOTERR
194; At this point a source has been found. There is search continuation info (a
195; la DOS_SEARCH_NEXT) for the source at RENAMEDMA, together with the first
196; directory entry found.
197; [THISCDS], [THISDPB], and [THISDRV] are set and will remain correct
198; throughout the RENAME since it is known at this point that the source and
199; destination are both on the same device.
200; [SATTRIB] is also set.
201 MOV SI,BX
202 ADD SI,dir_first
203 invoke REN_DEL_Check
204 JNC REN_OK1
205 MOV AX,error_sharing_violation
206 JMP RENAME_POP
207
208REN_OK1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
209 invoke FastOpen_Delete ; delete dir info in fastopen DOS 3.3
210 MOV SI,[REN_WFP] ; Swap source and destination
211 MOV [WFP_START],SI
212 MOV [CURR_DIR_END],-1 ; No current dir on dest
213 MOV WORD PTR [CREATING],0E5FFH ; Creating, not DEL *.*
214 ; A rename is like a CREATE_NEW as far
215 ; as the destination is concerned.
216 invoke GetPathNoSet
217; If this Getpath fails due to file not found, we know all renames will work
218; since no files match the destination name. If it fails for any other
219; reason, the rename fails on a path not found, or whatever (also fails if
220; we find a device or directory). If the Getpath succeeds, we aren't sure
221; if the rename should fail because we haven't built an explicit name by
222; substituting for the meta chars in it. In this case the destination file
223; spec with metas is in [NAME1] and the explicit source name is at RENAMEDMA
224; in the directory entry part.
225 JC NODEST
226;; JZ BAD_ACC ; Dest string is a directory ;AC000;
227 OR AH,AH ; Device?
228 JNS SAVEDEST ; No, continue
229BAD_ACC:
230 MOV AX,error_access_denied
231 STC
232RENAME_CLEAN:
233 PUSHF ; Save carry state
234 PUSH AX ; and error code (if carry set)
235 MOV AL,[THISDRV]
236 invoke FLUSHBUF
237 POP AX
238 CMP [FAILERR],0
239 JNZ BAD_ERR ; User FAILed to I 24
240 POPF
241 JMP RENAME_POP
242
243BAD_ERR:
244 POP AX ; Saved flags
245 MOV AX,error_path_not_found
246 JMP GOTERR
247
248NODEST:
249 JNZ BAD_PATH
250 CMP [FAILERR],0
251 JNZ BAD_PATH ; Search for dest failed because user FAILed on
252 ; I 24
253 OR CL,CL
254 JNZ SAVEDEST
255BAD_PATH:
256 MOV AX,error_path_not_found
257 STC
258 JMP RENAME_POP
259
260SAVEDEST:
261 Context ES
262 MOV DI,OFFSET DOSGROUP:NAME2
263 MOV SI,OFFSET DOSGROUP:NAME1
264 MOV CX,11
265 REP MOVSB ; Save dest with metas at NAME2
266 MOV AX,[DIRSTART]
267 MOV [DESTSTART],AX
268BUILDDEST:
269 Context ES ; needed due to JMP BUILDDEST below
270 MOV BX,OFFSET DOSGROUP:RENAMEDMA + 21 ; Source of replace chars
271 MOV DI,OFFSET DOSGROUP:NAME1 ; Real dest name goes here
272 MOV SI,OFFSET DOSGROUP:NAME2 ; Raw dest
273 MOV CX,11
274 CALL NEW_RENAME ;IFS. replace ? chars ;AN000;
275
276 MOV [ATTRIB],attr_all ; Stop duplicates with any attributes
277 MOV [CREATING],0FFH
278 invoke DEVNAME ; Check if we built a device name
279 ASSUME ES:NOTHING
280 JNC BAD_ACC
281 MOV BX,[DESTSTART]
282 LES BP,[THISDPB]
283 invoke SetDirSrch ; Reset search to start of dir
284 JC BAD_ACC ; Screw up
285 invoke FINDENTRY ; See if new name already exists
286 JNC BAD_ACC ; Error if found
287 CMP [FAILERR],0
288 JNZ BAD_ACCJ ; Find failed because user FAILed to I 24
289 MOV AX,[DESTSTART] ; DIRSTART of dest
290 CMP AX,WORD PTR [RENAMEDMA + 15] ; DIRSTART of source
291 JZ SIMPLE_RENAME ; If =, just give new name
292
293 MOV AL,[RENAMEDMA + 21 + dir_attr]
294 TEST AL,attr_directory
295 JNZ BAD_ACCJ ; Can only do a simple rename on dirs,
296 ; otherwise the . and .. entries get
297 ; wiped.
298 MOV [ATTRIB],AL
299 MOV WORD PTR [THISSFT+2],DS
300 MOV SI,OFFSET DOSGROUP:AUXSTACK - SIZE SF_ENTRY
301 MOV WORD PTR [THISSFT],SI
302 MOV [SI].sf_mode,sharing_compat+open_for_both
303 XOR CX,CX ; Set "device ID" for call into makenode
304 invoke RENAME_MAKE ; This is in mknode
305 JNC GOT_DEST
306BAD_ACCJ:
307 JMP BAD_ACC
308
309GOT_DEST:
310 SaveReg <BX>
311 LES DI,ThisSFT ; Rename_make entered this into sharing
312 Invoke ShareEnd ; we need to remove it.
313 RestoreReg <BX>
314; A zero length entry with the correct new name has now been made at
315; [CURBUF+2]:BX.
316 LES DI,[CURBUF]
317 Assert ISBUF,<ES,DI>,"Got_Dest"
318
319 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
320 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
321 invoke INC_DIRTY_COUNT ;LB. ;AN000;
322 OR ES:[DI.buf_flags],buf_dirty
323yesdirty:
324 MOV DI,BX
325 ADD DI,dir_attr ; Skip name
326 MOV SI,OFFSET DOSGROUP:RENAMEDMA + 21 + dir_attr
327 MOV CX,(SIZE dir_entry) - dir_attr
328 REP MOVSB
329 CALL GET_SOURCE
330 JC RENAME_OVER
331 MOV DI,BX
332 MOV ES,WORD PTR [CURBUF+2]
333 MOV AL,0E5H
334 STOSB ; "free" the source
335 JMP SHORT DIRTY_IT
336
337SIMPLE_RENAME:
338 CALL GET_SOURCE ; Get the source back
339 JC RENAME_OVER
340 MOV DI,BX
341 MOV ES,WORD PTR [CURBUF+2]
342 MOV SI,OFFSET DOSGROUP:NAME1 ; New Name
343 MOV CX,11
344 REP MOVSB
345DIRTY_IT:
346 MOV DI,WORD PTR [CURBUF]
347
348 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
349 JNZ yesdirty2 ;LB. don't increment dirty count ;AN000;
350 invoke INC_DIRTY_COUNT ;LB. ;AN000;
351 OR ES:[DI.buf_flags],buf_dirty
352yesdirty2:
353 Assert ISBUF,<ES,DI>,"Dirty_it"
354NEXT_SOURCE:
355 MOV SI,OFFSET DOSGROUP:RENAMEDMA + 1 ;Name
356;
357; WARNING! Rename_Next leaves the disk critical section *ALWAYS*. We need
358; to enter it before going to RENAME_Next.
359;
360 EnterCrit critDisk
361 MOV [CREATING],0 ; Correct setting for search (we changed it
362 ; to FF when we made the prev new file).
363 invoke RENAME_NEXT
364;
365; Note, now, that we have exited the previous ENTER and so are back to where
366; we were before.
367;
368 JC RENAME_OVER
369 LEA SI,[BX].dir_First
370 invoke REN_DEL_Check
371 JNC REN_OK2
372 MOV AX,error_sharing_violation
373 JMP RENAME_CLEAN
374
375REN_OK2: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
376 invoke FastOpen_Delete ; delete dir info in fastopen DOS 3.3
377 JMP BUILDDEST
378
379RENAME_OVER:
380 CLC
381 JMP RENAME_CLEAN
382
383; Inputs:
384; RENAMEDMA has source info
385; Function:
386; Re-find the source
387; Output:
388; [CURBUF] set
389; [CURBUF+2]:BX points to entry
390; Carry set if error (currently user FAILed to I 24)
391; DS preserved, others destroyed
392
393GET_SOURCE:
394 DOSAssume CS,<DS>,"Get_Source"
395 ASSUME ES:NOTHING
396
397 MOV BX,WORD PTR [RENAMEDMA + 15] ; DirStart
398 LES BP,ThisDPB
399 invoke SetDirSrch
400 retc
401 invoke StartSrch
402 MOV AX,WORD PTR [RENAMEDMA + 13] ; Lastent
403 invoke GetEnt
404 return
405
406EndProc DOS_RENAME
407
408;Input: DS:SI -> raw string with ?
409; ES:DI -> destination string
410; DS:BX -> source string
411;Function: replace ? chars of raw string with chars in source string and
412; put in destination string
413;Output: ES:DI-> new string
414
415
416
417 procedure NEW_RENAME,NEAR
418 DOSAssume CS,<DS>,"DOS_Rename"
419 ASSUME ES:NOTHING
420NEWNAM:
421 LODSB
422 CMP AL,"?"
423 JNZ NOCHG
424 MOV AL,[BX] ; Get replace char
425NOCHG:
426 STOSB
427 INC BX ; Next replace char
428 LOOP NEWNAM
429 return
430
431EndProc NEW_RENAME
432
433CODE ENDS
434 END
diff --git a/v4.0/src/DOS/ROM.ASM b/v4.0/src/DOS/ROM.ASM
new file mode 100644
index 0000000..ca34409
--- /dev/null
+++ b/v4.0/src/DOS/ROM.ASM
@@ -0,0 +1,938 @@
1; SCCSID = @(#)rom.asm 1.1 85/04/10
2TITLE ROM - Miscellaneous routines
3NAME ROM
4; Misc Low level routines for doing simple FCB computations, Cache
5; reads and writes, I/O optimization, and FAT allocation/deallocation
6;
7; SKPCLP
8; FNDCLUS
9; BUFSEC
10; BUFRD
11; BUFWRT
12; NEXTSEC
13; OPTIMIZE
14; FIGREC
15; ALLOCATE
16; RESTFATBYT
17; RELEASE
18; RELBLKS
19; GETEOF
20;
21; Modification history:
22;
23; Created: ARR 30 March 1983
24;
25
26;
27; get the appropriate segment definitions
28;
29.xlist
30include dosseg.asm
31include fastseek.inc ; DOS 4.00
32include fastxxxx.inc ; DOS 4.00
33include version.inc
34
35CODE SEGMENT BYTE PUBLIC 'CODE'
36 ASSUME SS:DOSGROUP,CS:DOSGROUP
37
38.xcref
39INCLUDE DOSSYM.INC
40INCLUDE DEVSYM.INC
41include EA.inc
42.cref
43.list
44
45 i_need CLUSNUM,WORD
46 i_need NEXTADD,WORD
47 i_need LASTPOS,WORD
48 i_need SECCLUSPOS,BYTE
49 i_need FATBYT,WORD
50 i_need THISSFT,DWORD
51 i_need TRANS,BYTE
52 i_need BYTCNT1,WORD
53 i_need CURBUF,DWORD
54 i_need BYTSECPOS,WORD
55 i_need DMAADD,WORD
56 i_need SECPOS,DWORD ;F.C. >32mb
57 i_need VALSEC,DWORD ;F.C. >32mb
58 i_need ALLOWED,BYTE
59 i_need FSeek_drive,BYTE ; DOS 3.4
60 i_need FSeek_firclus,WORD ; DOS 3.4
61 i_need FSeek_logclus,WORD ; DOS 3.4
62 i_need FSeek_logsave,WORD ; DOS 3.4
63 i_need FastSeekFlg,BYTE ; DOS 3.4
64 i_need XA_condition,BYTE ; DOS 3.4
65 i_need HIGH_SECTOR,WORD ; DOS 3.4
66 i_need DISK_FULL,BYTE ; DOS 3.4
67 i_need Temp_VAR2,WORD ; DOS 3.4
68
69
70
71Break <FNDCLUS -- Skip over allocation units>
72
73; Inputs:
74; CX = No. of clusters to skip
75; ES:BP = Base of drive parameters
76; [THISSFT] point to SFT
77; Outputs:
78; BX = Last cluster skipped to
79; CX = No. of clusters remaining (0 unless EOF)
80; DX = Position of last cluster
81; Carry set if error (currently user FAILed to I 24)
82; DI destroyed. No other registers affected.
83
84 procedure FNDCLUS,NEAR
85 DOSAssume CS,<DS>,"FndClus"
86 ASSUME ES:NOTHING
87
88 Assert ISDPB,<ES,BP>,"FndCLus"
89;; 10/31/86 FastSeek
90 PUSH ES
91 LES DI,[THISSFT]
92 Assert ISSFT,<ES,DI>,"FndClus"
93 MOV [FSeek_logclus],CX ; presume CX is the position ;AN000;
94 MOV BX,ES:[DI.sf_lstclus]
95 MOV DX,ES:[DI.sf_cluspos]
96;; 10/31/86 FastSeek
97 OR BX,BX
98 JNZ YCLUS
99 JMP NOCLUS
100YCLUS:
101 SUB CX,DX
102 JNB FINDIT
103 ADD CX,DX
104 XOR DX,DX
105 MOV BX,ES:[DI.sf_firclus]
106FINDIT:
107;; 10/31/86 FastSeek
108
109
110 POP ES
111 OR CX,CX
112 JNZ skpclp
113 JMP RET10
114
115entry SKPCLP
116 TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000;
117 JZ do_norm ; no ;AN000;
118 TEST [FastSeekflg],FS_begin ; do fastseek ;AN000;
119 JZ do_norm ; no ;AN000;
120 TEST [FastSeekflg],FS_insert ; is in insert mode ? ;AN000;
121 JNZ do_norm ; yes ;AN000;
122 MOV [Temp_Var2],BX ; save physical cluster ;AN000;
123 ; PTR P005079
124SKPCLP2:
125 invoke FastSeek_Lookup ; ask for next cluster # ;AN000;
126 JNC clusfound ; yes, we got it ;AN000;
127 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
128 JNZ par_found ; yes, ;AN000;
129 AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000;
130 JMP SHORT do_norm ;AN000;
131 ;AN000;
132par_found:
133 CALL FS_Trunc_EOF ; check EOF and truncate ;AN000;
134 JNC SKPCLP2 ; redo lookup ;AN000;
135noteof:
136 OR [FastSeekflg],FS_insert ; no, start to insert ;AN000;
137 CMP DX,[FSeek_logsave] ; is current better than new? ;AN000;
138 JBE OnCache ; no, let's use new ;AN000;
139 MOV [FSeek_logclus],DX ; use current ;AN000;
140 MOV BX,[Temp_Var2] ; retore pysical cluster ;AN000;
141 MOV DI,BX ; insert cureent cluster ;AN000;
142 invoke FastSeek_Insert ; insert cluster # to ;AN000;
143 INC [FSeek_logclus] ; get next inserted position ;AN000;
144 JMP SHORT do_norm
145OnCache:
146 MOV CX,[FSeek_logclus] ; get the number of clusters ;AN000;
147 SUB CX,[FSeek_logsave] ; we need to skip ;AN000;
148 MOV DX,[FSeek_logsave] ; cluster position ;AN000;
149dodo:
150 INC [FSeek_logsave] ; get next inserted position ;AN000;
151 PUSH [FSeek_logsave] ; logclus=logsave ;AN000;
152 POP [FSeek_logclus] ;AN000;
153
154do_norm:
155
156 invoke UNPACK
157 retc
158
159 invoke FastSeek_Insert ; insert cluster # to ;AN000;
160cluss: ;AN000;
161 PUSH BX ; FastSeek ;AN000;
162 MOV BX,DI
163 Invoke IsEOF
164 POP BX
165 JAE RET10
166 XCHG BX,DI
167 INC DX
168 INC [FSeek_logclus] ; increment for next inserted ;AN000;
169 LOOP SKPCLPX
170 JMP short RET10
171SKPCLPX:
172 JMP SKPCLP
173RET10: ;AN000;
174 AND [FastSeekflg],FS_no_insert ; clear insert mode
175 CLC
176 return
177NOCLUS:
178 POP ES
179 INC CX
180 DEC DX
181 CLC
182 return
183clusfound:
184 MOV DX,[FSeek_logclus] ; get cluster position ;AN000;
185 MOV BX,[FSeek_logsave] ; bx=previous cluster # PTM ;AN000;
186 DEC DX ;AN000;
187 MOV CX,1 ; we found it ;AN000;
188 JMP cluss ;AN000;
189
190EndProc FNDCLUS
191
192Break <BUFSEC -- BUFFER A SECTOR AND SET UP A TRANSFER>
193
194; Inputs:
195; AH = priority of buffer
196; AL = 0 if buffer must be read, 1 if no pre-read needed
197; ES:BP = Base of drive parameters
198; [CLUSNUM] = Physical cluster number
199; [SECCLUSPOS] = Sector position of transfer within cluster
200; [BYTCNT1] = Size of transfer
201; Function:
202; Insure specified sector is in buffer, flushing buffer before
203; read if necessary.
204; Outputs:
205; ES:DI = Pointer to buffer
206; SI = Pointer to transfer address
207; CX = Number of bytes
208; [NEXTADD] updated
209; [TRANS] set to indicate a transfer will occur
210; Carry set if error (user FAILed to I 24)
211
212 procedure BUFSEC,NEAR
213 DOSAssume CS,<DS>,"BufSec"
214 ASSUME ES:NOTHING
215
216 Assert ISDPB,<ES,BP>,"BufSec"
217 MOV DX,[CLUSNUM]
218 MOV BL,[SECCLUSPOS]
219 MOV [ALLOWED],allowed_FAIL + allowed_RETRY + allowed_IGNORE
220 CALL FIGREC
221 invoke GETBUFFR
222 retc
223 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
224 MOV SI,[NEXTADD]
225 MOV DI,SI
226 MOV CX,[BYTCNT1]
227 ADD DI,CX
228 MOV [NEXTADD],DI
229 LES DI,[CURBUF]
230 Assert ISBUF,<ES,DI>,"BufSec"
231 OR ES:[DI.buf_flags],buf_isDATA
232 LEA DI,[DI].BUFINSIZ ; Point to buffer
233 ADD DI,[BYTSECPOS]
234 CLC
235 return
236EndProc BUFSEC
237
238Break <BUFRD, BUFWRT -- PERFORM BUFFERED READ AND WRITE>
239
240; Do a partial sector read via one of the system buffers
241; ES:BP Points to DPB
242; Carry set if error (currently user FAILed to I 24)
243
244 procedure BUFRD,NEAR
245 DOSAssume CS,<DS>,"BufRd"
246 ASSUME ES:NOTHING
247
248 Assert ISDPB,<ES,BP>,"BufRd"
249 PUSH ES
250 MOV AX,0
251 CALL BUFSEC
252 JNC BUF_OK
253BUF_IO_FAIL:
254 POP ES
255 JMP SHORT RBUFPLACED
256
257BUF_OK:
258 MOV BX,ES
259 MOV ES,[DMAADD+2]
260 MOV DS,BX
261ASSUME DS:NOTHING
262 XCHG DI,SI
263 SHR CX,1
264 JNC EVENRD
265 MOVSB
266EVENRD:
267 REP MOVSW
268 POP ES
269 LDS DI,[CURBUF]
270 Assert ISBUF,<DS,DI>,"BufRD/EvenRD"
271 LEA BX,[DI.BufInSiz]
272 SUB SI,BX ; Position in buffer
273 invoke PLACEBUF
274 Assert ISDPB,<ES,BP>,"BufRD/EvenRD"
275 CMP SI,ES:[BP.dpb_sector_size] ; Read Last byte?
276 JB RBUFPLACEDC ; No, leave buf where it is
277 invoke PLACEHEAD ; Make it prime candidate for chucking
278 ; even though it is MRU.
279RBUFPLACEDC:
280 CLC
281RBUFPLACED:
282 PUSH SS
283 POP DS
284 return
285EndProc BUFRD
286
287; Do a partial sector write via one of the system buffers
288; ES:BP Points to DPB
289; Carry set if error (currently user FAILed to I 24)
290
291 procedure BUFWRT,NEAR
292 DOSAssume CS,<DS>,"BufWrt"
293 ASSUME ES:NOTHING
294
295 Assert ISDPB,<ES,BP>,"BufWrt"
296 MOV AX,WORD PTR [SECPOS]
297 ADD AX,1 ; Set for next sector
298 MOV WORD PTR [SECPOS],AX ;F.C. >32mb ;AN000;
299 ADC WORD PTR [SECPOS+2],0 ;F.C. >32mb ;AN000;
300 MOV AX,WORD PTR [SECPOS+2] ;F.C. >32mb ;AN000;
301 CMP AX,WORD PTR [VALSEC+2] ;F.C. >32mb ;AN000;
302 MOV AL,1 ;F.C. >32mb ;AN000;
303 JA NOREAD ;F.C. >32mb ;AN000;
304 JB doread ;F.C. >32mb ;AN000;
305 MOV AX,WORD PTR [SECPOS] ;F.C. >32mb ;AN000;
306 CMP AX,WORD PTR [VALSEC] ; Has sector been written before?
307 MOV AL,1
308 JA NOREAD ; Skip preread if SECPOS>VALSEC
309doread:
310 XOR AL,AL
311NOREAD:
312 PUSH ES
313 CALL BUFSEC
314 JC BUF_IO_FAIL
315 MOV DS,[DMAADD+2]
316ASSUME DS:NOTHING
317 SHR CX,1
318 JNC EVENWRT
319 MOVSB
320EVENWRT:
321 REP MOVSW
322 POP ES
323 LDS BX,[CURBUF]
324 Assert ISBUF,<DS,BX>,"BufWrt/EvenWrt"
325
326 TEST [BX.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
327 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
328 invoke INC_DIRTY_COUNT ;LB. ;AN000;
329 OR [BX.buf_flags],buf_dirty
330yesdirty:
331 LEA SI,[BX.BufInSiz]
332 SUB DI,SI ; Position in buffer
333 MOV SI,DI
334 MOV DI,BX
335 invoke PLACEBUF
336 Assert ISDPB,<ES,BP>,"BufWrt/EvenWrt"
337 CMP SI,ES:[BP.dpb_sector_size] ; Written last byte?
338 JB WBUFPLACED ; No, leave buf where it is
339 invoke PLACEHEAD ; Make it prime candidate for chucking
340 ; even though it is MRU.
341WBUFPLACED:
342 CLC
343 PUSH SS
344 POP DS
345 return
346EndProc BUFWRT
347
348Break <NEXTSEC -- Compute next sector to read or write>
349
350; Compute the next sector to read or write
351; ES:BP Points to DPB
352
353 procedure NEXTSEC,NEAR
354 DOSAssume CS,<DS>,"NextSec"
355 ASSUME ES:NOTHING
356
357 Assert ISDPB,<ES,BP>,"NextSec"
358 TEST BYTE PTR [TRANS],-1
359 JZ CLRET
360 MOV AL,[SECCLUSPOS]
361 INC AL
362 CMP AL,ES:[BP.dpb_cluster_mask]
363 JBE SAVPOS
364 MOV BX,[CLUSNUM]
365 Invoke IsEOF
366 JAE NONEXT
367;; 11/5/86 FastSeek
368 TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000;
369 JZ do_norm2 ; no ;AN000;
370 PUSH [LASTPOS] ; save logical cluster # ;AN000;
371 POP [FSeek_logclus] ;AN000;
372 INC [FSeek_logclus] ; get next cluster ;AN000;
373 ;AN000;
374 TEST [FastSeekflg],FS_begin ; from R/W ;AN000;
375 JZ do_norm2 ; no ;AN000;
376look2: ;AN000;
377 invoke FastSeek_Lookup ; call lookup ;AN000;
378 JNC clusgot ; found one ;AN000;
379
380 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
381 JNZ parfound2 ; yes, ;AN000;
382 AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000;
383 JMP SHORT do_norm2 ;AN000;
384parfound2:
385 CALL FS_TRUNC_EOF ; check EOF ;AN000;
386 MOV BX,[CLUSNUM] ; don't need partially found cluster
387 OR [FastSeekflg],FS_insert ; prepared for cluster insertion ;AN000;
388 ; use the old bx ;AN000;
389 ;AN000;
390do_norm2:
391 invoke UNPACK
392 JC NONEXT
393 invoke FastSeek_Insert ; call insert ;AN000;
394 AND [FastSeekflg],FS_no_insert ; clear insert flag ;AN000;
395 ;AN000;
396clusgot:
397;; 11/5/86 FastSeek
398 MOV [CLUSNUM],DI
399 INC [LASTPOS]
400 MOV AL,0
401SAVPOS:
402 MOV [SECCLUSPOS],AL
403CLRET:
404 CLC
405 return
406NONEXT:
407 STC
408 return
409EndProc NEXTSEC
410
411Break <OPTIMIZE -- DO A USER DISK REQUEST WELL>
412
413; Inputs:
414; BX = Physical cluster
415; CX = No. of records
416; DL = sector within cluster
417; ES:BP = Base of drives parameters
418; [NEXTADD] = transfer address
419; Outputs:
420; AX = No. of records remaining
421; BX = Transfer address
422; CX = No. or records to be transferred
423; DX = Physical sector address (LOW)
424; [HIGH_SECTOR] = Physical sector address (HIGH)
425; DI = Next cluster
426; [CLUSNUM] = Last cluster accessed
427; [NEXTADD] updated
428; Carry set if error (currently user FAILed to I 24)
429; ES:BP unchanged. Note that segment of transfer not set.
430
431 procedure OPTIMIZE,NEAR
432 DOSAssume CS,<DS>,"Optimize"
433 ASSUME ES:NOTHING
434
435 Assert ISDPB,<ES,BP>,"Optimize"
436 PUSH DX
437 PUSH BX
438 MOV AL,ES:[BP.dpb_cluster_mask]
439 INC AL ; Number of sectors per cluster
440 MOV AH,AL
441 SUB AL,DL ; AL = Number of sectors left in first cluster
442 MOV DX,CX
443 MOV CX,0
444;;; 11/5/86 FastSeek
445 PUSH [LASTPOS] ; save logical cluster # ;AN000;
446 POP [FSeek_logclus] ;AN000;
447 INC [FSeek_logclus] ; get next cluster ;AN000;
448 ;AN000;
449OPTCLUS:
450; AL has number of sectors available in current cluster
451; AH has number of sectors available in next cluster
452; BX has current physical cluster
453; CX has number of sequential sectors found so far
454; DX has number of sectors left to transfer
455; ES:BP Points to DPB
456; ES:SI has FAT pointer
457
458 TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000;
459 JZ do_norm3 ; no ;AN000;
460 TEST [FastSeekflg],FS_begin ; from R/W ;AN000;
461 JZ do_norm3 ; no ;AN000;
462 TEST [FastSeekflg],FS_insert ; is in insert mode ? ;AN000;
463 JNZ do_norm3 ; yes ;AN000;
464 invoke FastSeek_Lookup ; call lookup ;AN000;
465 JNC clusgot2 ; found one ;AN000;
466
467 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
468 JNZ par_found3 ; yes, ;AN000;
469 AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000;
470 JMP SHORT do_norm3 ;AN000;
471par_found3:
472 PUSH BX
473 CALL FS_TRUNC_EOF ; file entry not existing ;AN000;
474 POP BX ;AN000;
475 OR [FastSeekflg],FS_insert ; prepare for insertion ;AN000;
476 ; use old bx ;AN000;
477do_norm3:
478 invoke UNPACK
479 JC OP_ERR
480clusgot2:
481 invoke FastSeek_Insert ; call insert ;AN000;
482 INC [FSeek_logclus] ; insert to next position ;AN000;
483;;; 11/5/86 FastSeek ;AN000;
484 ADD CL,AL
485 ADC CH,0
486 CMP CX,DX
487 JAE BLKDON
488 MOV AL,AH
489 INC BX
490 CMP DI,BX
491 JZ OPTCLUS
492 DEC BX
493FINCLUS:
494 MOV [CLUSNUM],BX ; Last cluster accessed
495 SUB DX,CX ; Number of sectors still needed
496 PUSH DX
497 MOV AX,CX
498 MUL ES:[BP.dpb_sector_size] ; Number of sectors times sector size
499 MOV SI,[NEXTADD]
500 ADD AX,SI ; Adjust by size of transfer
501 MOV [NEXTADD],AX
502 POP AX ; Number of sectors still needed
503 POP DX ; Starting cluster
504 SUB BX,DX ; Number of new clusters accessed
505 ADD [LASTPOS],BX
506 POP BX ; BL = sector postion within cluster
507 invoke FIGREC
508 MOV BX,SI
509 AND [FastSeekflg],FS_no_insert ; clear insert flag
510 CLC
511 return
512
513OP_ERR:
514 ADD SP,4
515 AND [FastSeekflg],FS_no_insert ; clear insert flag
516 STC
517 return
518
519BLKDON:
520 SUB CX,DX ; Number of sectors in cluster we don't want
521 SUB AH,CL ; Number of sectors in cluster we accepted
522 DEC AH ; Adjust to mean position within cluster
523 MOV [SECCLUSPOS],AH
524 MOV CX,DX ; Anyway, make the total equal to the request
525 JMP SHORT FINCLUS
526EndProc OPTIMIZE
527
528Break <FIGREC -- Figure sector in allocation unit>
529
530; Inputs:
531; DX = Physical cluster number
532; BL = Sector postion within cluster
533; ES:BP = Base of drive parameters
534; Outputs:
535; DX = physical sector number (LOW)
536; [HIGH_SECTOR] Physical sector address (HIGH)
537; No other registers affected.
538
539 procedure FIGREC,NEAR
540ASSUME DS:NOTHING,ES:NOTHING
541
542 Assert ISDPB,<ES,BP>,"FigRec"
543 PUSH CX
544 MOV CL,ES:[BP.dpb_cluster_shift]
545 DEC DX
546 DEC DX
547 MOV [HIGH_SECTOR],0 ;F.C. >32mb
548 OR CL,CL ;F.C. >32mb
549 JZ noshift ;F.C. >32mb
550 XOR CH,CH ;F.C. >32mb
551rotleft: ;F.C. >32mb
552 CLC ;F.C. >32mb
553 RCL DX,1 ;F.C. >32mb
554 RCL [HIGH_SECTOR],1 ;F.C. >32mb
555 LOOP rotleft ;F.C. >32mb
556noshift:
557
558; SHL DX,CL
559 OR DL,BL
560 ADD DX,ES:[BP.dpb_first_sector]
561 ADC [HIGH_SECTOR],0 ;F.C. >32mb
562 POP CX
563 return
564EndProc FIGREC
565
566Break <ALLOCATE -- Assign disk space>
567
568;*** ALLOCATE - Allocate Disk Space
569;
570; ALLOCATE is called to allocate disk clusters. The new clusters are
571; FAT-chained onto the end of the existing file.
572;
573; The DPB contains the cluster # of the last free cluster allocated
574; (dpb_next_free). We start at this cluster and scan towards higher
575; numbered clusters, looking for the necessary free blocks.
576;
577; Once again, fancy terminology gets in the way of corrct coding. When
578; using next_free, start scanning AT THAT POINT and not the one following it.
579; This fixes the boundary condition bug when only free = next_free = 2.
580;
581; If we get to the end of the disk without satisfaction:
582;
583; if (dpb_next_free == 2) then we've scanned the whole disk.
584; return (insufficient_disk_space)
585; ELSE
586; dpb_next_free = 2; start scan over from the beginning.
587;
588; Note that there is no multitasking interlock. There is no race when
589; examining the entrys in an in-core FAT block since there will be no
590; context switch. When UNPACK context switches while waiting for a FAT read
591; we are done with any in-core FAT blocks, so again there is no race. The
592; only special concern is that V2 and V3 MSDOS left the last allocated
593; cluster as "00"; marking it EOF only when the entire alloc request was
594; satisfied. We can't allow another activation to think this cluster is
595; free, so we give it a special temporary mark to show that it is, indeed,
596; allocated.
597;
598; Note that when we run out of space this algorithem will scan from
599; dpb_next_free to the end, then scan from cluster 2 through the end,
600; redundantly scanning the later part of the disk. This only happens when
601; we run out of space, so sue me.
602;
603;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
604; C A V E A T P A T T E R S O N ;
605; ;
606; The use of FATBYT and RESTFATBYT is somewhat mysterious. Here is the
607; explanation:
608;
609; In the NUL file case (sf_firclus currently 0) ALLOCATE is called with
610; entry BX = 0. What needs to be done in this case is to stuff the cluster
611; number of the first cluster allocated in sf_firclus when the ALLOCATE is
612; complete. THIS VALUE IS SAVED TEMPORARILY IN CLUSTER 0, HENCE THE CURRENT
613; VALUE IN CLUSTER 0 MUST BE SAVED AND RESTORED. This is a side effect of
614; the fact that PACK and UNPACK don't treat requests for clusters 0 and 1 as
615; errors. This "stuff" is done by the call to PACK which is right before
616; the
617; LOOP findfre ; alloc more if needed
618; instruction when the first cluster is allocated to the nul file. The
619; value is recalled from cluster 0 and stored at sf_firclus at ads4:
620;
621; This method is obviously useless (because it is non-reentrant) for
622; multitasking, and will have to be changed. Storing the required value on
623; the stack is recommended. Setting sf_firclus at the PACK of cluster 0
624; (instead of actually doing the PACK) is BAD because it doesn't handle
625; problems with INT 24 well.
626;
627; C A V E A T P A T T E R S O N ;
628;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
629; ;
630; ENTRY BX = Last cluster of file (0 if null file)
631; CX = No. of clusters to allocate
632; ES:BP = Base of drive parameters
633; [THISSFT] = Points to SFT
634;
635; EXIT 'C' set if insufficient space
636; [FAILERR] can be tested to see the reason for failure
637; CX = max. no. of clusters that could be added to file
638; 'C' clear if space allocated
639; BX = First cluster allocated
640; FAT is fully updated
641; sf_FIRCLUS field of SFT set if file was null
642;
643; USES ALL but SI, BP
644
645 PROCEDURE ALLOCATE,NEAR
646
647 DOSAssume CS,<DS>,"Allocate"
648 ASSUME ES:NOTHING
649
650 Assert ISDPB,<ES,BP>,"Allocate"
651 PUSH BX ; save (bx)
652 XOR BX,BX
653 invoke UNPACK
654 MOV [FATBYT],DI ; save correct cluster 0 value
655 POP BX
656 retc ; abort if error [INTERR?]
657
658 PUSH CX
659 PUSH BX
660
661 MOV DX,BX
662 Assert ISDPB,<ES,BP>,"Allocate/Unpack"
663 mov bx,es:[bp.dpb_next_free]
664 cmp bx,2
665 ja findfre
666
667; couldn't find enough free space beyond dpb_next_free, or dpb_next_free is
668; <2 or >dpb_max_clus. Reset it and restart the scan
669
670ads1:
671 Assert ISDPB,<ES,BP>,"Alloc/ads1"
672 mov es:[bp.dpb_next_free],2
673 mov bx,1 ; Counter next instruction so first
674 ; cluster examined is 2
675
676; Scanning both forwards and backwards for a free cluster
677;
678; (BX) = forwards scan pointer
679; (CX) = clusters remaining to be allocated
680; (DX) = current last cluster in file
681; (TOS) = last cluster of file
682
683FINDFRE:
684 INC BX
685 Assert ISDPB,<ES,BP>,"Alloc/findfre"
686 CMP BX,ES:[BP.dpb_max_cluster]
687 JBE aupk
688 jmp ads7 ; at end of disk
689aupk:
690 invoke UNPACK ; check out this cluster
691 jc ads4 ; FAT error [INTERR?]
692 jnz findfre ; not free, keep on truckin
693
694; Have found a free cluster. Chain it to the file
695;
696; (BX) = found free cluster #
697; (DX) = current last cluster in file
698
699 mov es:[bp.dpb_next_free],bx ; next time start search here
700 xchg ax,dx ; save (dx) in ax
701 mov dx,1 ; mark this free guy as "1"
702 invoke PACK ; set special "temporary" mark
703 jc ads4 ; FAT error [INTERR?]
704 CMP ES:[BP.dpb_free_cnt],-1 ; Free count valid?
705 JZ NO_ALLOC ; No
706 DEC ES:[BP.dpb_free_cnt] ; Reduce free count by 1
707NO_ALLOC:
708 xchg ax,dx ; (dx) = current last cluster in file
709 XCHG BX,DX
710 MOV AX,DX
711 invoke PACK ; link free cluster onto file
712 ; CAVEAT.. On Nul file, first pass stuffs
713 ; cluster 0 with FIRCLUS value.
714 jc ads4 ; FAT error [INTERR?]
715 xchg BX,AX ; (BX) = last one we looked at
716 mov dx,bx ; (dx) = current end of file
717 LOOP findfre ; alloc more if needed
718
719; We've successfully extended the file. Clean up and exit
720;
721; (BX) = last cluster in file
722
723 MOV DX,0FFFFH
724 invoke PACK ; mark last cluster EOF
725
726; Note that FAT errors jump here to clean the stack and exit. this saves us
727; 2 whole bytes. Hope its worth it...
728;
729; 'C' set iff error
730; calling (BX) and (CX) pushed on stack
731
732ads4: POP BX
733 POP CX ; Don't need this stuff since we're successful
734 retc
735 invoke UNPACK ; Get first cluster allocated for return
736 ; CAVEAT... In nul file case, UNPACKs cluster 0.
737 retc
738 invoke RESTFATBYT ; Restore correct cluster 0 value
739 retc
740 XCHG BX,DI ; (DI) = last cluster in file upon our entry
741 OR DI,DI ; clear 'C'
742 retnz ; we were extending an existing file
743
744; We were doing the first allocation for a new file. Update the SFT cluster
745; info
746;; Extended Attributes
747; TEST [XA_condition],XA_No_SFT ;FT. don't update SFT when from ;AN000;
748; JZ dofastk ;FT. GetSet_XA ;AN000;
749; AND [XA_condition],not XA_No_SFT ;FT. clear the bit ;AN000;
750; CLC ;FT. ;AN000;
751; ret ;FT. ;AN000;
752;; 11/6/86 FastSeek
753dofastk:
754 PUSH DX
755 MOV DL,ES:[BP.dpb_drive] ; get drive #
756
757 PUSH ES
758 LES DI,[THISSFT]
759 Assert ISSFT,<ES,DI>,"Allocate/ads4"
760 MOV ES:[DI.sf_firclus],BX
761 MOV ES:[DI.sf_lstclus],BX
762
763 TEST [FastSeekflg],Fast_yes ; fastseek installed
764 JZ do_norm5 ; no
765 TEST [FastSeekflg],FS_begin ; do fastseek
766 JZ do_norm5 ; no
767 PUSH CX
768 MOV CX,BX ; set up firclus #
769 MOV [FSeek_firclus],BX ; update firclus varible
770 invoke FastSeek_Open ; create this file entry
771 POP CX
772do_norm5:
773 POP ES
774;; 11/6/86 FastSeek
775 POP DX
776 return
777
778
779;** we're at the end of the disk, and not satisfied. See if we've scanned ALL
780; of the disk...
781
782ads7: cmp es:[bp.dpb_next_free],2
783if not debug
784 jz tmplab2 ;
785 jmp ads1 ; start scan from front of disk
786tmplab2:
787else
788 jz tmplab
789 jmp ads1
790tmplab:
791endif
792
793; Sorry, we've gone over the whole disk, with insufficient luck. Lets give
794; the space back to the free list and tell the caller how much he could have
795; had. We have to make sure we remove the "special mark" we put on the last
796; cluster we were able to allocate, so it doesn't become orphaned.
797;
798; (CX) = clusters remaining to be allocated
799; (TOS) = last cluster of file (before call to ALLOCATE)
800; (TOS+1) = # of clusters wanted to allocate
801
802
803 POP BX ; (BX) = last cluster of file
804 MOV DX,0FFFFH
805 invoke RELBLKS ; give back any clusters just alloced
806 POP AX ; No. of clusters requested
807 ; Don't "retc". We are setting Carry anyway,
808 ; Alloc failed, so proceed with return CX
809 ; setup.
810 SUB AX,CX ; AX=No. of clusters allocated
811 invoke RESTFATBYT ; Don't "retc". We are setting Carry anyway,
812 ; Alloc failed.
813; fmt <>,<>,<"$p: disk full in allocate\n">
814 MOV [DISK_FULL],1 ;MS. indicating disk full
815 STC
816 return
817
818EndProc ALLOCATE
819
820; SEE ALLOCATE CAVEAT
821; Carry set if error (currently user FAILed to I 24)
822
823 procedure RESTFATBYT,NEAR
824 DOSAssume CS,<DS>,"RestFATByt"
825 ASSUME ES:NOTHING
826
827 PUSH BX
828 PUSH DX
829 PUSH DI
830 XOR BX,BX
831 MOV DX,[FATBYT]
832 invoke PACK
833 POP DI
834 POP DX
835 POP BX
836 return
837EndProc RESTFATBYT
838
839Break <RELEASE -- DEASSIGN DISK SPACE>
840
841; Inputs:
842; BX = Cluster in file
843; ES:BP = Base of drive parameters
844; Function:
845; Frees cluster chain starting with [BX]
846; Carry set if error (currently user FAILed to I 24)
847; AX,BX,DX,DI all destroyed. Other registers unchanged.
848
849 procedure RELEASE,NEAR
850 DOSAssume CS,<DS>,"Release"
851 ASSUME ES:NOTHING
852
853 XOR DX,DX
854entry RELBLKS
855 DOSAssume CS,<DS>,"RelBlks"
856 Assert ISDPB,<ES,BP>,"RelBlks"
857
858; Enter here with DX=0FFFFH to put an end-of-file mark in the first cluster
859; and free the rest in the chain.
860
861 invoke UNPACK
862 retc
863 retz
864 MOV AX,DI
865 PUSH DX
866 invoke PACK
867 POP DX
868 retc
869 OR DX,DX
870 JNZ NO_DEALLOC ; Was putting EOF mark
871 CMP ES:[BP.dpb_free_cnt],-1 ; Free count valid?
872 JZ NO_DEALLOC ; No
873 INC ES:[BP.dpb_free_cnt] ; Increase free count by 1
874NO_DEALLOC:
875 MOV BX,AX
876 dec ax ; check for "1"
877 retz ; is last cluster of incomplete chain
878 Invoke IsEOF
879 JB RELEASE ; Carry clear if JMP not taken
880ret12: return
881EndProc RELEASE
882
883Break <GETEOF -- Find the end of a file>
884
885; Inputs:
886; ES:BP Points to DPB
887; BX = Cluster in a file
888; DS = CS
889; Outputs:
890; BX = Last cluster in the file
891; Carry set if error (currently user FAILed to I 24)
892; DI destroyed. No other registers affected.
893
894 procedure GETEOF,NEAR
895 DOSAssume CS,<DS>,"GetEOF"
896 ASSUME ES:NOTHING
897
898 Assert ISDPB,<ES,BP>,"GetEof"
899 invoke UNPACK
900 retc
901 PUSH BX
902 MOV BX,DI
903 Invoke IsEOF
904 POP BX
905 JAE RET12 ; Carry clear if jmp
906 MOV BX,DI
907 JMP GETEOF
908EndProc GETEOF
909
910Break <FS_TRUNC_EOF - truncate EOF for Fastseek>
911
912; Inputs:
913; ES:BP Points to DPB
914; BX = Cluster in a file
915; Functions: if BX=EOF then truncate it from Fastseek Cache
916; Outputs:
917; carry set: not EOF
918; carry clear: EOF and do truncate
919
920 procedure FS_TRUNC_EOF,NEAR
921 ASSUME ES:NOTHING,DS:NOTHING
922
923 MOV BX,DI ; get beginning physical# ;AN000;
924 invoke IsEOF ; is EOF ;AN000;
925 JB noteof2 ; no ;AN000;
926 PUSH [FSeek_logclus] ; ;AN000;
927 PUSH [FSeek_logsave] ; logclus=logsave ;AN000;
928 POP [FSeek_logclus] ; delete EOF ;AN000;
929 invoke FastSeek_Truncate ; ;AN000;
930 POP [FSeek_logclus] ; redo the look up ;AN000;
931 CLC ;AN000;
932noteof2: ;AN000;
933 return ;AN000;
934EndProc FS_TRUNC_EOF ;AN000;
935
936CODE ENDS
937 END
938 \ No newline at end of file
diff --git a/v4.0/src/DOS/SEARCH.ASM b/v4.0/src/DOS/SEARCH.ASM
new file mode 100644
index 0000000..1f23942
--- /dev/null
+++ b/v4.0/src/DOS/SEARCH.ASM
@@ -0,0 +1,346 @@
1; SCCSID = @(#)search.asm 1.1 85/04/10
2TITLE SEARCH - Directory scan system calls
3NAME SEARCH
4
5;
6;
7; Directory search system calls. These will be passed direct text of the
8; pathname from the user. They will need to be passed through the macro
9; expander prior to being sent through the low-level stuff. I/O specs are
10; defined in DISPATCH. The system calls are:
11;
12;
13; $Dir_Search_First written
14; $Dir_Search_Next written
15; $Find_First written
16; $Find_Next written
17; PackName written
18;
19; Modification history:
20;
21; Created: ARR 4 April 1983
22;
23
24.xlist
25;
26; get the appropriate segment definitions
27;
28include dosseg.asm
29
30CODE SEGMENT BYTE PUBLIC 'CODE'
31 ASSUME SS:DOSGroup,CS:DOSGroup
32
33.xcref
34INCLUDE DOSSYM.INC
35INCLUDE DEVSYM.INC
36INCLUDE fastopen.inc
37INCLUDE fastxxxx.inc
38.cref
39.list
40
41 i_need SEARCHBUF,53
42 i_need SATTRIB,BYTE
43 I_Need OpenBuf,128
44 I_need DMAAdd,DWORD
45 I_need THISFCB,DWORD
46 I_need CurDrv,BYTE
47 I_need EXTFCB,BYTE
48 I_need Fastopenflg,BYTE
49 I_need DOS34_FLAG,WORD
50
51; Inputs:
52; DS:DX Points to unopenned FCB
53; Function:
54; Directory is searched for first matching entry and the directory
55; entry is loaded at the disk transfer address
56; Returns:
57; AL = -1 if no entries matched, otherwise 0
58
59 procedure $DIR_SEARCH_FIRST,NEAR
60ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
61
62 MOV WORD PTR [THISFCB],DX
63 MOV WORD PTR [THISFCB+2],DS
64 MOV SI,DX
65 CMP BYTE PTR [SI],0FFH
66 JNZ NORMFCB4
67 ADD SI,7 ; Point to drive select byte
68NORMFCB4:
69 SaveReg <[SI]> ; Save original drive byte for later
70 Context ES ; get es to address DOSGroup
71 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
72 invoke TransFCB ; convert the FCB, set SATTRIB EXTFCB
73 JNC SearchIt ; no error, go and look
74 RestoreReg <BX> ; Clean stack
75;
76; Error code is in AX
77;
78 transfer FCB_Ret_Err ; error
79
80SearchIt:
81 Context DS ; get ready for search
82 SaveReg <<WORD PTR [DMAAdd]>, <WORD PTR [DMAAdd+2]>>
83 MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF
84 MOV WORD PTR [DMAAdd+2],DS
85 invoke GET_FAST_SEARCH ; search
86 RestoreReg <<WORD PTR [DMAAdd+2]>, <WORD PTR [DMAAdd]>>
87 JNC SearchSet ; no error, transfer info
88 RestoreReg <BX> ; Clean stack
89;
90; Error code is in AX
91;
92 transfer FCB_Ret_Err
93
94;
95; The search was successful (or the search-next). We store the information
96; into the user's FCB for continuation.
97;
98SearchSet:
99 MOV SI,OFFSET DOSGroup:SEARCHBUF
100 LES DI,[THISFCB] ; point to the FCB
101 TEST [EXTFCB],0FFH ;
102 JZ NORMFCB1
103 ADD DI,7 ; Point past the extension
104NORMFCB1:
105 RestoreReg <BX> ; Get original drive byte
106 OR BL,BL
107 JNZ SearchDrv
108 MOV BL,[CurDrv]
109 INC BL
110SearchDrv:
111 LODSB ; Get correct search contin drive byte
112 XCHG AL,BL ; Search byte to BL, user byte to AL
113 INC DI
114; STOSB ; Store the correct "user" drive byte
115 ; at the start of the search info
116 MOV CX,20/2
117 REP MOVSW ; Rest of search cont info, SI -> entry
118 XCHG AL,BL ; User drive byte back to BL, search
119 ; byte to AL
120 STOSB ; Search contin drive byte at end of
121 ; contin info
122 LES DI,[DMAAdd]
123 TEST [EXTFCB],0FFH
124 JZ NORMFCB2
125 MOV AL,0FFH
126 STOSB
127 INC AL
128 MOV CX,5
129 REP STOSB
130 MOV AL,[SATTRIB]
131 STOSB
132NORMFCB2:
133 MOV AL,BL ; User Drive byte
134 STOSB
135 IF DBCS ;AN000;
136 MOVSW ; 2/13/KK ;AN000;
137 CMP BYTE PTR ES:[DI-2],5 ; 2/13/KK ;AN000;
138 JNZ NOTKTRAN ; 2/13/KK ;AN000;
139 MOV BYTE PTR ES:[DI-2],0E5H ; 2/13/KK ;AN000;
140NOTKTRAN: ; 2/13/KK ;AN000;
141 MOV CX,15 ; 2/13/KK ;AN000;
142 ELSE ;AN000;
143 MOV CX,16 ; 32 / 2 words of dir entry ;AN000;
144 ENDIF ;AN000;
145 REP MOVSW
146 transfer FCB_Ret_OK
147
148EndProc $DIR_SEARCH_FIRST
149
150; Inputs:
151; DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
152; Function:
153; Directory is searched for the next matching entry and the directory
154; entry is loaded at the disk transfer address
155; Returns:
156; AL = -1 if no entries matched, otherwise 0
157
158 procedure $DIR_SEARCH_NEXT,NEAR
159ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
160
161 MOV WORD PTR [THISFCB],DX
162 MOV WORD PTR [THISFCB+2],DS
163 MOV [SATTRIB],0
164 MOV [EXTFCB],0
165 Context ES
166 MOV DI,OFFSET DOSGroup:SEARCHBUF
167 MOV SI,DX
168 CMP BYTE PTR [SI],0FFH
169 JNZ NORMFCB6
170 ADD SI,6
171 LODSB
172 MOV [SATTRIB],AL
173 DEC [EXTFCB]
174NORMFCB6:
175 LODSB ; Get original user drive byte
176 SaveReg <AX> ; Put it on stack
177 MOV AL,[SI+20] ; Get correct search contin drive byte
178 STOSB ; Put in correct place
179 MOV CX,20/2
180 REP MOVSW ; Transfer in rest of search contin info
181 Context DS
182 SaveReg <<WORD PTR [DMAAdd]>, <WORD PTR [DMAAdd+2]>>
183 MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF
184 MOV WORD PTR [DMAAdd+2],DS
185 invoke DOS_SEARCH_NEXT ; Find it
186 RestoreReg <<WORD PTR [DMAAdd+2]>, <WORD PTR [DMAAdd]>>
187 JC SearchNoMore
188 JMP SearchSet ; Ok set return
189
190SearchNoMore:
191 LES DI,[THISFCB]
192 TEST [EXTFCB],0FFH
193 JZ NORMFCB8
194 ADD DI,7 ; Point past the extension
195NORMFCB8:
196 RestoreReg <BX> ; Get original drive byte
197 MOV ES:[DI],BL ; Store the correct "user" drive byte
198 ; at the right spot
199;
200; error code is in AX
201;
202 transfer FCB_Ret_Err
203
204EndProc $DIR_SEARCH_NEXT
205
206; Assembler usage:
207; MOV AH, FindFirst
208; LDS DX, name
209; MOV CX, attr
210; INT 21h
211; ; DMA address has datablock
212;
213; Error Returns:
214; AX = error_path_not_found
215; = error_no_more_files
216
217 procedure $FIND_FIRST,NEAR
218ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
219
220 MOV SI,DX ; get name in appropriate place
221 MOV [SATTRIB],CL ; Search attribute to correct loc
222 MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
223 invoke TransPathSet ; convert the path
224 JNC Find_it ; no error, go and look
225FindError:
226 error error_path_not_found ; error and map into one.
227Find_it:
228 Context DS
229 SaveReg <<WORD PTR [DMAAdd]>, <WORD PTR [DMAAdd+2]>>
230 MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF
231 MOV WORD PTR [DMAAdd+2],DS
232 invoke GET_FAST_SEARCH ; search
233 RestoreReg <<WORD PTR [DMAAdd+2]>, <WORD PTR [DMAAdd]>>
234 JNC FindSet ; no error, transfer info
235 transfer Sys_Ret_Err
236
237FindSet:
238 MOV SI,OFFSET DOSGroup:SEARCHBUF
239 LES DI,[DMAAdd]
240 MOV CX,21
241 REP MOVSB
242 PUSH SI ; Save pointer to start of entry
243 MOV AL,[SI.dir_attr]
244 STOSB
245 ADD SI,dir_time
246 MOVSW ; dir_time
247 MOVSW ; dir_date
248 INC SI
249 INC SI ; Skip dir_first
250 MOVSW ; dir_size (2 words)
251 MOVSW
252 POP SI ; Point back to dir_name
253 IF DBCS ;AN000;
254 PUSH DI ; XXXX save dest name 2/13/KK ;AN000;
255 CALL PackName ;AN000;
256 POP DI ; XXXX Recover dest name 2/13/KK ;AN000;
257 CMP BYTE PTR ES:[DI],05H ; XXXX Need fix? 2/13/KK ;AN000;
258 JNZ FNXXX ; XXXX No 2/13/KK ;AN000;
259 MOV BYTE PTR ES:[DI],0E5H ; XXXX Yes, Fix 2/13/KK ;AN000;
260FNXXX: ; 2/13/KK ;AN000;
261 ELSE ;AN000;
262 CALL PackName
263 ENDIF
264 transfer Sys_Ret_OK ; bye with no errors
265EndProc $FIND_FIRST
266
267 procedure $FIND_NEXT,NEAR
268ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
269
270; Assembler usage:
271; ; dma points at area returned by find_first
272; MOV AH, findnext
273; INT 21h
274; ; next entry is at dma
275;
276; Error Returns:
277; AX = error_no_more_files
278
279 Context ES
280 MOV DI,OFFSET DOSGroup:SEARCHBUF
281 LDS SI,[DMAAdd]
282 MOV CX,21
283 REP MOVSB ; Put the search continuation info
284 ; in the right place
285 Context DS ; get ready for search
286 SaveReg <<WORD PTR [DMAAdd]>, <WORD PTR [DMAAdd+2]>>
287 MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF
288 MOV WORD PTR [DMAAdd+2],DS
289 invoke DOS_SEARCH_NEXT ; Find it
290 RestoreReg <<WORD PTR [DMAAdd+2]>, <WORD PTR [DMAAdd]>>
291 JNC FindSet ; No error, set info
292 transfer Sys_Ret_Err
293
294EndProc $FIND_NEXT
295
296Break <PackName - convert file names from FCB to ASCIZ>
297;
298; PackName - transfer a file name from DS:SI to ES:DI and convert it to
299; the ASCIZ format.
300;
301; Input: DS:SI points to an 11 character FCB or dir entry name
302; ES:DI points to a destination area (13 bytes)
303; Output: Above pointers advanced
304; Registers modified: SI,DI,CX,AL
305 Procedure PackName,NEAR
306 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
307 MOV CX,8 ; Pack the name
308 REP MOVSB ; Move all of it
309main_kill_tail:
310 CMP BYTE PTR ES:[DI-1]," "
311 JNZ find_check_dot
312 DEC DI ; Back up over trailing space
313 INC CX
314 CMP CX,8
315 JB main_kill_tail
316find_check_dot:
317 CMP WORD PTR [SI],(" " SHL 8) OR " "
318 JNZ got_ext ; Some chars in extension
319 CMP BYTE PTR [SI+2]," "
320 JZ find_done ; No extension
321got_ext:
322 MOV AL,"."
323 STOSB
324 MOV CX,3
325 REP MOVSB
326ext_kill_tail:
327 CMP BYTE PTR ES:[DI-1]," "
328 JNZ find_done
329 DEC DI ; Back up over trailing space
330 JMP ext_kill_tail
331find_done:
332 XOR AX,AX
333 STOSB ; NUL terminate
334 return
335EndProc PackName
336
337 procedure GET_FAST_SEARCH,NEAR
338 ASSUME DS:NOTHING,ES:NOTHING
339
340 OR [DOS34_FLAG],SEARCH_FASTOPEN ;FO.trigger fastopen ;AN000;
341 invoke DOS_SEARCH_FIRST
342 return
343
344EndProc GET_FAST_SEARCH
345CODE ENDS
346END
diff --git a/v4.0/src/DOS/SEGCHECK.ASM b/v4.0/src/DOS/SEGCHECK.ASM
new file mode 100644
index 0000000..992eac2
--- /dev/null
+++ b/v4.0/src/DOS/SEGCHECK.ASM
@@ -0,0 +1,288 @@
1; SCCSID = @(#)segcheck.asm 1.2 85/07/24
2TITLE SegCheck - internal consistency check
3NAME SegCheck
4
5.xlist
6INCLUDE DOSSYM.INC
7INCLUDE DEVSYM.INC
8
9ShareF = FALSE
10
11IF NOT SHAREF
12include dosseg.asm
13ENDIF
14.list
15
16AsmVars <NET, DEBUG>
17
18DEBUG = FALSE
19
20IF NOT SHAREF
21CODE SEGMENT BYTE PUBLIC 'CODE'
22ASSUME CS:DOSGroup
23ELSE
24SHARE SEGMENT BYTE PUBLIC 'SHARE'
25ASSUME CS:SHARE
26ENDIF
27
28DEBUG = FALSE
29
30BREAK <SegCheck - validate segments in MSDOS>
31
32Off Macro reg,var
33IF SHAREF
34 mov reg,offset var
35else
36 mov reg,offset DOSGroup:var
37endif
38endm
39
40zfmt MACRO fmts,args
41local a,b
42 PUSHF
43 PUSH AX
44 PUSH BP
45 MOV BP,SP
46If (not sharef) and (not redirector)
47Table segment
48a db fmts,0
49Table ends
50 MOV AX,OFFSET DOSGROUP:a
51else
52 jmp short b
53a db fmts,0
54if sharef
55b: mov ax,offset share:a
56else
57b: mov ax,offset netwrk:a
58endif
59endif
60 PUSH AX
61cargs = 2
62IRP item,<args>
63IFIDN <AX>,<item>
64 MOV AX,[BP+2]
65ELSE
66 MOV AX,item
67ENDIF
68 PUSH AX
69cargs = cargs + 2
70ENDM
71 invoke PFMT
72 ADD SP,Cargs
73 POP BP
74 POP AX
75 POPF
76ENDM
77
78segFrame Struc
79segbp DW ?
80segip DW ?
81segmes dw ?
82segtemp DW ?
83segFrame ENDS
84;
85; SegCheck - assure that segments are correctly set up
86;
87; Inputs: top of stack points to:
88; 2-byte jump
89; byte flags 04h is ES 02h is DS 01 is CS/SS
90; offset asciz message
91;
92; Outputs: message to screen (via INT 29h)
93; Nothing modified (flags too)
94
95Procedure SegCheck,NEAR
96 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
97 SaveReg <BP>
98 MOV BP,SP ; set up addressing
99 PUSHF
100 SaveReg <AX,BX,CX,DX>
101 MOV AL,BYTE PTR [BP].segtemp; get flags
102 MOV CX,SS
103 TEST AL,1 ; shall we use CS or SS?
104 JZ SegUseSS ; use SS
105 MOV CX,CS ; use CS instead
106SegUseSS:
107 TEST AL,2 ; do we check DS?
108 JZ SegTestES ; no, go check ES
109 MOV DX,DS
110 CMP CX,DX
111 JZ SegTestES ; DS is valid, go check ES
112 MOV AX,[BP].segmes
113 zfmt <"Assumed DS invalid $s\n">,<AX>
114SegTestES:
115 TEST AL,4 ; do we check ES?
116 JZ SegTestDone ; no, all done
117 MOV DX,ES
118 CMP CX,DX
119 JZ SegTestDone ; ES is valid, all done
120 MOV AX,[BP].segmes
121 zfmt <"Assumed ES invalid $s\n">,<AX>
122SegTestDone:
123 RestoreReg <DX,CX,BX,AX>
124 POPF
125 RestoreReg <BP>
126 ret 4 ; release message, temp
127EndProc SegCheck
128
129
130IF NOT SHAREF
131I_need DPBHead,DWORD
132I_need BuffHead,DWORD
133I_need sftFCB,DWORD
134I_need AuxStack,BYTE
135I_need IOStack,BYTE
136I_need renbuf,byte
137I_need CurrentPDB,WORD
138I_need User_In_AX,WORD
139
140extrn ECritDisk:NEAR
141
142CritNOP label byte
143 RET
144
145AstFrame STRUC
146Astbp dw ?
147Astip dw ?
148Astmes dw ?
149Astarg dd ?
150AstFrame ENDS
151
152Public SGCHK001S,SGCHK001E
153SGCHK001S label byte
154DPBMes DB "DPB assertion failed: ",0
155BUFMes DB "BUF assertion failed: ",0
156SFTMes DB "SFT assertion failed: ",0
157BlankSp DB " ",0
158Colon DB ":",0
159
160Msg DW ?
161
162SGCHK001E label byte
163
164Table segment
165 Extrn SectPDB:WORD, SectRef:WORD
166Table ends
167
168; DPBCheck - validate a supposed DPB pointer
169; Inputs: Pushed arguments
170; Outputs: Message to screen
171; Registers modified: none
172
173Procedure DPBCheck,NEAR
174 MOV Msg,OFFSET DOSGroup:DPBMes
175 SaveReg <BP>
176 MOV BP,SP
177 PUSHF
178 SaveReg <AX,BX,DS,SI,ES,DI>
179 LES DI,DPBHead
180 LDS SI,[BP].Astarg
181DPBLoop:CMP DI,-1
182 JZ DPBNotFound
183 invoke PointComp
184 JZ DPBRet
185 LES DI,ES:[DI.dpb_next_dpb]
186 JMP DPBLoop
187DPBNotFound:
188 MOV AX,[BP].Astmes
189 zfmt <"$s$x:$x $s\n">,<msg,ds,si,AX>
190 CLI
191a: JMP a ; slam the door.
192DPBRet: RestoreReg <DI,ES,SI,DS,BX,AX> ; Done:
193 POPF
194 RestoreReg <BP>
195 RET 6
196EndProc DPBCheck
197
198; SFTCheck - validate a supposed SFT pointer
199; Inputs: Pushed arguments
200; Outputs: Message to screen
201; Registers modified: none
202
203Procedure SFTCheck,NEAR
204 MOV Msg,OFFSET DOSGroup:SFTMes
205 SaveReg <BP>
206 MOV BP,SP
207 PUSHF
208 SaveReg <AX,BX,DS,SI,ES,DI>
209 LDS SI,[BP].Astarg
210 XOR BX,BX ; i = 0;
211SFTLoop:
212 SaveReg <BX>
213 invoke SFFromSFN ; while ((d=SF(i)) != NULL)
214 RestoreReg <BX>
215 JC Sft1
216 invoke PointComp
217 JZ DPBRet ; goto Done;
218SFTNext:INC BX ; else
219 JMP SFTLoop ; i++;
220SFT1: LES DI,sftFCB
221 MOV BX,ES:[DI.sfCount]
222 LEA DI,[DI.sfTable]
223SFT2:
224 invoke PointComp
225DPBRETJ:JZ DPBRet
226 ADD DI,SIZE sf_entry
227 DEC BX
228 JNZ SFT2
229;
230; The SFT is not in the allocated tables. See if it is one of the static
231; areas.
232;
233 Context ES
234 MOV DI,OFFSET DOSGROUP:AUXSTACK - SIZE SF_ENTRY
235 Invoke PointComp
236 JZ DPBRet
237 MOV DI,OFFSET DOSGROUP:RenBuf
238 Invoke PointComp
239 JZ DPBRetj
240DPBNotFoundJ:
241 JMP DPBNotFound
242EndProc SFTCheck
243
244; BUFCheck - validate a supposed BUF pointer
245; Inputs: Pushed arguments
246; Outputs: Message to screen
247; Registers modified: none
248
249Procedure BUFCheck,NEAR
250 MOV Msg,OFFSET DOSGroup:BUFMes
251 SaveReg <BP>
252 MOV BP,SP
253 PUSHF
254 SaveReg <AX,BX,DS,SI,ES,DI>
255;
256; CheckDisk - make sure that we are in the disk critical section...
257;
258 MOV AL,BYTE PTR ECritDisk
259 CMP AL,CritNOP
260 JZ CheckDone
261 MOV AX,CurrentPDB
262 CMP SectPDB + 2 * critDisk,AX
263 MOV AX,[BP].astmes
264 JZ CheckRef
265 zfmt <"$p: $x $s critDisk owned by $x\n">,<User_In_AX,AX,SectPDB+2*critDisk>
266CheckRef:
267 CMP SectRef + 2 * critDisk,0
268 JNZ CheckDone
269 zfmt <"$p: $x $s critDisk ref count is 0\n">,<User_In_AX,AX>
270CheckDone:
271
272 LDS SI,[BP].Astarg
273 LES DI,BUFFHead
274BUFLoop:CMP DI,-1
275 JZ DPBNotFoundJ
276 invoke PointComp
277 JNZ BufNext
278 JMP DPBRet
279BufNext:
280 LES DI,ES:[DI.buf_link]
281 JMP BUFLoop
282EndProc BUFCheck
283
284CODE ENDS
285ELSE
286SHARE ENDS
287ENDIF
288END
diff --git a/v4.0/src/DOS/SHARE.ASM b/v4.0/src/DOS/SHARE.ASM
new file mode 100644
index 0000000..ded4cd7
--- /dev/null
+++ b/v4.0/src/DOS/SHARE.ASM
@@ -0,0 +1,151 @@
1; SCCSID = @(#)share.asm 1.1 85/04/10
2TITLE SHARING ROUTINES - Routines for file Sharing
3NAME SHARE
4
5include dosseg.asm
6
7CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME SS:DOSGROUP,CS:DOSGROUP
9
10.xlist
11.xcref
12INCLUDE DOSSYM.INC
13INCLUDE DEVSYM.INC
14.cref
15.list
16
17AsmVars <IBM, Installed>
18
19Installed = True
20
21 i_need THISDPB,DWORD
22 i_need EXTERR,WORD
23 i_need ReadOp,BYTE
24 i_need ThisSFT,DWORD
25 i_need ALLOWED,BYTE
26 I_need RetryCount,WORD
27 i_need JShare,DWORD
28
29; Inputs:
30; [THISSFT] Points to filled in local file/device SFT for new
31; instance of file sf_mode ALWAYS has mode (even on FCB SFTs)
32; [WFP_START] has full path of name
33; [USER_ID] Set
34; [PROC_ID] Set
35; Function:
36; Check for sharing violations on local file/device access
37; Outputs:
38; Carry clear
39; Sharing approved
40; Carry set
41; A sharing violation detected
42; AX is error code
43; USES ALL but DS
44
45 procedure SHARE_CHECK,NEAR
46 DOSAssume CS,<DS>,"Share_Check"
47 ASSUME ES:NOTHING
48
49if installed
50 call JShare + 1 * 4
51else
52 Call MFT_Enter
53endif
54 return
55
56EndProc SHARE_CHECK
57
58; Inputs:
59; [THISDPB] Set
60; AX has error code
61; Function:
62; Handle Sharing errors
63; Outputs:
64; Carry set if user says FAIL, causes error_sharing_violation
65; Carry clear if user wants a retry
66;
67; DS, ES, DI preserved, others destroyed
68
69 procedure SHARE_VIOLATION,NEAR
70 DOSAssume CS,<DS>,"Share_Violation"
71 ASSUME ES:NOTHING
72
73 PUSH DS
74 PUSH ES
75 PUSH DI
76 MOV [READOP],0 ; All share errors are reading
77 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
78 LES BP,[THISDPB]
79 MOV DI,1 ; Fake some registers
80 MOV CX,DI
81 MOV DX,ES:[BP.dpb_dir_sector]
82 invoke HARDERR
83 POP DI
84 POP ES
85 POP DS
86 CMP AL,1
87 retz ; 1 = retry, carry clear
88 STC
89 return
90
91EndProc SHARE_VIOLATION
92
93; ShareEnd - terminate sharing info on a particular SFT/UID/PID. This does
94; NOT perform a close, it merely asserts that the sharing information
95; for the SFT/UID/PID may be safely released.
96;
97; Inputs: ES:DI points to an SFT
98; Outputs: None
99; Registers modified: all except DS,ES,DI
100
101 procedure ShareEnd,Near
102 DOSAssume CS,<DS>,"ShareEnd"
103 ASSUME ES:NOTHING
104
105if installed
106 Call JShare + 2 * 4
107else
108 Call MFTClose
109endif
110 return
111
112EndProc ShareEnd
113
114break <ShareEnter - attempt to enter a node into the sharing set>
115
116;
117; ShareEnter - perform a retried entry of a nodde into the sharing set. If
118; the max number of retries is exceeded, we notify the user via int 24.
119;
120; Inputs: ThisSFT points to the SFT
121; WFP_Start points to the WFP
122; Outputs: Carry clear => successful entry
123; Carry set => failed system call
124; Registers modified: all
125
126Procedure ShareEnter,NEAR
127 DOSAssume CS,<DS>,"ShareEnter"
128 assume es:nothing
129
130 SaveReg <CX>
131retry:
132 mov cx,RetryCount
133attempt:
134 les di,ThisSFT ; grab sft
135 XOR AX,AX
136 MOV ES:[DI.sf_MFT],AX ; indicate free SFT
137 SaveReg <CX>
138 call Share_Check ; attempt to enter into the sharing set
139 RestoreReg <CX>
140 jnc done ; success, let the user see this
141 invoke Idle ; wait a while
142 loop attempt ; go back for another attempt
143 call Share_violation ; signal the problem to the user
144 jnc retry ; user said to retry, go do it
145done:
146 RestoreReg <CX>
147 return
148EndProc ShareEnter
149
150CODE ENDS
151 END
diff --git a/v4.0/src/DOS/SHRPRINT.ASM b/v4.0/src/DOS/SHRPRINT.ASM
new file mode 100644
index 0000000..6854eca
--- /dev/null
+++ b/v4.0/src/DOS/SHRPRINT.ASM
@@ -0,0 +1,35 @@
1; SCCSID = @(#)shrprint.asm 1.1 85/04/10
2TITLE SHRPRINT - PRINTF at SHARE level
3NAME SHRPRINT
4;
5;
6; Modification history:
7;
8; Created: MZ 16 June 1984
9;
10
11.xlist
12;
13; get the appropriate segment definitions
14;
15include dosseg.asm
16
17Share SEGMENT PARA PUBLIC 'SHARE'
18 ASSUME SS:DOSGROUP,CS:SHARE
19
20.xcref
21INCLUDE DOSSYM.INC
22INCLUDE DEVSYM.INC
23.cref
24.list
25.sall
26
27 I_Need Proc_ID,WORD
28 I_Need User_ID,WORD
29
30BREAK <debugging output>
31
32include print.asm
33
34SHARE ENDS
35END
diff --git a/v4.0/src/DOS/SRVCALL.ASM b/v4.0/src/DOS/SRVCALL.ASM
new file mode 100644
index 0000000..26064c8
--- /dev/null
+++ b/v4.0/src/DOS/SRVCALL.ASM
@@ -0,0 +1,306 @@
1; SCCSID = @(#)srvcall.asm 1.4 85/08/02
2TITLE SRVCALL - Server DOS call
3NAME SRVCALL
4;
5; Server DOS call functions
6;
7;
8; $ServerCall
9;
10; Modification history:
11;
12; Created: ARR 08 August 1983
13;
14
15.xlist
16;
17; get the appropriate segment definitions
18;
19include dosseg.asm
20
21CODE SEGMENT BYTE PUBLIC 'CODE'
22 ASSUME SS:DOSGROUP,CS:DOSGROUP
23
24.xcref
25INCLUDE DOSSYM.INC
26INCLUDE DEVSYM.INC
27.cref
28.list
29
30AsmVars <Installed>
31
32include dpl.asm
33
34Installed = TRUE
35
36 i_need USER_ID,WORD
37 i_need PROC_ID,WORD
38 i_need SaveBX,WORD
39 i_need SaveDS,WORD
40 i_need SWAP_START,BYTE
41 i_need SWAP_ALWAYS,BYTE
42 i_need SWAP_END,BYTE
43 I_Need ThisSFT,DWORD
44 I_need fSharing,BYTE
45 i_need OpenBuf,128
46 I_Need ExtErr,WORD
47 I_Need ExtErr_Action,BYTE
48 I_Need ExtErrPt,DWORD
49 I_Need EXTERR_LOCUS,BYTE ; Extended Error Locus
50 i_need JShare,DWORD
51 i_need SWAP_AREA_TABLE,BYTE
52 i_need SWAP_ALWAYS_AREA,DWORD
53 i_need SWAP_ALWAYS_AREA_LEN,WORD
54 i_need SWAP_AREA_LEN,WORD
55
56BREAK <ServerCall -- Server DOS call>
57
58TABLE SEGMENT
59Public SRVC001S,SRVC001E
60SRVC001S label byte
61
62ServerTab DW DOSGroup:Server_Disp
63SERVERLEAVE DW DOSGROUP:ServerReturn
64SERVER_DISP DB (SERVER_DISP_END-SERVER_DISP-1)/2
65 DW OFFSET DOSGROUP:SRV_CALL ; 0
66 DW OFFSET DOSGROUP:COMMIT_ALL ; 1
67 DW OFFSET DOSGROUP:CLOSE_NAME ; 2
68 DW OFFSET DOSGROUP:CLOSE_UID ; 3
69 DW OFFSET DOSGROUP:CLOSE_UID_PID ; 4
70 DW OFFSET DOSGROUP:GET_LIST ; 5
71 DW OFFSET DOSGROUP:GET_DOS_DATA ; 6
72 DW OFFSET DOSGROUP:SPOOL_OPER ; 7
73 DW OFFSET DOSGROUP:SPOOL_OPER ; 8
74 DW OFFSET DOSGROUP:SPOOL_OPER ; 9
75 DW OFFSET DOSGroup:$setExtendedError ; 10
76SERVER_DISP_END LABEL BYTE
77
78SRVC001E label byte
79
80TABLE ENDS
81
82; Inputs:
83; DS:DX -> DPL (except calls 7,8,9)
84; Function:
85; AL=0 Server DOS call
86; AL=1 Commit All files
87; AL=2 Close file by name (SHARING LOADED ONLY) DS:DX in DPL -> name
88; AL=3 Close all files for DPL_UID
89; AL=4 Close all files for DPL_UID/PID_PID
90; AL=5 Get open file list entry
91; IN: BX File Index
92; CX User Index
93; OUT:ES:DI -> Name
94; BX = UID
95; CX = # locked blocks held by this UID
96; AL=6 Get DOS data area
97; OUT: DS:SI -> Start
98; CX size in bytes of swap if indos
99; DX size in bytes of swap always
100; AL=7 Get truncate flag
101; AL=8 Set truncate flag
102; AL=9 Close all spool files
103; AL=10 SetExtendedError
104; AL=11 DOS4.00 Get DOS data area
105; DS:SI -> swap table
106
107 procedure $ServerCall,NEAR
108ASSUME DS:NOTHING,ES:NOTHING
109 CMP AL,7
110 JB SET_STUFF
111 CMP AL,9
112 JBE NO_SET_ID ; No DPL on calls 7,8,9
113 CMP AL,11 ;IFS. ;AN000;
114 JNZ SET_STUFF ;IFS. ;AN000;
115 MOV DI,OFFSET DOSGROUP:SWAP_AREA_TABLE ;IFS. ;AN000;
116 PUSH SS ;IFS. ;AN000;
117 POP ES ;IFS. ;AN000;
118 invoke GET_USER_STACK ;IFS. ;AN000;
119 MOV [SI.user_DS],ES ;IFS. ds:si -> swap tab ;AN000;
120 MOV [SI.user_SI],DI ;IFS. ;AN000;
121 transfer SYS_RET_OK ;IFS. ;AN000;
122SET_STUFF:
123 MOV SI,DX ; Point to DPL with DS:SI
124 MOV BX,[SI.DPL_UID]
125 MOV [USER_ID],BX ; Set UID
126 MOV BX,[SI.DPL_PID]
127 MOV [PROC_ID],BX ; Set process ID
128NO_SET_ID:
129 PUSH SERVERLEAVE ; push return address
130 PUSH ServerTab ; push table address
131 PUSH AX
132 Invoke TableDispatch
133 MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
134 error error_invalid_function
135ServerReturn:
136 return
137
138; Commit - iterate through the open file list and make sure that the
139; directory entries are correctly updated.
140
141COMMIT_ALL:
142ASSUME DS:NOTHING,ES:NOTHING
143 XOR BX,BX ; for (i=0; ThisSFT=getSFT(i); i++)
144 Context DS
145 EnterCrit critSFT ; Gonna scan SFT cache, lock it down
146CommitLoop:
147 SaveReg <BX>
148 Invoke SFFromSFN
149 JC CommitDone
150 CMP ES:[DI].sf_Ref_Count,0 ; if (ThisSFT->refcount != 0)
151 JZ CommitNext
152 CMP ES:[DI].sf_Ref_Count,sf_busy ; BUSY SFTs have god knows what
153 JZ CommitNext ; in them.
154; TEST ES:[DI].sf_flags,sf_isnet
155 invoke Test_IFS_Remote ;IFS. ;AN000;
156 JNZ CommitNext ; Skip Network SFTs so the SERVER
157 ; doesn't deadlock
158 MOV WORD PTR ThisSFT,DI
159 MOV WORD PTR ThisSFT+2,ES
160 Invoke DOS_Commit ; DOSCommit ();
161CommitNext:
162 RestoreReg <BX>
163 INC BX
164 JMP CommitLoop
165CommitDone:
166 LeaveCrit critSFT
167 RestoreReg <BX>
168 transfer Sys_Ret_OK
169
170CLOSE_NAME:
171ASSUME DS:NOTHING,ES:NOTHING
172
173if installed
174 Call JShare + 5 * 4
175else
176 Call MFTcloN
177endif
178CheckReturns:
179 JC func_err
180 transfer SYS_RET_OK
181func_err:
182 transfer SYS_RET_ERR
183
184CLOSE_UID:
185ASSUME DS:NOTHING,ES:NOTHING
186
187if installed
188 Call JShare + 3 * 4
189else
190 Call MFTclU
191endif
192 JMP CheckReturns
193
194CLOSE_UID_PID:
195ASSUME DS:NOTHING,ES:NOTHING
196
197if installed
198 Call JShare + 4 * 4
199else
200 Call MFTCloseP
201endif
202 JMP CheckReturns
203
204GET_LIST:
205ASSUME DS:NOTHING,ES:NOTHING
206if installed
207 Call JShare + 9 * 4
208else
209 Call MFT_get
210endif
211 JC func_err
212 invoke get_user_stack
213 MOV [SI.user_BX],BX
214 MOV [SI.user_DI],DI
215 MOV [SI.user_ES],ES
216SetCXOK:
217 MOV [SI.user_CX],CX
218 transfer SYS_RET_OK
219
220SRV_CALL:
221ASSUME DS:NOTHING,ES:NOTHING
222 POP AX ; get rid of call to $srvcall
223 SaveReg <DS,SI>
224 invoke GET_USER_STACK
225 RestoreReg <DI,ES>
226;
227; DS:SI point to stack
228; ES:DI point to DPL
229;
230 invoke XCHGP
231;
232; DS:SI point to DPL
233; ES:DI point to stack
234;
235; We now copy the registers from DPL to save stack
236;
237 SaveReg <SI>
238 MOV CX,6
239 REP MOVSW ; Put in AX,BX,CX,DX,SI,DI
240 INC DI
241 INC DI ; Skip user_BP
242 MOVSW ; DS
243 MOVSW ; ES
244 RestoreReg <SI> ; DS:SI -> DPL
245 MOV AX,[SI.DPL_AX]
246 MOV BX,[SI.DPL_BX]
247 MOV CX,[SI.DPL_CX]
248 MOV DX,[SI.DPL_DX]
249 MOV DI,[SI.DPL_DI]
250 MOV ES,[SI.DPL_ES]
251 PUSH [SI.DPL_SI]
252 MOV DS,[SI.DPL_DS]
253 POP SI
254 MOV [SaveDS],DS
255 MOV [SaveBX],BX
256 MOV fSharing,-1 ; set no redirect flag
257 transfer REDISP
258
259GET_DOS_DATA:
260ASSUME DS:NOTHING,ES:NOTHING
261 LES DI,[SWAP_ALWAYS_AREA] ;IFS. get beginning addr of swap ;AC000;
262 MOV DX,[SWAP_ALWAYS_AREA_LEN] ;IFS. get swap always area len ;AC000;
263 AND DX,7FFFH ;IFS. clear high bit ;AC000;
264 MOV CX,[SWAP_AREA_LEN] ;IFS. get swap len ;AC000;
265 invoke GET_USER_STACK
266 MOV [SI.user_DS],ES ; set user regs
267 MOV [SI.user_SI],DI ;
268 MOV [SI.user_DX],DX ;
269 JMP SetCXOK ; ;AN000;
270
271SPOOL_OPER:
272ASSUME DS:NOTHING,ES:NOTHING
273 CallInstall NETSpoolOper,multNet,37,AX,BX
274 JC func_err2
275 transfer SYS_RET_OK
276func_err2:
277 transfer SYS_RET_ERR
278
279Break <$SetExtendedError - set extended error for later retrieval>
280
281;
282; $SetExtendedError takes extended error information and loads it up for the
283; next extended error call. This is used by interrupt-level proccessors to
284; mask their actions.
285;
286; Inputs: DS:SI points to DPL which contains all registers
287; Outputs: none
288;
289
290$SetExtendedError:
291 ASSUME DS:NOTHING,ES:NOTHING
292 MOV AX,[SI].dpl_AX
293 MOV [EXTERR],AX
294 MOV AX,[SI].dpL_di
295 MOV WORD PTR ExtErrPt,AX
296 MOV AX,[SI].dpL_ES
297 MOV WORD PTR ExtErrPt+2,AX
298 MOV AX,[SI].dpL_BX
299 MOV WORD PTR [EXTERR_ACTION],AX
300 MOV AX,[SI].dpL_CX
301 MOV [EXTERR_LOCUS],AH
302 return
303EndProc $ServerCall
304
305CODE ENDS
306 END
diff --git a/v4.0/src/DOS/STDASW.ASM b/v4.0/src/DOS/STDASW.ASM
new file mode 100644
index 0000000..d9fa382
--- /dev/null
+++ b/v4.0/src/DOS/STDASW.ASM
@@ -0,0 +1,29 @@
1; SCCSID = @(#)stdasw.asm 1.1 85/04/10
2TRUE EQU 0FFFFH
3FALSE EQU NOT TRUE
4
5; Use the switches below to produce the standard Microsoft version or the IBM
6; version of the operating system
7MSVER EQU TRUE
8IBM EQU FALSE
9WANG EQU FALSE
10ALTVECT EQU TRUE
11
12; Set this switch to cause DOS to move itself to the end of memory
13HIGHMEM EQU FALSE
14
15 IF IBM
16ESCCH EQU 0 ; character to begin escape seq.
17TOGLPRN EQU TRUE ;One key toggles printer echo
18ZEROEXT EQU TRUE
19 ELSE
20 IF WANG ;Are we assembling for WANG?
21ESCCH EQU 1FH ;Yes. Use 1FH for escape character
22 ELSE
23ESCCH EQU 1BH
24 ENDIF
25CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
26TOGLPRN EQU FALSE ;Separate keys for printer echo on
27 ;and off
28ZEROEXT EQU TRUE
29 ENDIF
diff --git a/v4.0/src/DOS/STDCODE.ASM b/v4.0/src/DOS/STDCODE.ASM
new file mode 100644
index 0000000..0332898
--- /dev/null
+++ b/v4.0/src/DOS/STDCODE.ASM
@@ -0,0 +1,17 @@
1; SCCSID = @(#)stdcode.asm 1.1 85/04/10
2TITLE MS-DOS MISC DOS ROUTINES - Int 25 and 26 handlers and other
3NAME STDCODE
4
5;
6; System call dispatch code
7;
8
9.xlist
10.xcref
11include stdsw.asm
12.cref
13.list
14
15include ms_code.asm
16 END
17 \ No newline at end of file
diff --git a/v4.0/src/DOS/STDCPMIO.ASM b/v4.0/src/DOS/STDCPMIO.ASM
new file mode 100644
index 0000000..44bbb57
--- /dev/null
+++ b/v4.0/src/DOS/STDCPMIO.ASM
@@ -0,0 +1,16 @@
1; SCCSID = @(#)stdcpmio.asm 1.1 85/04/10
2;
3; Standard device IO for MSDOS (first 12 function calls)
4;
5
6.xlist
7.xcref
8include stdsw.asm
9include dosseg.asm
10.cref
11.list
12
13TITLE STDCPMIO - device IO for MSDOS
14NAME STDCPMIO
15
16include cpmio.asm
diff --git a/v4.0/src/DOS/STDCTRLC.ASM b/v4.0/src/DOS/STDCTRLC.ASM
new file mode 100644
index 0000000..90af372
--- /dev/null
+++ b/v4.0/src/DOS/STDCTRLC.ASM
@@ -0,0 +1,15 @@
1; SCCSID = @(#)stdctrlc.asm 1.1 85/04/10
2;
3; ^C and error handler for MSDOS
4;
5
6.xlist
7.xcref
8include stdsw.asm
9.cref
10.list
11
12TITLE Control C detection, Hard error and EXIT routines
13NAME STDCTRLC
14
15include ctrlc.asm
diff --git a/v4.0/src/DOS/STDDATA.ASM b/v4.0/src/DOS/STDDATA.ASM
new file mode 100644
index 0000000..ddbb1bc
--- /dev/null
+++ b/v4.0/src/DOS/STDDATA.ASM
@@ -0,0 +1,33 @@
1; SCCSID = @(#)stddata.asm 1.1 85/04/10
2;
3; DATA Segment for MS-DOS
4;
5
6.xlist
7.xcref
8include stdsw.asm
9include dosseg.asm
10debug = FALSE ; No dossym (too big)
11INCLUDE DOSMAC.INC
12INCLUDE SF.INC
13INCLUDE DIRENT.INC
14INCLUDE CURDIR.INC
15INCLUDE DPB.INC
16INCLUDE BUFFER.INC
17INCLUDE ARENA.INC
18INCLUDE VECTOR.INC
19INCLUDE DEVSYM.INC
20INCLUDE PDB.INC
21INCLUDE FIND.INC
22INCLUDE MI.INC
23.cref
24.list
25
26TITLE STDDATA - DATA segment for MS-DOS
27NAME STDDATA
28
29installed = TRUE
30
31include msdata.asm
32include msinit.asm
33 END
diff --git a/v4.0/src/DOS/STDDISP.ASM b/v4.0/src/DOS/STDDISP.ASM
new file mode 100644
index 0000000..9010b98
--- /dev/null
+++ b/v4.0/src/DOS/STDDISP.ASM
@@ -0,0 +1,16 @@
1; SCCSID = @(#)stddisp.asm 1.1 85/04/10
2TITLE MS-DOS DOS DISPATCHER - System call dispatch code
3NAME DISP
4
5;
6; System call dispatch code
7;
8
9.xlist
10.xcref
11include stdsw.asm
12.cref
13.list
14
15include disp.asm
16 END
diff --git a/v4.0/src/DOS/STDDOSME.ASM b/v4.0/src/DOS/STDDOSME.ASM
new file mode 100644
index 0000000..c1d5a53
--- /dev/null
+++ b/v4.0/src/DOS/STDDOSME.ASM
@@ -0,0 +1,20 @@
1; SCCSID = @(#)stddosmes.as 1.2 85/10/07
2; SCCSID = @(#)stddosmes.as 1.2 85/10/07
3;
4; Standard device IO for MSDOS (first 12 function calls)
5;
6
7.xlist
8.xcref
9include stdsw.asm
10include dosseg.asm
11.cref
12.list
13
14debug=0
15
16TITLE STDDOSMES - DOS OEM dependancies
17NAME STDDOSMES
18
19include dosmes.asm
20 \ No newline at end of file
diff --git a/v4.0/src/DOS/STDIOCTL.ASM b/v4.0/src/DOS/STDIOCTL.ASM
new file mode 100644
index 0000000..9444530
--- /dev/null
+++ b/v4.0/src/DOS/STDIOCTL.ASM
@@ -0,0 +1,5 @@
1; SCCSID = @(#)STDIOCTL.INC 1.1 85/04/10
2IBM EQU 0 ;FALSE
3
4INCLUDE IOCTL.INC
5 SCCSID = @(#)STDIOCTL.INC 1.1 85/04/10
diff --git a/v4.0/src/DOS/STDPROC.ASM b/v4.0/src/DOS/STDPROC.ASM
new file mode 100644
index 0000000..c83fe2b
--- /dev/null
+++ b/v4.0/src/DOS/STDPROC.ASM
@@ -0,0 +1,15 @@
1; SCCSID = @(#)stdproc.asm 1.1 85/04/10
2;
3; Pseudo EXEC system call for MSDOS
4;
5
6.xlist
7.xcref
8include stdsw.asm
9.cref
10.list
11
12TITLE STDPROC - process maintenance for MSDOS
13NAME STDPROC
14
15include proc.asm
diff --git a/v4.0/src/DOS/STDSW.ASM b/v4.0/src/DOS/STDSW.ASM
new file mode 100644
index 0000000..c9fc581
--- /dev/null
+++ b/v4.0/src/DOS/STDSW.ASM
@@ -0,0 +1,32 @@
1; SCCSID = @(#)stdsw.asm 1.1 85/04/10
2TRUE EQU 0FFFFH
3FALSE EQU 0
4
5; Use the switches below to produce the standard Microsoft version or the IBM
6; version of the operating system
7MSVER EQU TRUE
8IBM EQU FALSE
9WANG EQU FALSE
10ALTVECT EQU FALSE
11Rainbow EQU FALSE
12
13
14; Set this switch to cause DOS to move itself to the end of memory
15HIGHMEM EQU FALSE
16
17 IF IBM
18ESCCH EQU 0 ; character to begin escape seq.
19CANCEL EQU 27 ;Cancel with ESCAPE
20TOGLPRN EQU TRUE ;One key toggles printer echo
21ZEROEXT EQU TRUE
22 ELSE
23 IF WANG ;Are we assembling for WANG?
24ESCCH EQU 1FH ;Yes. Use 1FH for escape character
25 ELSE
26ESCCH EQU 1BH
27 ENDIF
28CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
29TOGLPRN EQU FALSE ;Separate keys for printer echo on
30 ;and off
31ZEROEXT EQU TRUE
32 ENDIF
diff --git a/v4.0/src/DOS/STDTABLE.ASM b/v4.0/src/DOS/STDTABLE.ASM
new file mode 100644
index 0000000..a06b3e6
--- /dev/null
+++ b/v4.0/src/DOS/STDTABLE.ASM
@@ -0,0 +1,16 @@
1; SCCSID = @(#)stdtable.asm 1.1 85/04/10
2;
3; Table Segment for MS-DOS DOS
4;
5
6.xlist
7.xcref
8include stdsw.asm
9.cref
10.list
11
12TITLE STDTABLE - Table segment for MS-DOS
13NAME STDTABLE
14
15include mstable.asm
16 END
diff --git a/v4.0/src/DOS/STRIN.ASM b/v4.0/src/DOS/STRIN.ASM
new file mode 100644
index 0000000..ac4b963
--- /dev/null
+++ b/v4.0/src/DOS/STRIN.ASM
@@ -0,0 +1,403 @@
1; SCCSID = @(#)strin.asm 1.2 85/04/18
2Break
3
4; Inputs:
5; DS:DX Point to an input buffer
6; Function:
7; Fill buffer from console input until CR
8; Returns:
9; None
10
11 procedure $STD_CON_STRING_INPUT,NEAR ;System call 10
12ASSUME DS:NOTHING,ES:NOTHING
13
14 MOV AX,SS
15 MOV ES,AX
16 MOV SI,DX
17 XOR CH,CH
18 LODSW
19;
20; AL is the buffer length
21; AH is the template length
22;
23 OR AL,AL
24 retz ;Buffer is 0 length!!?
25 MOV BL,AH ;Init template counter
26 MOV BH,CH ;Init template counter
27 ;
28 ; BL is the number of bytes in the template
29 ;
30 CMP AL,BL
31 JBE NOEDIT ;If length of buffer inconsistent with contents
32 CMP BYTE PTR [BX+SI],c_CR
33 JZ EDITON ;If CR correctly placed EDIT is OK
34;
35; The number of chars in the template is >= the number of chars in buffer or
36; there is no CR at the end of the template. This is an inconsistant state
37; of affairs. Pretend that the template was empty:
38;
39NOEDIT:
40 MOV BL,CH ;Reset buffer
41EDITON:
42 MOV DL,AL
43 DEC DX ;DL is # of bytes we can put in the buffer
44;
45; Top level. We begin to read a line in.
46;
47NEWLIN:
48 MOV AL,[CARPOS]
49 MOV [STARTPOS],AL ;Remember position in raw buffer
50 PUSH SI
51 MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here
52 MOV [INSMODE],CH ;Insert mode off
53 MOV BH,CH ;No chars from template yet
54 MOV DH,CH ;No chars to new line yet
55 invoke $STD_CON_INPUT_NO_ECHO ;Get first char
56 CMP AL,c_LF ;Linefeed
57 JNZ GOTCH ;Filter out LF so < works
58;
59; This is the main loop of reading in a character and processing it.
60;
61; BH is the index of the next byte in the template
62; BL is the length of the template
63; DH is the number of bytes in the buffer
64; DL is the length of the buffer
65;
66entry GETCH
67 invoke $STD_CON_INPUT_NO_ECHO
68GOTCH:
69;
70; Brain-damaged TP ignored ^F in case his BIOS did not flush the
71; input queue.
72;
73 CMP AL,"F"-"@"
74 JZ GETCH
75;
76; If the leading char is the function-key lead byte
77;
78 CMP AL,[ESCCHAR]
79 JZ ESCape ;change reserved keyword DBM 5-7-87
80;
81; Rubout and ^H are both destructive backspaces.
82;
83 CMP AL,c_DEL
84 JZ BACKSPJ
85 CMP AL,c_BS
86 JZ BACKSPJ
87;
88; ^W deletes backward once and then backs up until a letter is before the
89; cursor
90;
91 CMP AL,"W" - "@"
92; The removal of the comment characters before the jump statement will
93; cause ^W to backup a word.
94;*** JZ WordDel
95 NOP
96 NOP
97 CMP AL,"U" - "@"
98; The removal of the comment characters before the jump statement will
99; cause ^U to clear a line.
100;*** JZ LineDel
101 NOP
102 NOP
103
104;
105; CR terminates the line.
106;
107 CMP AL,c_CR
108 JZ ENDLIN
109;
110; LF goes to a new line and keeps on reading.
111;
112 CMP AL,c_LF
113 JZ PHYCRLF
114;
115; ^X (or ESC) deletes the line and starts over
116;
117 CMP AL,[CANCHAR]
118 JZ KILNEW
119;
120; Otherwise, we save the input character.
121;
122SAVCH:
123 CMP DH,DL
124 JAE BUFFUL ; buffer is full.
125 STOSB
126 INC DH ; increment count in buffer.
127 invoke BUFOUT ;Print control chars nicely
128 CMP BYTE PTR [INSMODE],0
129 JNZ GETCH ; insertmode => don't advance template
130 CMP BH,BL
131 JAE GETCH ; no more characters in template
132 INC SI ; Skip to next char in template
133 INC BH ; remember position in template
134 JMP SHORT GETCH
135
136BACKSPJ: JMP SHORT BACKSP
137
138BUFFUL:
139 MOV AL,7 ; Bell to signal full buffer
140 invoke OUTT
141 JMP SHORT GETCH
142
143ESCape: ;change reserved keyword DBM 5-7-87
144 transfer OEMFunctionKey ; let the OEM's handle the key dispatch
145
146ENDLIN:
147 STOSB ; Put the CR in the buffer
148 invoke OUTT ; Echo it
149 POP DI ; Get start of user buffer
150 MOV [DI-1],DH ; Tell user how many bytes
151 INC DH ; DH is length including CR
152COPYNEW:
153 SaveReg <DS,ES>
154 RestoreReg <DS,ES> ; XCHG ES,DS
155 MOV SI,OFFSET DOSGROUP:INBUF
156 MOV CL,DH ; set up count
157 REP MOVSB ; Copy final line to user buffer
158 return
159;
160; Output a CRLF to the user screen and do NOT store it into the buffer
161;
162PHYCRLF:
163 invoke CRLF
164 JMP GETCH
165
166;
167; Delete the previous line
168;
169LineDel:
170 OR DH,DH
171 JZ GetCh
172 Call BackSpace
173 JMP LineDel
174
175;
176; delete the previous word.
177;
178WordDel:
179WordLoop:
180 Call BackSpace ; backspace the one spot
181 OR DH,DH
182 JZ GetChJ
183 MOV AL,ES:[DI-1]
184 cmp al,'0'
185 jb GetChj
186 cmp al,'9'
187 jbe WordLoop
188 OR AL,20h
189 CMP AL,'a'
190 JB GetChJ
191 CMP AL,'z'
192 JBE WordLoop
193GetChJ:
194 JMP GetCh
195;
196; The user wants to throw away what he's typed in and wants to start over. We
197; print the backslash and then go to the next line and tab to the correct spot
198; to begin the buffered input.
199;
200 entry KILNEW
201 MOV AL,"\"
202 invoke OUTT ;Print the CANCEL indicator
203 POP SI ;Remember start of edit buffer
204PUTNEW:
205 invoke CRLF ;Go to next line on screen
206 MOV AL,[STARTPOS]
207 invoke TAB ;Tab over
208 JMP NEWLIN ;Start over again
209
210
211;
212; Destructively back up one character position
213;
214entry BackSp
215 Call BackSpace
216 JMP GetCh
217
218BackSpace:
219 OR DH,DH
220 JZ OLDBAK ;No chars in line, do nothing to line
221 CALL BACKUP ;Do the backup
222 MOV AL,ES:[DI] ;Get the deleted char
223 CMP AL," "
224 JAE OLDBAK ;Was a normal char
225 CMP AL,c_HT
226 JZ BAKTAB ;Was a tab, fix up users display
227;; 9/27/86 fix for ctrl-U backspace
228 CMP AL,"U"-"@" ; ctrl-U is a section symbol not ^U
229 JZ OLDBAK
230 CMP AL,"T"-"@" ; ctrl-T is a paragraphs symbol not ^T
231 JZ OLDBAK
232;; 9/27/86 fix for ctrl-U backspace
233 CALL BACKMES ;Was a control char, zap the '^'
234OLDBAK:
235 CMP BYTE PTR [INSMODE],0
236 retnz ;In insert mode, done
237 OR BH,BH
238 retz ;Not advanced in template, stay where we are
239 DEC BH ;Go back in template
240 DEC SI
241 return
242
243BAKTAB:
244 PUSH DI
245 DEC DI ;Back up one char
246 STD ;Go backward
247 MOV CL,DH ;Number of chars currently in line
248 MOV AL," "
249 PUSH BX
250 MOV BL,7 ;Max
251 JCXZ FIGTAB ;At start, do nothing
252FNDPOS:
253 SCASB ;Look back
254 JNA CHKCNT
255 CMP BYTE PTR ES:[DI+1],9
256 JZ HAVTAB ;Found a tab
257 DEC BL ;Back one char if non tab control char
258CHKCNT:
259 LOOP FNDPOS
260FIGTAB:
261 SUB BL,[STARTPOS]
262HAVTAB:
263 SUB BL,DH
264 ADD CL,BL
265 AND CL,7 ;CX has correct number to erase
266 CLD ;Back to normal
267 POP BX
268 POP DI
269 JZ OLDBAK ;Nothing to erase
270TABBAK:
271 invoke BACKMES
272 LOOP TABBAK ;Erase correct number of chars
273 JMP SHORT OLDBAK
274
275BACKUP:
276 DEC DH ;Back up in line
277 DEC DI
278BACKMES:
279 MOV AL,c_BS ;Backspace
280 invoke OUTT
281 MOV AL," " ;Erase
282 invoke OUTT
283 MOV AL,c_BS ;Backspace
284 JMP OUTT ;Done
285
286;User really wants an ESC character in his line
287 entry TwoEsc
288 MOV AL,[ESCCHAR]
289 JMP SAVCH
290
291;Copy the rest of the template
292 entry COPYLIN
293 MOV CL,BL ;Total size of template
294 SUB CL,BH ;Minus position in template, is number to move
295 JMP SHORT COPYEACH
296
297 entry CopyStr
298 invoke FINDOLD ;Find the char
299 JMP SHORT COPYEACH ;Copy up to it
300
301;Copy one char from template to line
302 entry COPYONE
303 MOV CL,1
304;Copy CX chars from template to line
305COPYEACH:
306 MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode
307 CMP DH,DL
308 JZ GETCH2 ;At end of line, can't do anything
309 CMP BH,BL
310 JZ GETCH2 ;At end of template, can't do anything
311 LODSB
312 STOSB
313 invoke BUFOUT
314 INC BH ;Ahead in template
315 INC DH ;Ahead in line
316 LOOP COPYEACH
317GETCH2:
318 JMP GETCH
319
320;Skip one char in template
321 entry SKIPONE
322 CMP BH,BL
323 JZ GETCH2 ;At end of template
324 INC BH ;Ahead in template
325 INC SI
326 JMP GETCH
327
328 entry SKIPSTR
329 invoke FINDOLD ;Find out how far to go
330 ADD SI,CX ;Go there
331 ADD BH,CL
332 JMP GETCH
333
334;Get the next user char, and look ahead in template for a match
335;CX indicates how many chars to skip to get there on output
336;NOTE: WARNING: If the operation cannot be done, the return
337; address is popped off and a jump to GETCH is taken.
338; Make sure nothing extra on stack when this routine
339; is called!!! (no PUSHes before calling it).
340FINDOLD:
341 invoke $STD_CON_INPUT_NO_ECHO
342 CMP AL,[ESCCHAR] ; did he type a function key?
343 JNZ FindSetup ; no, set up for scan
344 invoke $STD_CON_INPUT_NO_ECHO ; eat next char
345 JMP NotFnd ; go try again
346FindSetup:
347 MOV CL,BL
348 SUB CL,BH ;CX is number of chars to end of template
349 JZ NOTFND ;At end of template
350 DEC CX ;Cannot point past end, limit search
351 JZ NOTFND ;If only one char in template, forget it
352 PUSH ES
353 PUSH DS
354 POP ES
355 PUSH DI
356 MOV DI,SI ;Template to ES:DI
357 INC DI
358 REPNE SCASB ;Look
359 POP DI
360 POP ES
361 JNZ NOTFND ;Didn't find the char
362 NOT CL ;Turn how far to go into how far we went
363 ADD CL,BL ;Add size of template
364 SUB CL,BH ;Subtract current pos, result distance to skip
365 return
366
367NOTFND:
368 POP BP ;Chuck return address
369 JMP GETCH
370
371entry REEDIT
372 MOV AL,"@" ;Output re-edit character
373 invoke OUTT
374 POP DI
375 PUSH DI
376 PUSH ES
377 PUSH DS
378 invoke COPYNEW ;Copy current line into template
379 POP DS
380 POP ES
381 POP SI
382 MOV BL,DH ;Size of line is new size template
383 JMP PUTNEW ;Start over again
384
385 entry EXITINS
386 entry ENTERINS
387 NOT BYTE PTR [INSMODE]
388 JMP GETCH
389
390;Put a real live ^Z in the buffer (embedded)
391 entry CTRLZ
392 MOV AL,"Z"-"@"
393 JMP SAVCH
394
395;Output a CRLF
396 entry CRLF
397 MOV AL,c_CR
398 invoke OUTT
399 MOV AL,c_LF
400 JMP OUTT
401
402EndProc $STD_CON_STRING_INPUT
403 \ No newline at end of file
diff --git a/v4.0/src/DOS/TIME.ASM b/v4.0/src/DOS/TIME.ASM
new file mode 100644
index 0000000..0d3895c
--- /dev/null
+++ b/v4.0/src/DOS/TIME.ASM
@@ -0,0 +1,380 @@
1; SCCSID = @(#)time.asm 1.1 85/04/10
2TITLE TIME - time and date functions
3NAME TIME
4;
5; System Calls and low level routines for DATE and TIME
6;
7; $GET_DATE
8; $SET_DATE
9; $GET_TIME
10; $SET_TIME
11; DATE16
12; READTIME
13; DSLIDE
14; SETYEAR
15; DODATE
16; DSUM
17;
18; Modification history:
19;
20; Created: ARR 30 March 1983
21;
22
23.xlist
24;
25; get the appropriate segment definitions
26;
27include dosseg.asm
28
29CODE SEGMENT BYTE PUBLIC 'CODE'
30 ASSUME SS:DOSGROUP,CS:DOSGROUP
31
32.xcref
33INCLUDE DOSSYM.INC
34INCLUDE DEVSYM.INC
35.cref
36.list
37
38
39 i_need DAY,BYTE
40 i_need MONTH,BYTE
41 i_need YEAR,WORD
42 i_need WEEKDAY,BYTE
43 i_need TIMEBUF,6
44 i_need BCLOCK,DWORD
45 i_need DAYCNT,WORD
46 i_need YRTAB,8
47 i_need MONTAB,12
48 i_need DATE_FLAG,WORD
49
50 FOURYEARS = 3*365 + 366
51
52SUBTTL DATE AND TIME - SYSTEM CALLS 42,43,44,45
53PAGE
54 procedure $GET_DATE,NEAR
55ASSUME DS:NOTHING,ES:NOTHING
56
57; Inputs:
58; None
59; Function:
60; Return current date
61; Returns:
62; Date in CX:DX
63
64 Context DS
65 CALL READTIME ;Check for rollover to next day
66 MOV AX,[YEAR]
67;
68; WARNING!!!! DAY and MONTH must be adjacently allocated!
69;
70 MOV BX,WORD PTR [DAY] ; fetch both day and month
71 invoke get_user_stack ;Get pointer to user registers
72ASSUME DS:NOTHING
73 MOV [SI.user_DX],BX ;DH=month, DL=day
74 ADD AX,1980 ;Put bias back
75 MOV [SI.user_CX],AX ;CX=year
76 MOV AL,BYTE PTR [WEEKDAY]
77 return
78EndProc $GET_DATE
79
80 procedure $SET_DATE,NEAR ;System call 43
81ASSUME DS:NOTHING,ES:NOTHING
82
83; Inputs:
84; CX:DX valid date
85; Function:
86; Set current date
87; Returns:
88; AL = -1 date bad, = 0 OK
89
90 MOV AL,-1 ;Be ready to flag error
91 SUB CX,1980 ;Fix bias in year
92 retc ;Error if not big enough
93 CMP CX,119 ;Year must be less than 2100
94 JA RET24
95 OR DH,DH
96 retz
97 OR DL,DL
98 retz ;Error if either month or day is 0
99 CMP DH,12 ;Check against max. month
100 JA RET24
101 Context DS
102 invoke DODATE
103RET24: return
104EndProc $SET_DATE
105
106 procedure $GET_TIME,NEAR ;System call 44
107ASSUME DS:NOTHING,ES:NOTHING
108
109; Inputs:
110; None
111; Function:
112; Get current time
113; Returns:
114; Time in CX:DX
115
116 Context DS
117 CALL READTIME
118 invoke get_user_stack ;Get pointer to user registers
119 MOV [SI.user_DX],DX
120 MOV [SI.user_CX],CX
121 XOR AL,AL
122RET26: return
123EndProc $GET_TIME
124
125 procedure $SET_TIME,NEAR ;System call 45
126ASSUME DS:NOTHING,ES:NOTHING
127
128; Inputs:
129; CX:DX = Time
130; Function:
131; Set time
132; Returns:
133; AL = -1 time bad, = 0 OK
134
135 MOV AL,-1 ;Flag in case of error
136 CMP CH,24 ;Check hours
137 JAE RET26
138 CMP CL,60 ;Check minutes
139 JAE RET26
140 CMP DH,60 ;Check seconds
141 JAE RET26
142 CMP DL,100 ;Check 1/100's
143 JAE RET26
144 PUSH CX
145 PUSH DX
146 Context DS
147 MOV BX,OFFSET DOSGROUP:TIMEBUF
148 MOV CX,6
149 XOR DX,DX
150 MOV AX,DX
151 PUSH BX
152 invoke SETREAD
153 DOSAssume CS,<ES>,"TIME/SetRead"
154 PUSH DS
155 LDS SI,[BCLOCK]
156ASSUME DS:NOTHING
157 invoke DEVIOCALL2 ;Get correct day count
158 POP DS
159 DOSAssume CS,<DS>,"TIME/DevIOCall2"
160 POP BX
161 invoke SETWRITE
162 POP WORD PTR [TIMEBUF+4]
163 POP WORD PTR [TIMEBUF+2]
164 LDS SI,[BCLOCK]
165ASSUME DS:NOTHING
166 invoke DEVIOCALL2 ;Set the time
167 XOR AL,AL
168 return
169EndProc $SET_TIME
170
171SUBTTL DATE16, READTIME, DODATE -- GUTS OF TIME AND DATE
172PAGE
173
174;
175; Date16 returns the current date in AX, current time in DX
176; AX - YYYYYYYMMMMDDDDD years months days
177; DX - HHHHHMMMMMMSSSSS hours minutes seconds/2
178;
179; DS = DOSGROUP on output
180
181procedure DATE16,NEAR
182 Context DS
183 ASSUME ES:NOTHING
184 PUSH CX
185 PUSH ES
186 CALL READTIME
187 POP ES
188 SHL CL,1 ;Minutes to left part of byte
189 SHL CL,1
190 SHL CX,1 ;Push hours and minutes to left end
191 SHL CX,1
192 SHL CX,1
193 SHR DH,1 ;Count every two seconds
194 OR CL,DH ;Combine seconds with hours and minutes
195 MOV DX,CX
196;
197; WARNING! MONTH and YEAR must be adjacently allocated
198;
199 MOV AX,WORD PTR [MONTH] ;Fetch month and year
200 MOV CL,4
201 SHL AL,CL ;Push month to left to make room for day
202 SHL AX,1
203 POP CX
204 OR AL,[DAY]
205 return
206EndProc DATE16
207
208;Gets time in CX:DX. Figures new date if it has changed.
209;Uses AX, CX, DX.
210
211 procedure READTIME,NEAR
212 DOSAssume CS,<DS>,"ReadTime"
213 ASSUME ES:NOTHING
214
215 MOV [DATE_FLAG],0 ; reset date flag for CPMIO
216 PUSH SI
217 PUSH BX
218 MOV BX,OFFSET DOSGROUP:TIMEBUF
219 MOV CX,6
220 XOR DX,DX
221 MOV AX,DX
222 invoke SETREAD
223 PUSH DS
224 LDS SI,[BCLOCK]
225ASSUME DS:NOTHING
226 invoke DEVIOCALL2 ;Get correct date and time
227 POP DS
228 DOSAssume CS,<DS>,"ReadTime/DevIOCall2"
229 POP BX
230 POP SI
231 MOV AX,WORD PTR [TIMEBUF]
232 MOV CX,WORD PTR [TIMEBUF+2]
233 MOV DX,WORD PTR [TIMEBUF+4]
234 CMP AX,[DAYCNT] ;See if day count is the same
235 retz
236 CMP AX,FOURYEARS*30 ;Number of days in 120 years
237 JAE RET22 ;Ignore if too large
238 MOV [DAYCNT],AX
239 PUSH SI
240 PUSH CX
241 PUSH DX ;Save time
242 XOR DX,DX
243 MOV CX,FOURYEARS ;Number of days in 4 years
244 DIV CX ;Compute number of 4-year units
245 SHL AX,1
246 SHL AX,1
247 SHL AX,1 ;Multiply by 8 (no. of half-years)
248 MOV CX,AX ;<240 implies AH=0
249 MOV SI,OFFSET DOSGROUP:YRTAB;Table of days in each year
250 CALL DSLIDE ;Find out which of four years we're in
251 SHR CX,1 ;Convert half-years to whole years
252 JNC SK ;Extra half-year?
253 ADD DX,200
254SK:
255 CALL SETYEAR
256 MOV CL,1 ;At least at first month in year
257 MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month
258 CALL DSLIDE ;Find out which month we're in
259 MOV [MONTH],CL
260 INC DX ;Remainder is day of month (start with one)
261 MOV [DAY],DL
262 CALL WKDAY ;Set day of week
263 POP DX
264 POP CX
265 POP SI
266RET22: return
267EndProc READTIME
268
269 procedure DSLIDE,NEAR
270 MOV AH,0
271DSLIDE1:
272 LODSB ;Get count of days
273 CMP DX,AX ;See if it will fit
274 retc ;If not, done
275 SUB DX,AX
276 INC CX ;Count one more month/year
277 JMP SHORT DSLIDE1
278EndProc DSLIDE
279
280 procedure SETYEAR,NEAR
281;Set year with value in CX. Adjust length of February for this year.
282 MOV BYTE PTR [YEAR],CL
283
284CHKYR:
285 TEST CL,3 ;Check for leap year
286 MOV AL,28
287 JNZ SAVFEB ;28 days if no leap year
288 INC AL ;Add leap day
289SAVFEB:
290 MOV [MONTAB+1],AL ;Store for February
291RET23: return
292EndProc SETYEAR
293
294 procedure DODATE,NEAR
295 DOSAssume CS,<DS>,"DoDate"
296 ASSUME ES:NOTHING
297 CALL CHKYR ;Set Feb. up for new year
298 MOV AL,DH
299 MOV BX,OFFSET DOSGROUP:MONTAB-1
300 XLAT ;Look up days in month
301 CMP AL,DL
302 MOV AL,-1 ;Restore error flag, just in case
303 retc ;Error if too many days
304 CALL SETYEAR
305;
306; WARNING! DAY and MONTH must be adjacently allocated
307;
308 MOV WORD PTR [DAY],DX ;Set both day and month
309 SHR CX,1
310 SHR CX,1
311 MOV AX,FOURYEARS
312 MOV BX,DX
313 MUL CX
314 MOV CL,BYTE PTR [YEAR]
315 AND CL,3
316 MOV SI,OFFSET DOSGROUP:YRTAB
317 MOV DX,AX
318 SHL CX,1 ;Two entries per year, so double count
319 CALL DSUM ;Add up the days in each year
320 MOV CL,BH ;Month of year
321 MOV SI,OFFSET DOSGROUP:MONTAB
322 DEC CX ;Account for months starting with one
323 CALL DSUM ;Add up days in each month
324 MOV CL,BL ;Day of month
325 DEC CX ;Account for days starting with one
326 ADD DX,CX ;Add in to day total
327 XCHG AX,DX ;Get day count in AX
328 MOV [DAYCNT],AX
329 PUSH SI
330 PUSH BX
331 PUSH AX
332 MOV BX,OFFSET DOSGROUP:TIMEBUF
333 MOV CX,6
334 XOR DX,DX
335 MOV AX,DX
336 PUSH BX
337 invoke SETREAD
338 DOSAssume CS,<ES>,"DoDate/SetRead"
339 PUSH DS
340 LDS SI,[BCLOCK]
341ASSUME DS:NOTHING
342 invoke DEVIOCALL2 ;Get correct date and time
343 POP DS
344 POP BX
345 DOSAssume CS,<DS>,"DoDate/DevIOCall2"
346 invoke SETWRITE
347 POP WORD PTR [TIMEBUF]
348 PUSH DS
349 LDS SI,[BCLOCK]
350ASSUME DS:NOTHING
351 invoke DEVIOCALL2 ;Set the date
352 POP DS
353 DOSAssume CS,<DS>,"DoDate/DevIOCall2(second)"
354 POP BX
355 POP SI
356WKDAY:
357 MOV AX,[DAYCNT]
358 XOR DX,DX
359 MOV CX,7
360 INC AX
361 INC AX ;First day was Tuesday
362 DIV CX ;Compute day of week
363 MOV [WEEKDAY],DL
364 XOR AL,AL ;Flag OK
365Ret25: return
366EndProc DODATE
367
368 procedure DSUM,NEAR
369 MOV AH,0
370 JCXZ RET25
371DSUM1:
372 LODSB
373 ADD DX,AX
374 LOOP DSUM1
375 return
376EndProc DSUM
377
378CODE ENDS
379 END
380 \ No newline at end of file
diff --git a/v4.0/src/DOS/UTIL.ASM b/v4.0/src/DOS/UTIL.ASM
new file mode 100644
index 0000000..3c9c516
--- /dev/null
+++ b/v4.0/src/DOS/UTIL.ASM
@@ -0,0 +1,232 @@
1; SCCSID = @(#)util.asm 1.1 85/04/10
2TITLE UTIL - Handle utilities
3NAME UTIL
4;
5; Handle related utilities for MSDOS 2.X.
6;
7; pJFNFromHandle written
8; SFFromHandle written
9; SFFromSFN written
10; JFNFree written
11; SFNFree written
12;
13; Modification history:
14;
15; Created: MZ 1 April 1983
16;
17
18.xlist
19;
20; get the appropriate segment definitions
21;
22include dosseg.asm
23
24CODE SEGMENT BYTE PUBLIC 'CODE'
25 ASSUME SS:DOSGROUP,CS:DOSGROUP
26
27.xcref
28INCLUDE DOSSYM.INC
29INCLUDE DEVSYM.INC
30.cref
31.list
32.sall
33
34 I_need CurrentPDB,WORD ; current process data block location
35 I_need SFT_Addr,DWORD ; pointer to beginning of table
36 I_Need PROC_ID,WORD ; current process ID
37 I_Need USER_ID,WORD ; current user ID
38if debug
39 I_need BugLev,WORD
40 I_need BugTyp,WORD
41include bugtyp.asm
42endif
43
44BREAK <pJFNFromHandle - return pointer to JFN table entry>
45
46;
47; pJFNFromHandle - Given a handle, return the pointer to the JFN location
48; in the user's data space
49; Inputs: BX - Handle
50; Outputs: Carry Set
51; AX has error code
52; Carry reset
53; ES:DI point to the handle spot
54; Registers modified:
55; If no error, ES:DI, else AX,ES
56; NOTE:
57; This routine is called from $CREATE_PROCESS_DATA_BLOCK which is called
58; at DOSINIT time with SS NOT DOSGROUP
59procedure pJFNFromHandle,NEAR
60 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
61 MOV ES,[CurrentPDB] ; get user process data block
62 CMP BX,ES:[PDB_JFN_Length] ; is handle greater than allocated
63 JB JFNAdd ; no, get offset
64 fmt TypAccess,LevSFN,<"$p: Illegal JFN %x\n">,<BX>
65 MOV AL,error_invalid_handle ; appropriate error
66ReturnCarry:
67 STC ; signal error
68 return ; go back
69JFNAdd: LES DI,ES:[PDB_JFN_Pointer] ; get pointer to beginning of table
70 ADD DI,BX ; add in offset
71ReturnNoCarry:
72 CLC ; no holes
73 return ; bye!
74EndProc pJFNFromHandle
75
76BREAK <SFFromHandle - return pointer (or error) to SF entry from handle>
77
78;
79; SFFromHandle - Given a handle, get JFN and then index into SF table
80;
81; Input: BX has handle
82; Output: Carry Set
83; AX has error code
84; Carry Reset
85; ES:DI has pointer to SF entry
86; Registers modified: If error, AX,ES, else ES:DI
87; NOTE:
88; This routine is called from $CREATE_PROCESS_DATA_BLOCK which is called
89; at DOSINIT time with SS NOT DOSGROUP
90procedure SFFromHandle,NEAR
91 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
92 CALL pJFNFromHandle ; get jfn pointer
93 retc ; return if error
94 CMP BYTE PTR ES:[DI],-1 ; unused handle
95 JNZ GetSF ; nope, suck out SF
96 fmt TypAccess,LevSFN,<"$p: Illegal SFN $x:$x\n">,<ES,DI>
97 MOV AL,error_invalid_handle ; appropriate error
98 jump ReturnCarry ; signal it
99GetSF:
100 SaveReg <BX> ; save handle
101 MOV BL,BYTE PTR ES:[DI] ; get SFN
102 XOR BH,BH ; ignore upper half
103 CALL SFFromSFN ; get real sf spot
104 RestoreReg <BX> ; restore
105 return ; say goodbye
106EndProc SFFromHandle
107
108BREAK <SFFromSFN - index into SF table for SFN>
109
110;
111; SFFromSFN - index into SF tables for SFN.
112;
113; Input: BX has SF index
114; Output: ES:DI points to SF entry
115; Registers modified: ES:DI, BX only
116; NOTE:
117; This routine is called from SFFromHandle which is called
118; at DOSINIT time with SS NOT DOSGROUP
119procedure SFFromSFN,NEAR
120 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
121 LES DI,[SFT_Addr] ; get pointer to beginning of table
122ScanLoop:
123 CMP BX,ES:[DI].SFCount ; is handle in this table?
124 JB GetOffset ; yes, go grab it
125 SUB BX,ES:[DI].SFCount
126 LES DI,ES:[DI].SFLink ; get next table segment
127 CMP DI,-1 ; end of tables?
128 JNZ ScanLoop ; no, try again
129 STC ; error...
130 JMP SHORT Restore ; go restore
131GetOffset:
132 SaveReg <AX> ; save AX
133 MOV AX,SIZE SF_Entry ; put it in a nice place
134 MUL BL ; times size
135 ADD DI,AX ; offset by size
136 RestoreReg <AX> ; get world back
137 ADD DI,SFTable ; offset into structure
138 CLC ; no holes
139Restore:
140 return ; bye!
141EndProc SFFromSFN
142
143BREAK <JFNFree - return a jfn pointer if one is free>
144
145;
146; JFNFree - scan through the JFN table and return a pointer to a free slot
147;
148; Input: None.
149; Output: Carry Set
150; AX has error code, BX,ES,DI garbage
151; Carry Reset
152; BX has new handle, ES:DI is pointer to JFN slot
153; Registers modified: As above only.
154procedure JFNFree,NEAR
155 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
156 XOR BX,BX ; try starting low
157JFNScan:
158 CALL pJFNFromHandle ; get the appropriate handle
159 JC JFNNone ; no more handles
160 CMP BYTE PTR ES:[DI],-1 ; free?
161 JZ JFNFound ; yes, carry is clear
162 INC BX ; no, next handle
163 JMP JFNScan ; and try again
164JFNNone:
165 MOV AL,error_too_many_open_files
166JFNFound:
167 return ; bye
168EndProc JFNFree
169
170BREAK <SFNFree - find a free SFN>
171
172;
173; SFNFree - scan through the sf table looking for free entries
174; Inputs: none
175; Outputs: Carry Set - AX has error code, BX destroyed
176; Carry Clear - BX has SFN
177; ES:DI - pointer to SFT
178; SFT_ref_count is set to 1
179; Registers modified: none
180
181Procedure SFNFree,NEAR
182 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
183 XOR BX,BX ; start at beginning
184SFNFreeLoop:
185 SaveReg <BX> ; Next call zaps BX
186 CALL SFFromSFN ; get the potential handle
187 RestoreReg <BX>
188 JNC SFNCheck ; no carry, check to see if its free
189 MOV AL,error_too_many_open_files ; appropriate error
190 JMP SFNDone
191SFNCheck:
192 CMP ES:[DI.sf_Ref_Count],0 ; free?
193IF NOT DEBUG
194 JZ SFNGot ; yep, got return him
195ELSE
196 JNZ NoGot
197 JMP SFNGot
198NoGot:
199ENDIF
200 CMP ES:[DI.sf_ref_count],sf_busy
201 JNZ SFNNext ; not marked busy...
202 fmt TypAccess,LevSFN,<"$p: SFT $x:$x($x)is busy, owner $x:$x\n">,<ES,DI,BX,ES:[DI].sf_UID,ES:[DI].sf_pid>
203 SaveReg <BX>
204 MOV BX,User_ID
205 CMP ES:[DI.sf_UID],BX
206 JNZ SFNNextP
207 MOV BX,Proc_ID
208 CMP ES:[DI.sf_PID],BX
209 JZ SFNGotP
210SFNNextP:
211 fmt TypAccess,LevSFN,<"$p: SFT unusable\n">
212 RestoreReg <BX>
213SFNNext:
214 INC BX ; no, try next sf number
215 JMP SFNFreeLoop ; and go until it fails
216SFNGot:
217 SaveReg <BX>
218SFNGotP:
219 CLC ; no error
220 fmt TypAccess,LevSFN,<"$p: SFT $x:$x($x) marked busy\n">,<ES,DI,BX>
221 MOV ES:[DI.sf_ref_count],sf_busy ; make sure that this is allocated
222 MOV BX,User_ID
223 MOV ES:[DI.sf_UID],BX
224 MOV BX,Proc_ID
225 MOV ES:[DI.sf_PID],BX
226 RestoreReg <BX>
227SFNDone:
228 return ; bye
229EndProc SFNFree
230
231CODE ENDS
232END