⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.fdo

📁 一个dos操作系统DRDOS的源码
💻 FDO
📖 第 1 页 / 共 5 页
字号:
	call	hdsblk			; get directory block in AX
	xchg	ax,dx			; directory block
	mov	cx,dcnt			; get the directory count in CX
	mov	al,physical_drv		; get physical drive in AL
	callf	ss:share_stub[di]	; ask SHARE if it knows of anyone open
	 jc	check_with_share10
	ret				; must be OK.

check_with_share10:
	jmp	fdos_error		; bail out with an error


eject

eject
;
;	Return a pointer to the DOS Handle corresponding to the internal
;	handle number passed in AX
;
; On Entry:
;	AL = IFN
;
; On Exit:
;	ES:BX -> DOS handle (All other Regs preserved)
;		CY set if no corresponding valid DHNDL_
;
	Public	ifn2dhndl
ifn2dhndl:
	push	ax
	xor	ah,ah			; make IFN a word
	les	bx,ss:file_ptr		; get the address of the first entry

ifn2dh10:
	cmp	ax,es:DCNTRL_COUNT[bx]	; handle in this block?
	 jae	ifn2dh20		; skip if not
	mov	ah,DHNDL_LEN		;  calculate offset of the DOS Handle
	mul	ah
	add	bx,ax			; add structure offset (should be 0) 
	add	bx,DCNTRL_LEN		;    and then skip the header
	pop	ax
	clc
	ret				; ES:BX -> valid DHDNL_

ifn2dh20:
	sub	ax,es:DCNTRL_COUNT[bx]	; update the internal file number
	les	bx,es:DCNTRL_DSADD[bx]	; get the next entry and check
	cmp	bx,0FFFFh		;   for the end of the list
	 jnz	ifn2dh10 
ifn2dh15:
	pop	ax
	stc
	ret				; invalid file handle number



;
;	Allocate a DHNDL_ structure
;
; On Entry:
;	None
;
; On Exit:
;	CY clear if handle allocated
;	AX = IFN of handle
;	ES:BX -> DOS handle
;	(All other Regs preserved)
;
	Public	find_dhndl
find_dhndl:
	push cx ! push dx ! push di ! push si
	mov	ax,ss:machine_id	; get current process
	mov	dx,ss:owning_psp	; DX = owining PSP
	xor	si,si			; SI = IFN
	les	di,ss:file_ptr		; get the address of the first entry
find_dh10:
	mov	cx,es:DCNTRL_COUNT[di]	; get # handles in this block
	 jcxz	find_dh40		; skip if none
	lea	bx,DCNTRL_LEN[di]	; ES:BX -> 1st DHNDL_
find_dh20:
	push	cx
	cli				; be alone while looking at handles
	mov	cx,es:DHNDL_COUNT[bx]
	 jcxz	find_dh50		; if handle free grab it
	inc	cx			; FFFF = allocated but unused
	 jnz	find_dh30
	cmp	ax,es:DHNDL_UID[bx]	; was it allocated to us
	 jne	find_dh30
	cmp	dx,es:DHNDL_PSP[bx]	; if so use it again
	 je	find_dh60
find_dh30:
	sti				; finished with this handle
	pop	cx
	inc	si			; onto next IFN
	cmp	si,0FFh			; only handles 00-FE are valid
	 jae	find_dh45		;  so bail if out of range
	add	bx,DHNDL_LEN		; onto next handle in the block
	loop	find_dh20
find_dh40:
	les	di,es:DCNTRL_DSADD[di]	; get the next entry and check
	cmp	di,0FFFFh		;  it's valid
	 jne	find_dh10
find_dh45:
	stc				; no more handles,
	jmps	find_dh70		;  exit in failure..

find_dh50:
	mov	es:DHNDL_COUNT[bx],0FFFFh
	mov	es:DHNDL_UID[bx],ax	; allocate it to us
	mov	es:DHNDL_PSP[bx],dx
find_dh60:
	sti				; safe again
	pop	cx			; discard handle count
	xchg	ax,si			; AX = IFN
	mov	ss:word ptr current_dhndl,bx
	mov	ss:word ptr current_dhndl+WORD,es
	mov	ss:current_ifn,ax
	clc				; we have found and allocated a handle
find_dh70:
	pop di ! pop si ! pop dx ! pop cx
	ret


	Public	get_xftptr

get_xftptr:
;----------
; On Entry:
;	None
; On Exit:
;	ES:DI -> PSP_XFTPTR for current_psp
;	CX = # entries in it
;	CY set if not PSP operation (eg. FCB's)
;	(all other regs preserved)
;

	test	ss:byte ptr remote_call+1,DHM_FCB/100h; if we are doing an FCB operation
	 jnz	get_xftptr_err		;  deal only with IFN, forget PSP
	mov	es,ss:current_psp
	mov	cx,PSP_XFNMAX		; CX = # entries in table
	les	di,PSP_XFTPTR		; ES:DI -> user file table
	ret

get_xftptr_err:
	stc				; forget about XFN's
	ret


	Public	current_dsk2al
	
current_dsk2al:
;--------------
; AL = current default drive
	mov	al,ss:current_dsk
	ret

	Public	lds_si_dmaptr
	
lds_si_dmaptr:
;-------------
; On Entry:
;	None
; On Exit:
;	DS:SI -> current DMA address
;	(All other regs preserved)
	lds	si,ss:dword ptr dma_offset
	ret


	public	les_di_dmaptr

les_di_dmaptr:
;-------------
; On Entry:
;	None
; On Exit:
;	ES:DI -> current DMA address
;	(All other regs preserved)
	les	di,ss:dword ptr dma_offset
	ret

	Public copy_asciiz
	
copy_asciiz:
;----------
; Copy an ASCIIZ string from DS:SI to ES:DI
	lodsb ! stosb
	test	al,al
	 jnz	copy_asciiz
	ret

if JOIN

check_join:
;----------
; On Entry:
;	fdos_hds -> HDS we wish to check
; On Exit:
;	AH = drive (zero based) from fdos_hds_drv
;	AL = drive (zero based) of the JOIN root
;	if JOINed drive
;	    ZF clear
;	else
;	    ZF set
;	(All other regs presrved)
;
	push es ! push bx
	mov	al,fdos_hds_drv		; get drive from HDS_
	mov	ah,al			; save HDS_DRV in AH
 	cmp	join_drv,0		; need we do anything ?
	 je	check_join30		;  not if we haven't JOIN'd
	cmp	fdos_hds_root,0		; is virtual root the physical one ?
	 jne	check_join10		;  if not we can't be JOIN'd
	call	get_ldt			; ES:BX -> LDT for this drive
	 jc	check_join10		; bad LDT - we can't be joined
	test	es:LDT_FLAGS[bx],LFLG_JOINED
	 jz	check_join30
	mov	al,es:LDT_NAME[bx]	; get drive letter
	sub	al,'A'			; make drive letter zero based
	mov	bl,byte ptr path_drive	; get the logical drive we are on
	push	ax
	mov	al,bl			; AL = logical drive we are using
	call	get_ldt			; ES:BX -> LDT for this drive
	pop	ax
	 jc	check_join10		; no valid LDT..
	cmp	es:LDT_NAME+2[bx],'\'	; are we at the root ?
	 jne	check_join10		; no, it can't be match
	mov	bl,es:LDT_NAME[bx]	; get the root drive for this drive
	sub	bl,'A'			; make drive letter zero based
	cmp	al,bl			; are we on the JOIN'd drive ?
	mov	bl,0ffh			; assume we are
	 je	check_join20		; were we ?
check_join10:
	mov	al,ah			; restore HDS_DRV
	xor	bl,bl			; return with ZF clear
check_join20:
	test	bl,bl			; set ZF appropriately
check_join30:
	pop bx ! pop es
	ret

offer_join:		; are we opening a JOIN'd drive ?
;----------
; If we are at the root of a JOIN'd drive moving up ("..") fiddle HDS
; onto parental JOIN drive root.
; If we are at the root of a non-JOIN'd drive see if we are searching for
; a JOIN'd drive directory
; On Entry:
;	info_fcb = entry we are searching for
; On Exit:
;	CY set if not a JOIN'd drive
;

	cmp	join_drv,0		; need we do anything ?
	 jne	oj_dochecks		; not, if we haven't JOIN'd
oj_rejected:
	stc				; not a JOIN drive
	ret

oj_dochecks:
;-----------
; Before we do anything else we must be at the physical root of a drive
; with a valid LDT. We then check for two cases
; 1) Doing a '..' from a JOIN'd drive to it's parental root
; 2) Opening a directory correpsonding to a JOIN'd drive
;
	mov	al,info_fcb		; AL -> drive we are looking for
	call	get_ldt			; ES:BX -> LDT for this drive
	 jc	oj_rejected		; bad LDT - we can't be joined
	cmp	es:LDT_ROOTLEN[bx],2	; is root at top level ?
	 ja	oj_rejected		; no, skip the rest
	cmp	fdos_hds_blk,0		; are we at the root ?
	 jne	oj_rejected		; if not we needn't do anything

; We have validated HDS_, so now check for case 1)
	call	check_join		; is it a joined drive ?
	 jz	oj_dir			; if not skip to case 2)
	cmp	word ptr info_fcb+1,'..'; else is it a '..' in JOIN'd root?
	 jne	oj_rejected		; if not we needn't do anything
	call	mvhds_drvroot		; do '..' from root -> real root
	clc				; we handled it it !
	ret

oj_dir:
;------
; We are in the physical root of a non-joined drive. We now need to see if
; the dir we are searching for corresponds with a joined drive
;
	push si ! push di
	call	build_match_name	; join_name = what we are looking for
	call	look_for_match		; see if we can find it
	 jc	oj_dir10
	call	mvhds_drvroot		; we have a match - move into it
	clc				; say we handled it
oj_dir10:
	pop di ! pop si
	ret

	
