📄 funcs.fdo
字号:
call check_handle ; check if legal file handle
mov ax,fdos_pb+4 ; get 32-bit file offset
mov dx,fdos_pb+6 ; into AX,DX
mov cx,fdos_pb+8 ; get seek mode
jcxz lseek4 ; seek from beginning
dec cx
jz lseek2 ; seek from current position
dec cx
jz lseek3 ; seek from end
mov ax,ED_DATA ; else invalid seek mode
jmp fdos_error ; return error code
lseek1:
ret ; return error code
lseek2: ; seek mode 1: relative to position
add ax,es:DHNDL_POSLO[bx]
adc dx,es:DHNDL_POSHI[bx]
jmps lseek4 ; update new position
lseek3: ; seek mode 2: relative to end
add ax,es:DHNDL_SIZELO[bx]
adc dx,es:DHNDL_SIZEHI[bx] ; add file size + offset
lseek4: ; seek mode 0: set absolute position
mov es:DHNDL_POSLO[bx],ax
mov es:DHNDL_POSHI[bx],dx
mov fdos_pb+4,ax ; set return values
mov fdos_pb+6,dx
ret
lseek_dev: ; jump here if character device
mov si,2[bp] ; SI -> parameter block
xor bx,bx
mov 4[si],bx ; always return result of 0000h
mov 6[si],bx
ret
eject
; GET/SET FILE ATTRIBUTES (CHMOD)
; +----+----+----+----+----+----+----+----+----+----+
; | 43 | name | flag | attrib |
; +----+----+----+----+----+----+----+----+----+----+
; | size |
; +----+----+----+----+
; entry:
; ------
; name: pointer to ASCIIZ file name
; flag: 00 = get attrib/size
; 01 = set attrib
; attrib: file attribute if flag=1
;
; exit:
; -----
; AX: 0000 or error code ( < 0)
; attrib: file attribute if flag=0
; size: file size if flag=0
;
if PASSWORD
; entry:
; ------
; name: pointer to ASCIIZ file name
; flag: 02 = get password mode
; 03 = set pw mode/password
; 04 = get encrypted password
; 05 = set encrypted password
; attrib: password mode if flag = 3,5
; dma: ascii password if flag = 3
; encrypted password if flag = 5
;
; exit:
; -----
; AX: 0000 or error code ( < 0)
; attrib: file's attribute if flag = 0
; password mode if flag = 2
; encrypted password if flag = 4
endif
if UNDELETE
; entry:
; ------
; name: pointer to ASCIIZ file name
; flag: 80 = undelete file
; 81 = purge file
; dma: result of sucessful search
;
; exit:
; -----
; AX: 0000 or error code ( < 0)
;
endif
fdos_chmod:
;----------
if UNDELETE
mov si,2[bp] ; SI -> parameter block
mov al,6[si] ; AX = flag
sub al,80h ; is it undelete or purge
jb fdos_chmod_path ; if so set
cmp al,1
ja fdos_chmod_path
call local_disk ; get MXdisk, switch stack
call select_from_DTA ; prepare for the search
mov chdblk,0 ; don't assume sequential access
dec dcnt ; retract so we find the same entry
call find_pending_delete ; did we find it ?
jz chmod_notfound ; No, then skip
call hdsblk ; AX = directory root cluster
xchg ax,dx ; DX = dir cluster
mov cx,dcnt ; CX = directory index for entry
mov ax,fdos_pb+6 ; get operation type
mov ah,DELW_UNDEL ; assume we are about to undelete
cmp al,80h ; is it undelete ?
je fdos_undelete_purge
mov ah,DELW_PURGE ; no, it must be purge entry
fdos_undelete_purge:
mov al,physical_drv ; give delwatch a chance to do it
callf ss:fdos_stub
jc fdos_ED_FUNCTION ; return error if DELWATCH not there
mov fdos_ret,ax ; else return result
ret
fdos_chmod_path:
endif
call redir_asciiz_offer
call local_disk ; get MXdisk, switch stack
call path_prep ; parse the path, go to bottom level
call chk_no_wild ; can't have wildcards
call finddfcbf ; find first matching FCB
jnz chmod10 ; if we can't find a file/dir
call chk_for_root ; check if we are in the root
jnz chmod_notfound ; if so return directory attribute
mov cx,fdos_pb+6 ; but only for get attributes
jcxz chmod_root ; other fall through to not found
chmod_notfound:
jmp fdos_ED_FILE
chmod_root:
mov fdos_pb+8,DA_DIR ; return directory attribute
ret
fdos_ED_FUNCTION:
mov ax,ED_FUNCTION ; invalid subfunction
jmp fdos_error
chmod10:
mov bx,dirp ; BX -> matching directory entry
mov ax,DSIZE[bx]
mov fdos_pb+10,ax
mov ax,DSIZE+WORD[bx]
mov fdos_pb+12,ax
xor ax,ax
mov al,DATTS[bx] ; get directory attributes
mov cx,fdos_pb+6 ; get function #
jcxz chmod30 ; always allow get attribs
if PASSWORD
cmp cl,5 ; validate sub-function number
ja chmod15
mov ax,DPWM[bx] ; assume return password mode
and ax,PWM_ANY ; isolate password mode bits
cmp cl,2 ; is it get mode ?
je chmod30 ; yes, just return it
push ax
push cx
call check_pwd_any ; check the password
pop cx
pop ax
mov dx,fdos_pb+8 ; DX = new attributes
cmp cl,2 ; is it get mode ?
ja chmod20 ; how about other password functions?
else
cmp cl,1 ; validate sub-function number
ja chmod15
mov dx,fdos_pb+8 ; DX = new attributes
endif
; Set new file attrib
; BX = DIRP
; DX = attrib
;
test dl,DA_DIR ; directory bit not allowed
jnz chmod12
xor dl,DATTS[bx] ; check which bits are changed
and dl,not DA_DIR ; don't check or flip directory bit
test dl,DA_FIXED ; trying to change the unchangeable?
jz chmod13
chmod12:
jmp fdos_ED_ACCESS ; return "access denied"
chmod13:
xor DATTS[bx],dl ; set new attributes
if PASSWORD
jmps chmod90
else
jmp update_dir ; update directory
endif
chmod15:
mov ah,PASSWD_CHMOD ; call out to SECURITY TSR
callf ss:fdos_stub
jc fdos_ED_FUNCTION
jmps chmod90
if PASSWORD
chmod20:
; Password support for functions 3-5
; BX = DIRP
; CX = flag
; DX = attrib
;
push bx
push cx
push dx
mov di,S_DENY_IF_OPEN ; check if file already open
call check_with_share ; and stop if it is
pop dx
pop cx
pop bx
mov ax,DPWD[bx] ; assume get encrypted password
cmp cl,4 ; was it ?
jne chmod50
endif ; yes, return encrypted password
chmod30:
mov fdos_pb+8,ax
ret
if PASSWORD
; Password support for functions 3/5
; BX = DIRP
; CX = flag
; DX = attrib
;
chmod50: ; set password/password mode
test dh,80h ; assign new password?
jz chmod70 ; skip if mode change only
mov di,offset save_area ; ES:DI -> local structure
push ds
call lds_si_dmaptr ; DS:SI -> users DMA address
lodsw ; AX = possible encrypted password
cmp cl,5 ; was it set encrypted password ?
je chmod60
dec si ; no, the DMA buffer contains
dec si ; an 8 character password so we
call hash_pwd ; compute password hash code
chmod60:
pop ds
or DATTS[bx],DA_HIDDEN ; file will be hidden
mov DPWD[bx],ax ; set new file password
test ax,ax ; null password?
jnz chmod70
xor dx,dx ; can't be protected....
chmod70:
mov ax,not PWM_ANY ; clear existing file
and DPWM[bx],ax ; password mode bits
not ax ; isolate password mode bits
and dx,ax ; in new password mode
jz chmod80 ; if no protection, leave them off
test DATTS[bx],DA_DIR ; directories protected in all modes
jz chmod80 ; skip if not a directory
xchg ax,dx ; force all modes on
chmod80:
or DPWM[bx],dx ; set password mode bits
test dx,dx ; test if protection enabled
jnz chmod90 ; skip if any protection still active
mov DPWD[bx],dx ; remove the password and hidden bit
and DATTS[bx],not DA_HIDDEN ; as file is no longer protected
endif
chmod90:
jmp update_dir ; now update the directory
eject
; DUPLICATE FILE HANDLE (DUP)
; +----+----+----+----+----+----+
; | 45 | handle | newhnd |
; +----+----+----+----+----+----+
; entry:
; ------
; handle: open file handle
; exit:
; -----
; newhnd: new file handle
; AX: duplicate file handle or error code ( < 0)
fdos_dup:
;--------
call find_xfn ; find new external file #
mov si,2[bp] ; SI -> parameter block
mov ds:4[si],di ; save new handle #
jnc fdos_fdup ; share the code with DUP2
mov bx,ED_HANDLE ; can't find a handle
ret
eject
; FORCE DUPLICATE FILE HANDLE (DUP2)
; +----+----+----+----+----+----+
; | 46 | handle | newhnd |
; +----+----+----+----+----+----+
; entry:
; ------
; handle: open file handle
; newhnd: new file handle
; exit:
; -----
; AX: duplicate file handle or error code ( < 0)
fdos_fdup:
;---------
call vfy_dhndl_ptr ; check file handle #
call local_disk ; get critical section locks
call get_xftptr ; ES:DI -> XFN table
jc dup_err ; we need one..
mov bx,fdos_pb+4 ; get user file number (0-19)
cmp bx,cx ; is it sensible ?
jae dup_err
cmp es:byte ptr [di+bx],0FFh
jne dup_err ; handle should be closed by PCMODE..
call check_handle ; check if legal file handle
inc es:DHNDL_COUNT[bx] ; another user
call dup_dev ; inform device driver it's happened
call get_xftptr ; ES:DI -> XFT's
mov bx,fdos_pb+2 ; get XFN to dup from
mov al,es:[di+bx] ; get it's IFN
mov bx,fdos_pb+4 ; BX = XFN to dup to
mov es:[di+bx],al ; it gets same IFN
mov fdos_ret,bx ; return XFN to caller
ret
dup_err: ; complain someone stole my handle
jmp fdos_ED_H_MATCH
eject
; GET CURRENT DIRECTORY
;
; +----+----+----+----+----+----+----+----+
; | 47 | drive | path |
; +----+----+----+----+----+----+----+----+
; entry:
; ------
; drive: drive to get path for
; path: address of 64 byte path buffer to be
; filled in with current path
; exit:
; -----
; BX: 0100 or error code
fdos_curdir:
;-----------
call local_disk ; it's a disk function
call get_pb2_drive ; get specified drive in AL
call get_ldt ; ES:BX -> LDT_ for drive
jc fdos_curdir30
mov dx,es:LDT_FLAGS[bx]
test dx,LFLG_NETWRKD
jnz fdos_curdir10
test dx,LFLG_PHYSICAL
jz fdos_curdir30
call select_unique ; select the drive for media changes
les bx,ss:current_ldt ; ES:BX -> LDT_ for this drive
cmp es:LDT_BLK[bx],0FFFFh ; is LDT valid
jne fdos_curdir10
call rebuild_ldt_curdir ; no, better rebuild it
fdos_curdir10:
push ds
push es ! push bx ; save LDT
les di,dword ptr fdos_pb+4 ; ES:DI -> destination buffer
pop si ! pop ds ; DS:SI -> LDT
add si,ds:LDT_ROOTLEN[si] ; skip the '\\server\dir'
lodsb ; eat the slash
call check_slash ; if it is one..
je fdos_curdir20
dec si ; I didn't mean it!
fdos_curdir20:
call copy_asciiz ; copy the string
pop ds
mov fdos_ret,100h ; return 100h for success
ret
fdos_curdir30:
jmp fdos_ED_DRIVE ; naughty - it's a bad drive
eject
; GET DISK PARAMETER BLOCK
; +----+----+----+----+----+----+----+----+----+----+
; | 48 | drive | dpb | adjust |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; drive: drive to get information about
; (top bit of word set if free space not required)
; exit:
; -----
; AX: 0000 or error code ( < 0)
; dpb: address of DOS DPB (offset/segment)
; adjust: delwatch adjustment of free space
fdos_getdpb:
;-----------
call redir_drv_offer
call local_disk ; get MXdisk, switch stack
call get_pb2_drive ; get drive from parameter block
call logical2physical ; AX = physical drive
call select_physical_drv
test fdos_pb+2,8000h ; free space required ?
jnz fdos_getdpb10
call update_ddsc_free ; then make sure it is up to date
if DELWATCH
xor cx,cx ; assume no adjustment
mov ah,DELW_SPACE
mov al,physical_drv ; now we call DELWATCH to
callf fdos_stub ; add pending deletes
mov fdos_pb+8,cx ; return free space adjust value
endif
fdos_getdpb10:
les ax,ss:current_ddsc
mov fdos_pb+4,ax
mov fdos_pb+6,es
ret
eject
; FLUSH BUFFERS
; +----+----+
; | 49 |
; +----+----+
; entry:
; ------
; none
; exit:
; -----
; none
fdos_flush:
;----------
call local_disk ; be alone...
fdos_flush_local:
; Entry point for people who already have the MX disk
xor dx,dx ; starting with drive A
fdos_flush10:
push dx
call mark_ldt_unsure ; ask for LDT's to be relogged
xchg ax,dx ; AL = drive to check
mov ah,BF_DIRTY
call buffers_check ; any buffers on this drive?
jz fdos_flush20 ; skip flush if none
call select_physical_drv ; select drive in AL
call update_fat ; flush all FAT buffers
; call update_dir ; dir always up to date
call update_dat ; flush all data buffers
fdos_flush20:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -