📄 utils.fdo
字号:
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 + -