1 ; SCCSID = @(#)misc.asm 1.1 85/04/10
2 TITLE MISC
- Miscellanious routines for
MS-DOS
5 ; Miscellaneous system calls most of which are CAVEAT
16 ; $CREATE_PROCESS_DATA_BLOCK
23 ; Created: ARR 30 March 1983
25 ; A000 version 4.00 Jan. 1988
26 ; A001 D490 -- Change IOCTL subfunctions from 63h, 43h to 66h , 46h
30 ; get the appropriate segment definitions
34 CODE SEGMENT BYTE PUBLIC 'CODE'
35 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
47 i_need LASTBUFFER
,DWORD
50 i_need SYSINITVAR
,BYTE
51 i_need CurrentPDB
,WORD
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;
66 BREAK <SleazeFunc
-- get a pointer to media
byte>
68 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
69 ; C A V E A T P R O G R A M M E R ;
74 ; Return Stuff sort of like old get fat call
76 ; DS:BX = Points to FAT ID byte (IBM only)
77 ; GOD help anyone who tries to do ANYTHING except
79 ; DX = Total Number of allocation units on disk
81 ; AL = Sectors per allocation unit
82 ; = -1 if bad drive specified
84 procedure $SLEAZEFUNC
,NEAR
85 ASSUME
DS:NOTHING
,ES:NOTHING
90 ;Same as above except drive passed in DL (0=default, 1=A, 2=B, ...)
94 invoke GETTHISDRV
; Get CDS structure
96 ; MOV AL,error_invalid_drive ; Assume error ;AC000;
99 JC SET_AL_RET
; User FAILed to I 24
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
104 MOV DI,OFFSET DOSGROUP
:FATBYTE
105 XOR AH,AH ; AL has sectors/cluster
106 invoke get_user_stack
111 MOV [SI.user_DS
],CS ; stash correct pointer
117 ; C A V E A T P R O G R A M M E R ;
118 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
120 BREAK <$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 ;
127 ; Returns location of DOS status for interrupt routines
129 ; Flag location in ES:BX
131 procedure $GET_INDOS_FLAG
,NEAR
132 ASSUME
DS:NOTHING
,ES:NOTHING
134 invoke get_user_stack
135 MOV [SI.user_BX
],OFFSET DOSGROUP
:INDOS
138 EndProc $GET_INDOS_FLAG
140 ; C A V E A T P R O G R A M M E R ;
141 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
143 BREAK <$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 ;
147 ; Return a pointer to interesting DOS variables This call is version
148 ; dependent and is subject to change without notice in future versions.
150 procedure $GET_IN_VARS
,NEAR
151 invoke get_user_stack
152 MOV [SI.user_BX
],OFFSET DOSGROUP
:SYSINITVAR
157 ; C A V E A T P R O G R A M M E R ;
158 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
161 BREAK <$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 ;
168 ; Return pointer to drive parameter table for default drive
170 ; DS:BX points to the DPB
171 ; AL = 0 If OK, = -1 if bad drive (call 50 only)
173 procedure $GET_DEFAULT_DPB
,NEAR
174 ASSUME
DS:NOTHING
,ES:NOTHING
179 ; Same as above only drive passed in DL (0=default, 1=A, 2=B, ...)
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
189 invoke FATRead_CDS
; Force Media Check and return DPB
191 JC ISNODRV
; User FAILed to I 24, only error we
193 invoke get_user_stack
203 EndProc $GET_Default_dpb
205 ; C A V E A T P R O G R A M M E R ;
206 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
209 BREAK <$Disk_Reset
-- Flush
out all dirty buffers
>
211 procedure $DISK_RESET
,NEAR
212 ASSUME
DS:NOTHING
,ES:NOTHING
217 ; Flush and invalidate all buffers
225 OR [DOS34_FLAG
],FROM_DISK_RESET
;AN000;
227 AND [DOS34_FLAG
],NO_FROM_DISK_RESET
;AN000;
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
233 ; Invalidate 'last-buffer' used
236 MOV WORD PTR [LASTBUFFER
+2],BX
237 MOV WORD PTR [LASTBUFFER
],BX
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
247 CallInstall NetFlushBuf
,multNET
,32
251 BREAK <$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 ;
255 procedure $SETDPB
,NEAR
256 ASSUME
DS:NOTHING
,ES:NOTHING
259 ; ES:BP Points to DPB
260 ; DS:SI Points to BPB
262 ; Build a correct DPB from the BPB
264 ; ES:BP and DS preserved all others destroyed
267 ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
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;
278 STOSB ; dpb_cluster_mask
289 STOSB ; dpb_cluster_shift
291 MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
293 STOSB ; dpb_FAT_count Number of FATs
294 ; OR AL,AL ; NONFAT ? ;AN000;
295 ; JZ setend ; yes, don't do anything ;AN000;
298 STOSW ; dpb_root_entries Number of directory entries
300 SHR DX,CL ; Directory entries per sector
302 ADD AX,DX ; Cause Round Up
306 MOV CX,AX ; Number of directory sectors
308 INC DI ; Skip dpb_first_sector
309 MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
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
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
332 rott: ;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
338 MOV AX,BX ;AN000;;F.C. >32mb
339 JMP setend
;AN000;;F.C. >32mb
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
347 MOV ES:[BP.dpb_max_cluster
],AX
348 MOV ES:[BP.dpb_next_free
],0 ; Init so first ALLOC starts at
350 MOV ES:[BP.dpb_free_cnt
],-1 ; current count is invalid.
354 ; C A V E A T P R O G R A M M E R ;
355 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
357 BREAK <$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 ;
362 ; Inputs: DX is new segment address of process
363 ; SI is end of new allocation block
365 procedure $Dup_PDB
,NEAR
366 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
367 MOV CreatePDB
,0FFH ; indicate a new process
373 procedure $CREATE_PROCESS_DATA_BLOCK
,NEAR
374 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
377 ; DX = Segment number of new base
379 ; Set up program base and copy term and ^C from int area
386 PUSH DS:[PDB_Block_len
]
389 XOR SI,SI ; copy all 80h bytes
395 MOV CX,FilPerProc
; copy handles in case of
396 MOV DI,PDB_JFN_Table
; Set Handle Count has been issued
398 LDS SI,DS:[PDB_JFN_Pointer
]
403 TEST CreatePDB
,0FFh ; Shall we create a process?
404 JZ Create_PDB_cont
; nope, old style call
406 ; Here we set up for a new process...
409 PUSH CS ; Called at DOSINIT time, NO SS
411 DOSAssume
CS,<DS>,"MISC/Create_Copy"
412 XOR BX,BX ; dup all jfns
413 MOV CX,FilPerProc
; only 20 of them
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.
423 ; We do not inherit network file handles.
425 MOV AH,BYTE PTR ES:[DI].sf_mode
427 CMP AH,sharing_net_fcb
430 ; The handle we have found is duplicatable (and inheritable). Perform
431 ; duplication operation.
433 MOV WORD PTR [THISSFT
],DI
434 MOV WORD PTR [THISSFT
+2],ES
435 invoke DOS_DUP
; signal duplication
437 ; get the old sfn for copy
439 invoke pJFNFromHandle
; ES:DI is jfn
440 MOV AL,ES:[DI] ; get sfn
442 ; Take AL (old sfn or -1) and stash it into the new position
446 MOV ES:[BX].PDB_JFN_Table
,AL; copy into new place!
450 MOV BX,CurrentPDB
; get current process
451 MOV ES:[PDB_Parent_PID
],BX ; stash in child
456 ; end of new process create
459 MOV BYTE PTR [CreatePDB
],0h
; reset flag
463 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
466 ; AX = Size of memory in paragraphs
469 ; Completely prepares a program base at the
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.
486 MOV SI,addr_int_terminate
496 SUB AX,10H
; Allow for 100h byte "stack"
497 MOV BX,ENTRYPOINTSEG
; in .COM files
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
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.
518 MOV word ptr DS:[PDB_Next_PDB
],-1
519 MOV word ptr DS:[PDB_Next_PDB
+2],-1
522 EndProc $CREATE_PROCESS_DATA_BLOCK
525 ; C A V E A T P R O G R A M M E R ;
526 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
527 procedure FETCHI_CHECK
,NEAR
528 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
530 CMP CS:[FETCHI_TAG
],22642
532 invoke DOSINIT
; go to hell
538 BREAK <$GSetMediaID
-- get set media ID
>
540 ; BL= drive number as defined in IOCTL
543 ; DS:DX= buffer containing information
544 ; DW 0 info level (set on input)
546 ; DB 11 dup(?) volume id
547 ; DB 8 dup(?) file system type
549 ; Get or set media ID
551 ; carry clear, DS:DX is filled
554 procedure $GSetMediaID
,NEAR ;AN000;
555 ASSUME
DS:NOTHING
,ES:NOTHING
;AN000;
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.;
564 MOV AL,0DH ;AN000;MS.; generic IOCTL
565 invoke $IOCTL
;AN000;MS.; let IOCTL take care of it
568 error error_invalid_function
;AN000;MS. ; invalid function
569 EndProc $GSetMediaID
;AN000;