📄 redir.a86
字号:
push ds ! push bp
mov si,2[bp] ; SI -> parameter block
lds si,2[si] ; DS:SI -> user supplied name
mov dx,si ; DS:DX as well..
push ss ! pop es
mov di,offset pri_pathname ; DI -> where to build pathname
mov ax,I2F_PPATH
int 2fh ; offer path build to someone else
pop bp ! pop ds
ret
build_remote_path:
;-----------------
; On Entry:
; DS:SI -> path to check
; SS:DI -> position to build remote path
; On Exit:
; CY clear, CX == 0 if it's a valid remote path
; CY clear, CX <> 0 if it's a local path
; CY set if there is an error to be returned (BX = error code)
;
mov cx,si ; save source path in CX
mov dl,ss:current_dsk ; assume current disk
lodsw ; get 1st two characters
test al,al ; make sure it's not a NUL string
jz build_remote_path10 ; before we check it it's a
cmp ah,':' ; drive specified
jne build_remote_path10 ; we want to find "d:\\" format too
mov bx,ED_DRIVE ; assume "invalid drive" error
and al,not 'a'-'A' ; cheap upper case
sub al,'A'
jb build_remote_path30 ; return "invalid drive" if error
cmp al,ss:last_drv ; check if > 'Z'
ja build_remote_path30 ; return "invalid drive" if error
xchg ax,dx ; DL = ASCIIZ supplied drive
lodsw ; get possible '\\'
build_remote_path10:
mov ss:word ptr current_ldt,0ffffh
call check_dslash ; is it "\\"
je build_remote_path20 ; if so forget about the drive #
call isremote ; test if drive DL is remote
if JOIN
jb build_remote_path30 ; return "invalid drive" if JOINed
endif
jnz build_remote_path20 ; it's remote, go build a path
xor cx,cx ; CY clear (no error)
inc cx ; CX <> 0, (non-remote drive)
ret
build_remote_path20:
; Build a path from the CSD and the pathname in the parameter block
mov si,cx ; DS:SI -> source ASIIZ name
push ss ! pop es ; ES:DI -> MSNET buffer
call redir_build_path
jc build_remote_path30
xor cx,cx ; CY clear, CX == 0
ret ; it's a valid remote path
build_remote_path30:
stc ; CY set, we have error BX
ret
eject
; MAKE DIRECTORY (MKDIR)
; +----+----+----+----+----+----+
; | 39 | name |
; +----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; exit:
; -----
; BX: 0000 or error code ( < 0)
redir_mkdir:
mov ax,I2F_MKDIR ; it's a make dir
jmps redir_pathop_common
eject
; REMOVE DIRECTORY (RMDIR)
; +----+----+----+----+----+----+
; | 3A | name |
; +----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; exit:
; -----
; BX: 0000 or error code ( < 0)
redir_rmdir:
mov ax,I2F_RMDIR ; it's a remove dir
; jmp redir_pathop_common
redir_pathop_common:
push ds
push ss ! pop ds
call int2f_ldt
pop ds
jc redir_pathop_common10
xor ax,ax ; no problems
redir_pathop_common10:
xchg ax,bx ; return result in BX
ret
eject
; CHANGE DIRECTORY (CHDIR)
; +----+----+----+----+----+----+
; | 3B | name |
; +----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; exit:
; -----
; BX: 0000 or error code ( < 0)
redir_chdir:
;------------
; The following code throws out the ASSIGN/SUBST form "f:=d:\"
; The alternative is to allow the Extentions to throw it out as a bad path
; but this is safer, and doesn't cost us much.
push ds
mov bx,ED_PATH ; assume we have a problem
; BX = ED_PATH ready for error
mov si,2[bp] ; SI -> parameter block
lds si,ds:2[si] ; DS:SI -> ASCIIZ string
cmp ds:word ptr 1[si],'=:' ; 'd:=' specification?
je redir_chdir40
push ss ! pop ds ; DS = PCMODE
cmp word ptr current_ldt,-1
je redir_chdir40 ; we reject any chdir of the form
; "\\server\path"
mov ax,I2F_CHDIR
call int2f_ldt ; is this a valid path ?
jc redir_chdir30
push ds ! pop es
mov si,offset pri_pathname
; DGM - don't allow path greater than 66 chars
mov cx, LDT_FLAGS-LDT_NAME ; calculate max pathlen from LDT
mov di, si
sub ax,ax
repne scasb
mov ax, ED_PATH ; assume path too long
jne redir_chdir30 ; jump if path too long
les di,current_ldt ; ES:DI -> path for this drive
call copy_asciiz ; copy new path to LDT current dir
xor ax,ax ; no errors
redir_chdir30:
xchg ax,bx ; return result in BX
redir_chdir40:
pop ds
ret
eject
; CREATE FILE (CREAT)
; +----+----+----+----+----+----+----+----+
; | 3C | name | mode |
; +----+----+----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; mode: attribute for file
; exit:
; -----
; BX: file handle or error code ( < 0)
redir_creat:
call get_attrib_mode ; AX = mode, CX = attrib
xchg ax,cx
or ax,20h ; set the ARCHIVE bit on create
mov file_attrib,ax
mov int2f_stack,ax ; attrib on stack
mov int2f_cmd,I2F_CREATE
cmp word ptr current_ldt,-1 ; valid LDT ?
jne redir_creat10 ; no, modify create function
mov int2f_cmd,I2F_XCREATE
redir_creat10:
jmp redir_open_create_common
eject
; OPEN FILE (OPEN)
; +----+----+----+----+----+----+----+----+----+----+
; | 3D | name | mode | attrib |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; mode: open mode
; attrib: file attrib for search (default = 16h)
; exit:
; -----
; BX: file handle or error code ( < 0)
redir_open:
;----------
;
call get_attrib_mode ; AX = mode, CX = attrib
and ax,7fh ; remove inheritance bit
mov int2f_stack,ax
mov int2f_cmd,I2F_OPEN
redir_open_create_common:
call find_xfn ; get external file handle in DI
mov bx,ED_HANDLE ; assume no handles
jc redir_open20
push di
call redir_openfile ; now do the open
pop di
jc redir_open20
; On Entry:
; AL = IFN
; DI = XFN
; ES:BX -> DHNDL_
; On Exit:
; PSP fixed up
;
mov bx,di
call get_xftptr ; ES:DI -> XFN table
jc redir_open10 ; no PSP, skip xfn stuff
add di,bx ; add external file #
stosb ; update table entry
ret
redir_open10:
xchg ax,bx ; no PSP, return XFN in BX
redir_open20:
ret
redir_openfile:
;--------------
; On Entry:
; pri_pathname and file_attrib have been set up
; On Exit:
; AL = IFN
; ES:BX = DHNDL_
; CY set on error, BX = error code
; We should set up COUNT, MODE, UID, PSP, and SHARE
call find_dhndl ; find DHNDL_
jc redir_openf40 ; return if a problem with this
push ax ; save IFN
push es ! push bx ; save DHNDL_
mov ax,file_mode
and al,not DHM_LOCAL
mov es:DHNDL_MODE[bx],ax ; save mode in DOSHNDL
mov es:DHNDL_SHARE[bx],0 ; zero share record
mov ax,int2f_cmd ; either open or create
call int2f_dhndl ; lets try the command
pop bx ! pop es ; recover DHNDL_
pop dx ; recover IFN
jc redir_openf30 ; on error discard the handle
xchg ax,dx ; return AL = IFN
mov es:DHNDL_COUNT[bx],1 ; handle now properly in use
mov cx,file_mode
test ch,DHM_FCB/256 ; is this an FCB open ?
jz redir_openf10
or es:byte ptr DHNDL_MODE+1[bx],DHM_FCB/100h
redir_openf10:
test cl,DHM_LOCAL ; is it a "private" file ?
jz redir_openf20
or es:byte ptr DHNDL_WATTR+1[bx],DHAT_LOCAL/100h
redir_openf20:
ret
redir_openf30:
xchg ax,bx ; returning error in BX
ret
redir_openf40:
mov bx,ED_HANDLE ; no handles are left
ret
eject
; CLOSE FILE (CLOSE)
; +----+----+----+----+
; | 3E | handle |
; +----+----+----+----+
; entry:
; ------
; handle: open file handle to be closed
; exit:
; -----
; BX: 0000 or error code ( < 0)
redir_close:
;------------
;
mov si,2[bp] ; SI -> parameter block
mov ax,2[si] ; get external file #
call get_xftptr ; ES:DI -> xft table
jc redir_close10
add di,ax ; add in XFN
mov ax,0FFh ; get "unused" value for XFT
xchg al,es:[di] ; release file & get internal #
redir_close10: ; we can now do the actual close
call ifn2dhndl ; ES:BX -> DHNDL_
jc redir_close30 ; exit if error occurrs
mov ax,es:DHNDL_COUNT[bx]
mov ah,3eh ; count, AH = 3E
push ax
mov ax,I2F_CLOSE
call int2f_dhndl ; close it
pop bx
jnc redir_close20 ; errors ?
xchg ax,bx ; recover return code
redir_close20:
ret
redir_close30:
mov bx,ED_H_MATCH ; assume invalid IFN
ret
eject
; READ FROM FILE (READ)
; +----+----+----+----+----+----+----+----+----+----+
; | 3F | handle | buffer | count |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; handle: open file handle
; buffer: buffer to read into
; count: max. number of bytes to read
; exit:
; -----
; BX: error code ( < 0)
redir_read:
;----------
mov ax,I2F_READ
redir_rw_handle:
mov si,2[bp] ; SI -> parameter block
mov cx,8[si] ; CX = Count
push ds
lds dx,4[si] ; DS:DX = DMA address
call redir_rw
pop ds
mov si,2[bp] ; SI -> parameter block
mov 8[si],cx ; CX = Count
ret
eject
; WRITE TO FILE (WRITE)
; +----+----+----+----+----+----+----+----+----+----+
; | 40 | handle | buffer | count |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; handle: open file handle
; buffer: buffer to be wriiten
; count: max. number of bytes to write
; exit:
; -----
; BX: error code ( < 0)
redir_write:
;-----------
mov ax,I2F_WRITE
jmps redir_rw_handle
redir_rw:
;--------
; On Entry:
; AX = command code
; ES:BX = DHNDL_
; CX = count
; DS:DX = buffer
; On Exit:
; CX = count transferred
; BX = zero or error code
;
cmp ax,I2F_WRITE ; is it a write ?
jne redir_rw10
and es:DHNDL_WATTR[bx],not (DHAT_CLEAN+DHAT_TIMEOK)
redir_rw10:
push ss:dma_offset
push ss:dma_segment
push cx
mov cl,4
mov di,dx ; save dma offset
and dx,15 ; make offset within para
shr di,cl ; convert offset to para offset
mov si,ds ; add to segment
add di,si ; DI:DX -> DMA address
ja redir_rw15 ; are we within normal TPA ?
inc di ; no adjust to offset within
shl di,cl ; magic segment FFFF
add dx,di
mov di,0ffffh ; use magic segment
redir_rw15:
pop cx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -