REDIR.A86
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:46k
源码类别:
操作系统开发
开发平台:
Asm
- title 'REDIR - DOS file system network redirector interace support'
- ; File : $REDIR.A86$
- ;
- ; Description :
- ;
- ; Original Author : DIGITAL RESEARCH
- ;
- ; Last Edited By : $CALDERA$
- ;
- ;-----------------------------------------------------------------------;
- ; Copyright Work of Caldera, Inc. All Rights Reserved.
- ;
- ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
- ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
- ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
- ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
- ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
- ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
- ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
- ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
- ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
- ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
- ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
- ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
- ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
- ; CIVIL LIABILITY.
- ;-----------------------------------------------------------------------;
- ;
- ; *** Current Edit History ***
- ; *** End of Current Edit History ***
- ; $Log: $
- ; REDIR.A86 1.30 94/12/01 10:05:21
- ; added attribute support for open/move/unlink
- ; REDIR.A86 1.29 94/11/11 15:10:03
- ; Code at redir_lseek30 changed to ensure that the file offset is
- ; updated. Previously, this did not happen when INT 21/4202 (seek from
- ; end of file) was called, and consequently the game MYST could not
- ; be installed under NWDOS7.
- ; REDIR.A86 1.28 94/10/03 15:41:12
- ; fix problem where VLM network mapping gets deleted if you try to access
- ; a path greater than 66 characters long on a network drive.
- ; REDIR.A86 1.27 94/02/22 18:05:09
- ; fix problem with "d:\filename.ext" (Netware 4 LOGIN)
- ; REDIR.A86 1.26 94/01/10 16:42:16
- ; File delete uses file attributes of 06, not 16 (no directory bit)
- ; REDIR.A86 1.25 93/12/10 00:03:09
- ; Move non-inherited bit to correct place in file handle
- ; REDIR.A86 1.22 93/11/19 23:59:00
- ; If a read/write returns ED_LOCKFAIL turn into ED_ACCESS on shared files
- ; REDIR.A86 1.21 93/09/24 19:50:50
- ; Tidy up code on rename
- ; REDIR.A86 1.15 93/06/16 16:22:21
- ; Always initialise file search attributes to 16h (ie. sys+hidden+dir)
- ; REDIR.A86 1.14 93/06/11 15:08:09
- ; Return 0 from search first/next
- ; REDIR.A86 1.13 93/06/11 02:06:53
- ; zero space adjust on getddsc
- ; ENDLOG
- eject ! include i:psp.def
- eject ! include i:fdos.equ
- eject ! include i:msdos.equ
- eject ! include i:mserror.equ
- eject ! include i:doshndl.def ; DOS Handle Structures
- eject ! include i:f52data.def ; DRDOS Structures
- eject ! include i:redir.equ
- FD_EXPAND equ 55h
- eject
- PCMODE_DATA dseg
- extrn current_dsk:byte
- extrn current_ddsc:dword
- extrn current_dhndl:dword
- extrn current_filepos:dword
- extrn current_ldt:dword
- extrn dma_offset:word
- extrn dma_segment:word
- extrn err_drv:byte
- extrn file_attrib:word
- extrn ldt_ptr:dword
- extrn last_drv:byte
- extrn phys_drv:byte
- extrn pri_pathname:byte
- extrn remote_call:word
- extrn sec_pathname:byte
- extrn srch_buf:byte
- ; Data for some int2f commands
- extrn int2f_cmd:word
- extrn int2f_stack:word
- extrn file_mode:word
- BDOS_CODE cseg
- Public islocal
- Public redir_asciiz_dev_offer
- Public redir_asciiz_offer
- Public redir_asciiz_file_offer
- Public redir_drv_offer
- Public redir_dhndl_offer
- Public redir_move_offer
- Public redir_snext_offer
- extrn toupper:near
- extrn check_delim:near
- extrn check_slash:near
- extrn check_dslash:near
- extrn copy_asciiz:near
- extrn unparse:near
- extrn find_xfn:near
- extrn find_dhndl:near
- extrn ifn2dhndl:near
- extrn get_xftptr:near
- if KANJI
- extrn dbcs_lead:near
- endif
- redir_dhndl_offer:
- ;================
- ; The FDOS has called this hook to see if we are operating on an MSNET drive.
- ; We return if we are not, or stay and process function here if we are
- test es:byte ptr DHNDL_WATTR+1[bx],DHAT_REMOTE/100h
- jnz redir_dhndl_accept
- ret
- redir_dhndl_accept:
- ; copy some info from DHNDL_ to local variables
- push ds
- push ss ! pop ds
- mov ax,es:DHNDL_DEVOFF[bx]
- mov word ptr current_ddsc,ax
- mov ax,es:word ptr DHNDL_DEVSEG[bx]
- mov word ptr current_ddsc+WORD,ax
- mov ax,es:word ptr DHNDL_POS[bx]
- mov word ptr current_filepos,ax
- mov ax,es:word ptr DHNDL_POS+2[bx]
- mov word ptr current_filepos+2,ax
- pop ds
- jmps redir_accept ; now we can process the call
- redir_asciiz_dev_offer:
- ;======================
- ; The FDOS has called this hook to see if we are opening a redirected device.
- ; We return if we are not, or stay and process function here if we are
- ; Before we build it all ourselves do the appropriate INT 2F to allow
- ; other people to process the path themselves
- call redir_dev_check ; is it a device ?
- jnc redir_accept ; it's been recognised
- ret
- redir_move_offer:
- ;================
- ; The FDOS has called this hook to see if the rename operation is on a
- ; redirected drive. Lantastic relies on the path check broadcast's being
- ; done in the order new_name, old_name.
- mov word ptr current_ldt,0ffffh
- mov err_drv,DHAT_DRVMSK
- push ds
- mov si,2[bp] ; SI -> parameter block
- lds si,10[si] ; DS:SI -> user supplied name
- push ss ! pop es
- mov di,offset sec_pathname ; DI -> where to build pathname
- push ds ! push si ! push di ! push bp
- mov ax,I2F_PPATH
- int 2fh ; offer path build to someone else
- pop bp ! pop di ! pop si ! pop ds
- mov cx,0 ; if accepted then it's a remote drive
- jnc redir_move_offer10
- call build_remote_path ; build path if it a remote drive
- redir_move_offer10:
- pop ds
- jc redir_asciiz_error ; return error's if we have any
- jcxz redir_asciiz_offer ; it's a valid remote path
- ret ; it's not a remote path
- redir_asciiz_offer:
- ;==================
- ; The FDOS has called this hook to see if we are operating on an redirected
- ; drive. We return if we are not, or stay and process function here if we are.
- call redir_dev_check ; is it a device ?
- jnc redir_accept ; it's been recognised
- ; jmp redir_asciiz_file_offer ; now try offering as a file
- redir_asciiz_file_offer:
- ;=======================
- ; entry: SS:BP -> function #, parameter address
- ; 1st level call (MXdisk not owned)
- ; exit: ZF = 1 if not networked
- ;
- ; This function is only called after an Int 2F/I2F_PPATH callout has been
- ; made and failed. On some functions (Open/Create) we do a check for devices
- ; between the redir_dev_offer and redir_asciiz_file offer
- ; We look for a "\" as the start of "\serverdirfile" form
- push ds ; save DS
- mov si,2[bp] ; SI -> parameter block
- lds si,2[si] ; get ASCIIZ # from parameter block
- mov di,offset pri_pathname ; SS:DI -> path buffer
- call build_remote_path ; build path if it a remote drive
- pop ds ; restore DS
- jc redir_asciiz_error ; return error's if we have any
- jcxz redir_accept ; it's a valid remote path
- ret ; it's not a remote path
- redir_asciiz_error:
- ; On Entry:
- ; BX = error code
- ; DS on stack
- ; On Exit:
- ; DS restored, BX preserved
- ; near return on stack discarded, and error returned to fdos_entry
- ;
- pop ax ; discard "offer" near ret
- ret ; drop straight back to caller
- redir_drv_offer:
- ;===============
- ; The FDOS has called this hook to see if we are operating on an MSNET drive.
- ; We return if we are not, or stay and process function here if we are
- ;
- ; entry: SS:BP -> function #, parameter address
- ; (MXdisk not owned)
- ; exit: return if not networked
- mov dl,current_dsk ; assume it's the default drive
- mov si,2[bp] ; SI -> parameter block
- mov ax,2[si] ; get drive # from parameter block
- test al,al ; test if default drive
- jz redir_drv_offer10 ; skip if default drive
- dec ax ; else decrement for 0..26
- xchg ax,dx ; and use that
- redir_drv_offer10:
- call isremote
- jnz redir_accept
- ret ; return if not
- redir_snext_offer:
- ;=================
- ; The FDOS has called this hook to see if we are operating on an MSNET drive.
- ; We return if we are not, or stay and process function here if we are
- call redir_restore_srch_state
- test al,80h ; MSNET drive ?
- jnz redir_accept
- ret
- redir_accept:
- ;============
- ; We have decided to accept an FDOS function.
- ; Note by this time the functions have been validated as legal
- mov file_attrib,16h ; default search attribs to all
- pop si ; discard the near return address
- mov si,2[bp] ; SI -> parameter block
- mov si,ds:[si] ; fdos code number
- add si,si ; make it a word offset
- jmp cs:redir_tbl-(39h*WORD)[si] ; call the relevant function
- redir_badfunc:
- ;-------------
- mov bx,ED_FUNCTION ; bad function number
- ret ; (shouldn't get here...)
- redir_tbl dw redir_mkdir ; 39-make directory
- dw redir_rmdir ; 3A-remove directory
- dw redir_chdir ; 3B-change directory
- dw redir_creat ; 3C-create file
- dw redir_open ; 3D-open file
- dw redir_close ; 3E-close file
- dw redir_read ; 3F-read from file
- dw redir_write ; 40-write to file
- dw redir_unlink ; 41-delete file
- dw redir_lseek ; 42-set file pointer
- dw redir_chmod ; 43-get/set file attributes
- dw redir_badfunc ; 44-IOCTL emulation
- dw redir_badfunc ; 45-duplicate handle
- dw redir_badfunc ; 46-force duplicate handle
- dw redir_badfunc ; 47-get current directory
- dw redir_getdpb ;*48*disk information
- dw redir_badfunc ;*49*flush buffers
- dw redir_badfunc ;*4A*drive select
- dw redir_badfunc ;*4B*create child PSP
- dw redir_badfunc ;*4C*close child PSP
- dw redir_badfunc ;*4D*generic FCB call
- dw redir_first ; 4E-find first matching file
- dw redir_next ; 4F-find next matching file
- dw redir_commit ;*50*commit file
- dw redir_mknew ;*51*make new file
- dw redir_lock ;*52*lock/unlock block
- dw redir_badfunc ; 53 build DDSC from BPB
- dw redir_badfunc ;*54*Int 25/26 emulation
- dw redir_expand ; 55 expand file name
- dw redir_move ; 56-rename file
- dw redir_dattim ; 57-get/set file name
- Public get_ldt
- ; To support func5D00 remote server calls we must bypass the LDT and
- ; go directly to the physical drive. To allow support of CDROM's etc
- ; on servers we do use the LDT's where no corresonding physical drive
- ; exists.
- get_ldt:
- ;-------
- ; On Entry:
- ; AL = drive (0 based)
- ; On Exit:
- ; ES:BX -> LDT for that drive, set CY if no valid LDT
- ; (All other regs preserved)
- ;
- cmp al,ss:phys_drv ; if there is no conflict with
- jae get_ldt_raw ; physical drives it's OK
- test ss:remote_call,0ffh ; remote calls must get to physical
- jz get_ldt_raw ; for server support
- mov bx,ED_DRIVE ; invalid drive
- stc ; no-go
- ret
- Public get_ldt_raw
- get_ldt_raw:
- ;-----------
- ; On Entry:
- ; AL = drive (0 based)
- ; On Exit:
- ; ES:BX -> LDT for that drive, set CY if no valid LDT
- ; (All other regs preserved)
- ;
- push ax
- mov bx,ED_DRIVE ; assume invalid drive
- cmp al,ss:last_drv ; do we have an LDT for this drive ?
- jae get_ldt10 ; if not we can't have an LDT
- cmp ss:word ptr ldt_ptr+2,0 ; are the LDT's allocated yet ?
- je get_ldt10 ; if not return an error
- mov bl,LDT_LEN
- mul bl ; AX = offset of LDT entry for drive
- les bx,ss:ldt_ptr ; get base of LDT's
- add bx,ax ; DS:BX -> LDT for this drive
- stc ; ie. CLC on exit
- get_ldt10:
- cmc
- pop ax
- ret
- get_ldt_flags:
- ;-------------
- ; entry: DL = drive number
- ; exit: AX = LDT_FLAGS entry for that drive
- ; (All other regs preserved)
- ;
- push es
- push bx
- xor ax,ax ; assume no LDT around...
- xchg ax,dx ; AL = drive number
- call get_ldt ; ES:BX -> LDT
- xchg ax,dx ; restore drive to DX
- jc glf10 ; AX = zero if no LDT
- mov ss:word ptr current_ldt,bx ; set current_ldt
- mov ss:word ptr current_ldt+2,es
- mov ax,es:LDT_FLAGS[bx] ; return real flags
- glf10:
- pop bx
- pop es
- ret
- islocal:
- ;-------
- ; entry: AL = drive number (zero based)
- ; exit: CY = set if drive is remote
- ; (All other regs preserved)
- ;
- push ax
- push dx
- xchg ax,dx
- call get_ldt_flags
- if JOIN
- test ax,LFLG_JOINED+LFLG_NETWRKD
- ; are REMOTE/JOINED bits set ?
- else
- test ax,LFLG_NETWRKD ; is REMOTE bit set ?
- endif
- jz islocal10
- stc ; indicate it's not local
- islocal10:
- pop dx
- pop ax
- ret
- isremote:
- ;--------
- ; entry: DL = drive number
- ; exit: ZF = clear if drive is remote
- ; CY = set if drive is JOIN'd
- ; (Only AX corrupted)
- ;
- call get_ldt_flags
- if JOIN
- test ax,LFLG_JOINED ; is JOINED bit set ?
- jnz isremote10
- endif
- test ax,LFLG_NETWRKD ; is REMOTE bit set ?
- ret
- if JOIN
- isremote10:
- test ax,LFLG_NETWRKD ; is REMOTE bit set ?
- stc ; STC to indicate JOIN'd
- ret
- endif
- redir_dev_check:
- ;---------------
- ; Offer the name to the network as a device
- ; On Entry:
- ; PB+2 = dword ptr to ascii name
- ; DI -> buffer to parse into
- ; On Exit:
- ; CY set if not recognised
- ;
- mov word ptr current_ldt,0ffffh
- mov err_drv,DHAT_DRVMSK
- 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
- ; "\serverpath"
- 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
- mov ss:dma_offset,dx ; save for xfer
- mov ss:dma_segment,di
- call int2f_dhndl ; try the xfer
- pop ss:dma_segment
- pop ss:dma_offset
- mov bx,0 ; assume no error
- jnc redir_rw20
- xchg ax,bx ; return error code
- cmp bx,ED_LOCKFAIL ; is it a lockfail error ?
- jne redir_rw20 ; no, just return it
- les di,ss:current_dhndl ; compatibility modes should generate
- test es:DHNDL_MODE[di],DHM_SHAREMSK
- jz redir_rw20 ; critical errors fro ED_LOCKFAIL
- mov bx,ED_ACCESS ; sharing modes return access denied
- redir_rw20:
- ret
- eject
- ; DELETE FILE (UNLINK)
- ; +----+----+----+----+----+----+
- ; | 41 | name |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- redir_unlink:
- mov ax,I2F_DEL ; it's a delete
- ; mov file_attrib,6 ; only delete files
- redir_unlink_move_common:
- push ax
- call get_attrib_mode ; allow overrides for server calls
- pop ax
- jmp redir_pathop_common
- eject
- ; GET/SET FILE POSITION (LSEEK)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 42 | handle | offset | method |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; On Entry:
- ; ES:BX = DHDNL_
- ; method: 0 = begin, 1 = current, 2 = end of file
- ;
- ; On Exit:
- ; BX = Error Code, offset updated with new value
- ;
- redir_lseek:
- ;-----------
- mov di,bx ; ES:DI -> DHNDL_
- mov si,2[bp] ; SI -> parameter block
- mov dx,4[si] ; get 32-bit file offset
- mov cx,6[si] ; into CX,DX
- mov ax,8[si] ; get seek mode
- test ax,ax
- jz redir_lseek20 ; seek from beginning
- dec ax
- jz redir_lseek10 ; seek from current position
- dec ax
- jz redir_lseek30 ; seek from end
- mov bx,ED_DATA ; else invalid seek mode
- ret
- redir_lseek10: ; seek mode 1: relative to position
- add dx,es:DHNDL_POSLO[di] ; add position + offset
- adc cx,es:DHNDL_POSHI[di]
- ; jmps redir_lseek20
- redir_lseek20: ; seek mode 0: set absolute position
- mov es:DHNDL_POSLO[di],dx ; set new file offset
- mov es:DHNDL_POSHI[di],cx ; SI = error code/0 at this point
- ; jmps redir_lseek90
- redir_lseek90:
- mov 4[si],dx ; set 32-bit file offset
- mov 6[si],cx ; for return
- xchg ax,bx ; error code in BX
- ret
- redir_lseek30: ; seek mode 2: relative to end
- mov bx,es:DHNDL_MODE[di] ; ask MSNET if anyone else can write
- and bl,DHM_SHAREMSK ; isolate sharing bits
- cmp bl,DHM_DENY_READ ; Only DENY_READ and DENY_NONE a
- jb redir_lseek40 ; problem - others might write to
- push si ; the file so we must ask the server
- ; how long the file is now
- mov ax,I2F_LSEEK ; CX:DX = position now
- call int2f_dhndl ; do a remote seek
- pop si ; DX:AX = EOF relative position
- jc redir_lseek90 ; (unless we have an error)
- xchg ax,dx ; AX:DX = new EOF relative position
- xchg ax,cx ; and finally get into CX:DX
- xor ax,ax ; no problems...
- ;jmps redir_lseek90 ; MYST-removed,file offset wasn't updated
- jmps redir_lseek20 ; MYST-added,go and update the new file offset.
- redir_lseek40:
- add dx,es:DHNDL_SIZELO[di] ; add file size + offset
- adc cx,es:DHNDL_SIZEHI[di]
- jmps redir_lseek20
- eject
- ; GET/SET FILE ATTRIBUTES (CHMOD)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 43 | name | flag | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | size |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; name: pointer to ASCIIZ file name
- ; flag: 0 = get attribute,
- ; 1 = set attribute,
- ; 2-5 = passwords (ignored)
- ; attrib: new attribute if flag = 1
- ; password mode if flag = 3
- ;
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- ; attrib: file's attribute if flag = 0
- ; size: file's size
- redir_chmod:
- ;-----------
- ;
- mov bx,2[bp] ; BX -> parameter block
- mov cx,8[bx] ; get attribs
- mov bx,6[bx] ; get access flag
- mov ax,I2F_SET_ATTR ; assume it's a set
- cmp bl,1 ; is it a set ?
- je redir_chmod10 ; if not then
- mov ax,I2F_GET_ATTR ; assume it's a get
- mov cx,16h ; with everything attribs
- jb redir_chmod10 ; was it ?
- mov ax,ED_ACCESS ; no, return access denied
- jmps redir_chmod20 ; cause it DR password stuff
- redir_chmod10:
- mov int2f_stack,cx ; attribs on the stack
- call int2f_ldt ; do the Int 2F
- jc redir_chmod20
- mov si,2[bp] ; SI -> parameter block
- mov 8[si],ax ; return attribute
- mov 10[si],di
- mov 12[si],bx
- xor ax,ax ; success
- redir_chmod20:
- xchg ax,bx ; return result in BX
- ret
- eject
- ; GET DISK PARAMETER BLOCK
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 48 | drive | dpb | adjust |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; drive: drive to get information about
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- ; dpb: address of DOS DPB (offset/segment)
- ; adjust: delwatch adjustment of free space
- ; NB. We only fill in the fields required by the Disk Free Space call.
- redir_getdpb:
- ;------------
- mov ax,I2F_SPACE
- call int2f_ldt ; get the info
- jnc redir_getdpb10 ; if we get an error then make CLMSK=FE
- mov al,0ffh
- redir_getdpb10:
- mov si,offset sec_pathname ; let's re-use this as a temp DPB
- dec al ; make cluster mask
- mov ds:DDSC_CLMSK[si],al ; and stuff into DPB
- mov ds:DDSC_FREE[si],dx
- mov ds:DDSC_SECSIZE[si],cx
- inc bx ; inc number of clusters
- mov ds:DDSC_NCLSTRS[si],bx
- mov al,err_drv ; also fill in drive number
- mov ds:DDSC_UNIT[si],al
- mov si,2[bp] ; DI -> parameter block
- mov 4[si],offset sec_pathname
- mov 6[si],ds ; point to my dummy DPB
- mov word ptr 8[si],0 ; zero adjust value
- mov bx,0ffh ; return 0xFF (ie. bad drive)
- ret
- eject
- ; FIND FIRST FILE
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 4E | name | ***** | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: pointer to ASCIIZ file name
- ; attrib: attribute to be used in search
- ;
- ; exit:
- ; -----
- ; BX: 0001 or error code ( < 0)
- ; Note: This call returns matching files in
- ; the current DMA address and also saves
- ; the BDOS state in the there.
- ;
- ; If there is space for multiple file names we
- ; could return as many as will fit into the DTA
- ; but it's easier just to return 1 file
- ;
- redir_first: ; 13-find first matching file
- ;----------
- ; ONLY 1 file returned for now.....
- ;
- call get_attrib_mode ; AX = mode, CX = attrib
- mov ax,I2F_SFIRST ; srch first, valid LDT
- les di,current_ldt
- cmp di,-1 ; valid LDT ?
- jne redir_first10
- mov ax,I2F_XSFIRST ; srch first, no valid LDT
- redir_first10:
- jmps srch_buf_common
- eject
- ; FIND NEXT FILE
- ; +----+----+
- ; | 4F |
- ; +----+----+
- ;
- ; entry:
- ; ------
- ;
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- ; Note: This call returns matching files in
- ; the current DMA address and also saves
- ; the BDOS state in the there.
- redir_next: ; 14-find next matching file
- ;---------
- ; ONLY 1 file returned for now.....
- ;
- push ss ! pop es
- mov di,offset srch_buf ; point ES:DI -> search buffer
- mov ax,I2F_SNEXT
- srch_buf_common:
- push dma_offset
- push dma_segment
- mov dma_offset,offset srch_buf
- mov dma_segment,ds
- call int2f_op
- pop dma_segment
- pop dma_offset
- jc srch_buf_common10
- call redir_save_srch_state ; if no error save state
- xor ax,ax ; return AX = 1 file found
- srch_buf_common10:
- xchg ax,bx ; return code in BX
- ret
- redir_save_srch_state:
- ; On entry DS=PCMODE
- les di,dword ptr dma_offset ; ES:DI -> search state in DMA address
- mov si,offset srch_buf
- mov cx,21 ; save 1st 21 bytes
- rep movsb
- push si ; save name/ext
- add si,11 ; skip to name/ext
- movsb ; copy the attribute
- add si,10 ; skip reserved bytes
- movsw ; copy the time
- movsw ; copy the date
- add si,2 ; skip starting cluster
- movsw ; copy the file size
- movsw
- pop bx ; recover name
- jmp unparse ; unparse the name
- ; Restore DOS search area from user DTA
- ;
- redir_restore_srch_state:
- ;------------------------
- ; On Entry:
- ; DS = SYSDAT
- ; On Exit:
- ; AL = 1st byte of srch buf
- ; DS preserved
- ;
- push ss
- pop es
- mov di,offset srch_buf ; ES:DI -> internal state
- push ds
- lds si,ss:dword ptr dma_offset
- lodsb ; DS:SI -> search state in DMA address
- stosb
- mov cx,20 ; copy 1st 21 bytes
- rep movsb
- pop ds
- ret
- eject
- ; COMMIT FILE (COMMIT)
- ; +----+----+----+----+
- ; | 50 | handle |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle to be flushed
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- redir_commit:
- test es:DHNDL_MODE[bx],DHM_WO+DHM_RW
- jz redir_commit10 ; we don't need to commit it
- mov ax,I2F_COMMIT
- call int2f_dhndl ; commit this file
- jc redir_commit20
- redir_commit10:
- xor ax,ax ; success
- redir_commit20:
- xchg ax,bx ; return result in BX
- ret
- eject
- ; CREATE NEW FILE
- ; +----+----+----+----+----+----+----+----+
- ; | 51 | name | mode |
- ; +----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; mode: attribute for file
- ; exit:
- ; -----
- ; BX: file handle or error code ( < 0)
- ; Note: The function is identical to CREATE FILE
- ; with the exception that an error is returned
- ; if the specified file already exists.
- redir_mknew:
- call get_attrib_mode ; AX = mode, CX = attrib
- xchg ax,cx
- or ax,120h ; set ARCHIVE + MKNEW bits
- mov file_attrib,ax
- mov int2f_stack,ax
- mov int2f_cmd,I2F_CREATE
- mov file_mode,DHM_RW ; Open Compatibility mode, Read/Write
- jmp redir_open_create_common
- eject
- ; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK)
- ; +----+----+----+----+----+----+----+----+
- ; | 52 | handle | offset |
- ; +----+----+----+----+----+----+----+----+
- ; | length | lock |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; offset: long integer offset
- ; length: long integer byte count
- ; lock: 0 = lock, 1 = unlock
- ; exit:
- ; -----
- ; BX: byte count or error code ( < 0)
- redir_lock:
- ; Lock uses I2F_LOCK, with CX,DX,SI as per INT 21, DI on stack
- ; Unlock uses I2F_UNLOCK with same.
- mov bx,2[bp] ; BX -> parameter block
- if DOS5
- push bp
- lea bp,4[bx] ; BP -> parameter block
- mov dx,bp ; as does DX
- mov ax,I2F_LOCK
- mov bl,ds:byte ptr 12[bx]
- mov bh,5Ch ; lock/unlock in BX
- call int2f_dhndl ; try the operation
- pop bp
- else
- mov dx,ds:4[bx] ; get low word of offset in DX
- mov cx,ds:6[bx] ; and the hi word in CX
- mov di,ds:8[bx] ; get low word of length in DI
- mov si,ds:10[bx] ; and high in SI
- mov int2f_stack,di ; length low is on stack
- mov ax,I2F_LOCK ; assume lock
- cmp ds:word ptr 12[bx],0
- je redir_lock10
- mov ax,I2F_UNLOCK ; no, it must be unlock
- redir_lock10:
- call int2f_dhndl ; try the operation
- endif
- jc redir_lock20
- xor ax,ax ; success
- redir_lock20:
- xchg ax,bx ; return result in BX
- ret
- eject
- ; EXPAND FILE
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 55 | old name | new name |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; old name: segmented address of ASCIIZ name
- ; new name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- ; If we got here pri_pathname already contains expanded name - just copy it
- ; back to the users buffer.
- redir_expand:
- ;------------
- mov si,2[bp] ; SI -> parameter block
- les di,10[si] ; ES:DI -> user supplied name
- mov si,offset pri_pathname
- call copy_asciiz
- xor bx,bx ; no errors
- ret
- eject
- ; RENAME FILE
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 56 | old name | new name |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; old name: segmented address of ASCIIZ name
- ; new name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- ; Note: R/O files can be renamed.
- ; ---
- redir_move:
- mov ax,I2F_REN ; it's a rename
- jmp redir_unlink_move_common
- eject
- ; GET/SET FILE DATE/TIME
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 57 | handle | mode | date | time |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; mode: 0 = get date/time, 1 = set date/time
- ; date: date as in directory FCB
- ; time: time as in directory FCB
- ; exit:
- ; -----
- ; BX: 0000 or error code ( < 0)
- ; date: date of last modification if mode = 0
- ; time: date of last modification if mode = 0
- redir_dattim:
- ;------------
- mov si,2[bp] ; DS:SI -> param block
- cmp ds:word ptr 4[si],1 ; is it set ?
- ja redir_dattim30 ; if illegal say so
- je redir_dattim10
- mov ax,es:DHNDL_DATE[bx] ; we need to copy the file date
- mov word ptr 6[si],ax ; into the parameter block
- mov ax,es:DHNDL_TIME[bx]
- mov word ptr 8[si],ax ; and the time
- jmps redir_dattim20
- redir_dattim10:
- mov ax,word ptr 6[si] ; copy the date we are given
- mov es:DHNDL_DATE[bx],ax ; into the DOSHNDL
- mov ax,word ptr 8[si] ; and the time
- mov es:DHNDL_TIME[bx],ax
- or es:DHNDL_WATTR[bx],DHAT_TIMEOK
- and es:DHNDL_WATTR[bx],not DHAT_CLEAN
- redir_dattim20:
- xor bx,bx ; all went OK
- jmps redir_dattim40
- redir_dattim30:
- mov bx,ED_FUNCTION ; bad function number
- redir_dattim40:
- ret
- Public redir_build_path
- ; AH contains state of path processing, and is normally zero
- BP_DOT equ 1 ; we have had a DOT end are processing the .EXT
- BP_WILD equ 2 ; we have encountered a wild card
- BP_BSLASH equ 4 ; the last character was a BSLASH
- ; May be called with or without MXDisk
- redir_build_path:
- ;----------------
- ; On Entry:
- ; DS:SI -> source name
- ; ES:DI -> destination name (in PCMODE data segment)
- ; current_ldt -> LDT_ for specified drive
- ; On Exit:
- ; CY clear if we could build the path
- ;
- ; firstly we discard any drive portion
- lodsw ; get 1st two characters
- cmp ah,':' ; is a drive specified ?
- jne redir_bp10 ; discard "d:" if so
- lodsw
- redir_bp10:
- ; Is it a "\serversharenamesubdirfilename.ext" format ?
- call check_dslash ; if it is \
- je redir_bp20 ; then just copy the lot
- ; it's a normal "A:subdirfilename.ext" pathname format
- dec si ; we have swallowed the 1st two
- dec si ; chars - now we change our mind
- push ds ! push si
- lds si,es:current_ldt
- mov cx,ds:LDT_ROOTLEN[si] ; copy the root portion of the name
- rep movsb ; copy the server stub name
- mov dx,di ; ES:DX -> root position
- call check_slash ; do we start from the root ?
- je redir_bp11 ; yes, then that's all
- call copy_asciiz ; no, copy the rest of the path
- call redir_bp_append_slash ; append '' for our path processing
- redir_bp11:
- pop si ! pop ds
- jmps redir_bp_next_level ; continue processing given path
- redir_bp20:
- ; It is a "\serversharenamesubdirfilename.ext" format
- stosw ; copy the "\"
- xor ax,ax ; clear "flags" in AH
- redir_bp21:
- lodsb ; work along the name
- test al,al ; unexpected end of name ?
- jz redir_bp_exit20 ; go with what we've got....
- call check_slash ; have we found the root '' ?
- je redir_bp23
- if KANJI
- call dbcs_lead ; is it the 1st of a kanji pair
- jne redir_bp22 ; no, onto next char
- stosb ; copy the 1st character
- movsb ; copy 2nd byte of KANJI pair
- jmps redir_bp21 ; now we can move onto next char
- redir_bp22:
- endif
- call toupper ; upper case the character
- stosb ; copy the character
- jmps redir_bp21 ; go and do another one
- redir_bp23:
- mov dx,di ; bodge root to the top
- ; mov al,''
- stosb ; put in a ''
- jmps redir_bp_next_level ; yes, this is the new "root"
- ; We have reached the terminating NUL
- redir_bp_exit:
- test ah,BP_WILD ; did we get any wildcards ?
- je redir_bp_exit10
- mov si,2[bp] ; SS:SI -> parameter block
- mov al,ss:[si] ; fdos code number
- cmp al,MS_X_FIRST ; search first ?
- je redir_bp_exit10
- cmp al,FD_EXPAND ; expand pathname
- je redir_bp_exit10
- cmp ss:remote_call,0 ; should we wildcard REN/DEL ?
- je redir_bp_ED_PATH ; reject as not allowed here
- cmp al,MS_X_RENAME ; rename ?
- je redir_bp_exit10
- cmp al,MS_X_UNLINK ; delete ?
- jne redir_bp_ED_PATH ; reject as not allowed here
- redir_bp_exit10:
- xor al,al ; make sure our string is zero
- stosb ; terminated
- call redir_bp_append_slash ; append a trailing '' if we don't
- dec di ; have one so we can remove it
- cmp di,dx ; are we talking about the root ?
- jne redir_bp_exit20
- cmp es:byte ptr 0FFFFh[di],':'
- jne redir_bp_exit20 ; if we have a trailing ':' allow
- inc di ; a '' at the root
- redir_bp_exit20:
- xor al,al ; KANJI aware way of removing trailing
- stosb ; '' from the path....
- ; clc
- ret
- redir_bp_next_level:
- ; DS:SI -> source pathname, ES:DI -> destination pathname, ES:DX -> root
- ; AH = current status
- mov cx,8 ; expansion count ready
- xor ax,ax
- redir_bp_next_char:
- lodsb
- test al,al ; end of the line ?
- jz redir_bp_exit ; do the exit
- ; Is it a '' ?
- redir_bp40:
- call check_slash ; was it a seperator ?
- jne redir_bp50
- test ah,BP_WILD ; have we encountered wildcards ?
- jnz redir_bp_ED_PATH ; reject as not allowed here
- mov al,'' ; make sure it's a BSLASH
- stosb
- jmps redir_bp_next_level ; start at a new level
- ; Is it a '.' ?
- redir_bp50:
- cmp al,'.' ; seperator ?
- jne redir_bp60
- lodsb ; get next letter
- test al,al ; is it trailing '.' ?
- je redir_bp_exit ; then exit now
- cmp cx,8 ; check for '.' and '..'
- je redir_bp52 ; if at start of field
- redir_bp51: ; othewise it's a ".EXT"
- mov bx,ED_FILE ; assume we have a problem
- test ah,BP_DOT ; have we had an extention before ?
- jnz redir_bp_err ; we've got a problem
- dec si ; rewind a character
- mov ax,'.'+256*BP_DOT ; so we are back to the '.'
- stosb ; store the '.' in destination
- mov cx,3 ; expand the extention
- jmps redir_bp_next_char
- redir_bp52: ; It might be a "." or ".."
- call check_slash ; is it '.'
- je redir_bp_next_char ; discard them both
- cmp al,'.' ; is it '..' ?
- jne redir_bp51 ; no, must be an extention after all
- call redir_bp_ddot ; rewind a level
- jnc redir_bp_next_level ; onto next level
- redir_bp_ED_PATH:
- ; set CY flag to indicate error then return
- mov bx,ED_PATH ; return "invalid path" error
- redir_bp_err:
- stc
- ret
- ; Is it a '*' ?
- redir_bp60:
- call check_delim ; is it a delimiter ?
- jz redir_bp_ED_PATH ; thats illegal at this point
- cmp al,'*' ; wildcards ?
- jne redir_bp70
- mov al,'?'
- rep stosb ; expand it
- ; or ah,BP_WILD ; remember wild-card encountered
- ; jmps redir_bp_next_char ; check for wildcards
- ;
- ; ; we can just fall through
- ;
- redir_bp70:
- cmp al,'?' ; wild card is possibly OK
- jne redir_bp80
- or ah,BP_WILD ; remember wild-card encountered
- redir_bp80:
- ; Normal Character
- ; AL contains a normal character for us to process.
- ; Uppercase the character, look out for KANJI etc
- jcxz redir_bp_next_char ; discard if no space is left
- dec cx ; one less to expand
- if KANJI
- call dbcs_lead ; is it the 1st of a kanji pair
- jne redir_bp90
- inc si ; skip 2nd byte
- jcxz redir_bp_next_char ; discard if no room for kanji char
- dec cx ; one less to expand
- stosb ; store 1st byte of kanji character
- dec si ; point at 2nd byte again
- movsb ; copy 2nd byte of kanji character
- jmps redir_bp_next_char
- redir_bp90:
- endif
- call toupper ; make it upper case
- stosb ; plant the character
- jmps redir_bp_next_char
- redir_bp_ddot:
- ; We have encountered a '..' in a pathname, so rewind up a level
- ; On Entry:
- ; DS:SI -> source position, ES:DI -> destination position
- ; ES:DX -> root position, AL = Character
- ; On Exit:
- ; ES:DI -> start of field one level up, unless we get an error when CY set.
- lodsb ; look at char after '..'
- call check_slash ; is it '..'
- je redir_bp_ddot10
- test al,al ; is it a trailing '..'
- jnz redir_bp_ED_PATH ; no, anything else is bad...
- dec si ; trailing '..', rewind to NUL
- redir_bp_ddot10:
- dec di ; move back to last ''
- cmp di,dx ; are we at the root anyway ?
- jle redir_bp_ED_PATH ; then don't discard any
- ; We now start at ES:DX and work along till ES:DI -> char after last ''
- push ds ! push si
- push es ! pop ds
- mov si,dx ; DS:SI -> char after root
- mov cx,dx ; last '' position in CX
- redir_bp_ddot20:
- lodsb
- cmp si,di ; end of the line yet ?
- jae redir_bp_ddot30 ; yes, stop now
- if KANJI
- call dbcs_lead ; is it 1st of a kanji pair ?
- jne redir_bp_ddot25
- lodsb ; skip the 2nd too
- jmps redir_bp_ddot20 ; then go on to next char
- redir_bp_ddot25:
- endif
- call check_slash ; is it a ''
- jne redir_bp_ddot20 ; no, do next
- mov cx,si ; save position after the ''
- jmps redir_bp_ddot20
- redir_bp_ddot30:
- mov di,cx ; last '' was here..
- pop si ! pop ds
- clc ; no errors
- ret
- redir_bp_append_slash:
- ; On Entry:
- ; ES:DX -> ASCIIZ string to append a '' to
- ; On Exit:
- ; ES:DI -> terminating NUL
- ; All but AX preserved
- ;
- xor ax,ax ; AH = 0, initially no previous char
- mov di,dx ; start processing from here
- redir_bp_append_slash10:
- mov ah,al ; save previous char in AH
- mov al,es:[di] ; get a character
- inc di ; point to next
- test al,al ; is it NUL ?
- if KANJI
- je redir_bp_append_slash20
- call dbcs_lead ; is it 1st of a kanji pair ?
- jne redir_bp_append_slash10
- inc di ; skip the 2nd too
- jmps redir_bp_append_slash10 ; (it might be '')
- redir_bp_append_slash20:
- else
- jnz redir_bp_append_slash10
- endif
- mov al,ah ; get previous char
- call check_slash ; did we have a '' ?
- je redir_bp_append_slash30
- dec di ; ES:DI -> existing NUL
- mov ax,''
- stosw ; new terminating ''
- redir_bp_append_slash30:
- dec di ; ES:DI -> NUL
- ret
- get_attrib_mode:
- ;---------------
- ; On Entry:
- ; SS:2[BP] -> param block
- ; On Exit:
- ; AX = file mode
- ; CX = file attributes
- ;
- mov si,2[bp] ; SI -> parameter block
- mov ax,ds:6[si] ; get mode
- mov cx,ds:8[si] ; get attribs
- mov file_mode,ax ; save open mode
- mov file_attrib,cx ; save file attribute
- ret
- int2f_ldt:
- ;---------
- ; On Entry:
- ; AX = Int2F command
- ; On Exit:
- ; CY clear, AX returned unchanged
- ; CY set, AX = Our Negative Error Code
- ;
- les di,ss:current_ldt
- jmps int2f_op
- int2f_dhndl:
- ;----------
- ; On Entry:
- ; AX = Int2F command
- ; On Exit:
- ; CY clear, AX returned unchanged
- ; CY set, AX = Our Negative Error Code
- ;
- les di,ss:current_dhndl
- int2f_op:
- push ds
- push ss ! pop ds
- push int2f_stack ; put word on stack
- int 2fh ; get the info
- pop int2f_stack ; clean up the stack
- pop ds
- jnc int2f_op10
- neg ax ; AX = we keep error codes negative
- ; stc ; we have a problem
- int2f_op10:
- ret
- end