look_for_match:
;--------------
; Compare join_name against available JOIN drives.
; Return with CY clear if we found it, ES:BX -> LDT, AL the drive
	xor	ch,ch
	mov	cl,join_drv		; search this many drives
	xor	ax,ax			; start with drive A:
	mov	ah,last_drv
	call	get_ldt			; ES:BX -> LDT for this drive
	 jnc	lfm20
	ret				; no LDT's...
lfm10:
	inc	al			; next drive
	cmp	al,ah			; paranioa - check if we have reached
	 jae	lfm50			;  last_drv and exit if so
	add	bx,LDT_LEN		; next LDT
lfm20:
	test	es:LDT_FLAGS[bx],LFLG_JOINED
	 jz	lfm10			; if not JOIN'd try next candidate

	lea	di,LDT_NAME[bx]		; ES:DI -> JOIN info
	mov	si,offset join_name	; lets see if it matches the
	push	ax
lfm30:
	lodsb				; get a byte
	scasb				; does it match ?
	 jne	lfm40			; no, forget it
	test	al,al			; end of the string yet ?
	 jnz	lfm30			; no, keep trying
lfm40:
	pop	ax
	 je	lfm60			; did we match ?
	loop	lfm10			; no, if any JOIN's left try them
lfm50:
	stc				; we didn't find it
lfm60:
	ret

build_match_name:
;----------------
; Fill join_name with the "C:\JOIN" we want to find
;
	mov	al,info_fcb		; AL -> drive we are looking for
	dec	al			; make it zero based
	call	get_ldt			; ES:BX -> LDT for this drive
	mov	al,es:LDT_NAME[bx]	; get the drive "D"
	push ds ! pop es		; ES -> SYSDAT
	mov	di,offset join_name	; construct the target name
	stosb				; plant the drive letter
	mov	ax,'\:'
	stosw				; now we have "d:\"
	mov	bx,offset info_fcb+1	; DS:SI -> name we are looking for
	jmp	unparse			; unparse the name

BDOS_DATA	dseg	word

join_name	db	'd:\filename.ext',0

BDOS_CODE	cseg

	Public	mv_join_root
	
mv_join_root:
;------------
; Poke the fdos_hds to be the root. If it's the physical root we then
; see if it is a JOIN'd drive. If it is we poke the drive and reselect
; the disk so we are at the real root of the drive.
;
	push bx ! push si ! push di	; save index registers
	mov	ax,fdos_hds_root
	mov	fdos_hds_blk,ax		; move us to virtual root
	test	ax,ax			; is it the real root ?
	 jnz	mvj_root10		; if not forget about JOIN'd drives
	call	check_join		; are we joined ?
	 jz	mvj_root10		; no, we've done enough
	call	mvhds_drvroot		; make it real root
mvj_root10:
	pop di ! pop si ! pop bx	; restore index registers
	ret


mvhds_drvroot:
;-------------
; On Entry:
;	AL = Drive (0 based physical)
; On Exit:
;	None
;
; Poke the HDS to be at the root of drive AL and select that drive
;
	mov	fdos_hds_drv,al		; change to joined drive
	xor	dx,dx
	mov	fdos_hds_blk,dx		; put us back to the root again
	mov	fdos_hds_root,dx
	cmp	al,physical_drv		; already there ?
	 je	mvhds_drvroot10		; then skip the selection
	call	select_physical_drv	; select the drive
mvhds_drvroot10:
	jmp	path_prep_root		; info_fcb = '.'
;	ret

endif	;JOIN

eject
stamp_dir_entry:
;---------------
; On Entry:
;	DIRP -> None
; On Exit:
;	None
;
; Apply current date/time stamp to a directory, along with any other
; security information required.
;
if PASSWORD
	mov	cx,local_password	; were we given a password ?
	 jcxz	stamp_dir_entry10	;  if so apply it
	mov	bx,dirp
	mov	DPWM[bx],PWM_ANY	; deny all for compatibility
	or	DATTS[bx],DA_HIDDEN	;  make dir entry hidden
	mov	DPWD[bx],cx		;  with this password
stamp_dir_entry10:
endif
	call	ReadTOD			; get current time/dat
	mov	bx,dirp
;	jmp	stamp_date_and_time
stamp_date_and_time:
; On Entry:
;	BX -> directory entry
;	AX = time
;	DX = date
; On Exit:
;	None
; stamp a directory entry with a given date and time
	mov	DDATE[bx],dx
	mov	DTIME[bx],ax
	mov	ah,PASSWD_CREAT		; call out to SECURITY TSR
	callf	ss:fdos_stub
	 jc	stamp_date_and_time10
	jmp	fdos_error		; return an error if required
stamp_date_and_time10:
	ret


	public	ReadTOD

ReadTOD:
;-------
; On Entry:
;	None
; On Exit:
;	DX = internal date format
;	AX = internal time format
;
	call	ReadTimeAndDate		; get current time/date from BIOS
;	jmp	GetTOD

GetTOD:
;-------
; On Entry:
;	None
; On Exit:
;	DX = internal date format
;	AX = internal time format
;
	mov	ax,yearsSince1980	; year is bits 9-15
	mov	cl,4
	shl	ax,cl
	add	al,month		; month is bits 4-8
	mov	cl,5
	shl	ax,cl

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -