mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-22 16:04:20 +00:00
1154 lines
30 KiB
Plaintext
1154 lines
30 KiB
Plaintext
; File : $DISK.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$
|
|
; DISK.A86 1.26 94/12/01 10:05:21
|
|
; added attribute support for open/move/unlink during server call
|
|
; DISK.A86 1.24 93/11/16 13:46:21
|
|
; Generate critical error on int21/36 (get free space)
|
|
; DISK.A86 1.23 93/10/25 21:58:02
|
|
; Tighten up error checks on int21/6C modes (DL bits 0-3 = 3 rejected)
|
|
; DISK.A86 1.22 93/10/18 17:40:51
|
|
; fix for >255 open files (PNW Server)
|
|
; DISK.A86 1.21 93/09/03 20:28:02
|
|
; Add "no critical errors" support (int 21/6C)
|
|
; DISK.A86 1.20 93/08/04 15:15:15
|
|
; Int21/6C allows DH=1
|
|
; DISK.A86 1.19 93/07/22 20:32:12
|
|
; don't check AL on int 21/6c
|
|
; DISK.A86 1.18 93/07/22 19:28:02
|
|
; correct bug in extended open/create
|
|
; DISK.A86 1.15 93/06/23 04:05:38
|
|
; more int21/6C - we still need no critical errors support
|
|
; DISK.A86 1.14 93/06/23 03:00:27
|
|
; fix bug in int21/6C
|
|
; DISK.A86 1.13 93/05/07 15:09:29
|
|
; Move delwatch free space adjust call inside the MXDisk
|
|
; DISK.A86 1.12 93/03/16 22:33:49
|
|
; UNDELETE support changes
|
|
; DISK.A86 1.11 93/03/05 18:10:55
|
|
; Add UNDELETE definition
|
|
; ENDLOG
|
|
;
|
|
; All FCB based PCMODE functions are translated to FDOS function
|
|
; calls in this file.
|
|
;
|
|
; 22 May 87 Support the extended CHMOD function to get/set the
|
|
; password mode.
|
|
; 28 May 87 Support the Update Handle Count Function
|
|
; 5 Nov 87 Remove MAJOR_VER reference from func0D
|
|
; 15 Mar 88 Return Attributes in CX and AX
|
|
; 3 May 88 Return correct disk size from functions 1B, 1C and 36
|
|
; 17 May 88 Add valid drive check routine used by FUNC29 and FUNC4B
|
|
; 30 Jun 88 Call FDOS to build DDSC for INT21/53
|
|
; 18 Aug 88 FUNC67 correctly fill new handle table with 0FFh
|
|
; Sorcim ACCPAC Plus
|
|
; 27 Sep 88 Return error codes from Read and Write Random.
|
|
; 19 Feb 89 Allowing SHARE to be disabled with DR DOS
|
|
; 16 May 89 Include Random Record field on func23 (file size)
|
|
; 23 May 89 func3F (Read) now allows Ignore on errors (CopyIIpc)
|
|
; 11 Sep 89 MSNET Flush hook added
|
|
; 20 Sep 89 func3B "d:=" form fills in LDT (func4B support)
|
|
; 24 Oct 89 func32 (getdpb) sets top bit of drive on fdos_getdpb
|
|
; to indicate free space count not required
|
|
; 27 Oct 89 mutilate the code to save space
|
|
; 24 Jan 90 valid_drive uses dos_entry, doesn't peek at HDS's
|
|
; 8 Feb 90 func_43 updated for new password support
|
|
; 27 Feb 90 func57 gives ED_FUNCTION if not get/set (HEADROOM bug)
|
|
; 7 Mar 90 Convert to register preserved function calls
|
|
; 14 Mar 90 Share func3D_mask bodge move to FDOS
|
|
; 28 Sep 90 Return sectors xfered on Int21/27 even if error (CALC.EXE>64k)
|
|
; 14 mar 91 add delwatch hook to func36 (disk free space)
|
|
; 14 jun 91 correct error codes from func3F during func4B
|
|
; 8 aug 91 func3B (chdir) now maintains LDT name for all cases
|
|
; 1 oct 91 Valdivar it
|
|
; 27 feb 92 func3E returns previous open count
|
|
; 3 mar 92 fill in default search attribute in Func3D for future
|
|
; 23 mar 92 func67 will now shrink #handles
|
|
;
|
|
|
|
include pcmode.equ
|
|
include fdos.def
|
|
include i:doshndl.def
|
|
include i:fdos.equ
|
|
include i:psp.def
|
|
include i:msdos.equ
|
|
include i:mserror.equ
|
|
include i:redir.equ
|
|
|
|
FCB_LEN equ 32
|
|
XFCB_LEN equ FCB_LEN+7
|
|
|
|
|
|
PCM_CODE CSEG BYTE
|
|
extrn dbcs_lead:near
|
|
extrn dos_entry:near
|
|
extrn fdos_nocrit:near
|
|
extrn fdos_crit:near, fdos_ax_crit:near
|
|
extrn fcbfdos_crit:near
|
|
extrn set_retry:near
|
|
extrn set_retry_RF:near
|
|
extrn error_exit:near
|
|
extrn error_ret:near
|
|
extrn fcberror_exit:near
|
|
|
|
extrn reload_registers:near
|
|
extrn reload_ES:near
|
|
extrn return_AX_CLC:near
|
|
extrn return_BX:near
|
|
extrn return_CX:near
|
|
extrn return_DX:near
|
|
|
|
; *****************************
|
|
; *** DOS Function 0D ***
|
|
; *** Disk Reset ***
|
|
; *****************************
|
|
;
|
|
Public func0D
|
|
func0D:
|
|
mov FD_FUNC,FD_FLUSH
|
|
call fdos_nocrit ; flush buffers
|
|
mov ax,0FFFFh
|
|
push ax
|
|
mov ax,I2F_FLUSH
|
|
int 2fh ; magic INT2F flush remote buffers
|
|
pop ax
|
|
push ss ! pop ds
|
|
ret
|
|
|
|
; *****************************
|
|
; *** DOS Function 0E ***
|
|
; *** Select Disk ***
|
|
; *****************************
|
|
;
|
|
Public func0E
|
|
func0E:
|
|
;
|
|
; Entry:
|
|
; DL == drive to set as default (0 == A:)
|
|
; Exit:
|
|
; AL == Number of Drives in System (from SYSDAT)
|
|
;
|
|
mov FD_FUNC,FD_SELECT
|
|
xchg ax,dx ; drive in AL
|
|
cbw ; make that AX
|
|
mov FD_DRIVE,ax
|
|
call fdos_nocrit ; ask the FDOS to try to select it
|
|
mov al,last_drv ; Return the number of valid drives
|
|
ret
|
|
|
|
;
|
|
; Return with the ZERO flag set if the drive passed in AL is
|
|
; valid. This function is used to set the initial AX value
|
|
; when a program is loaded.
|
|
;
|
|
; On Entry:- AL 00 - Default Drive
|
|
; 01 to 26 - A: to Z:
|
|
;
|
|
; On Exit:- ZF If AL referenced a valid drive
|
|
;
|
|
Public valid_drive
|
|
valid_drive:
|
|
push dx
|
|
mov dl,al ; get drive in DL
|
|
dec dl ; make drive zero based
|
|
js valid_drive10 ; if current drive always OK
|
|
mov ah,MS_DRV_GET
|
|
call dos_entry ; get current drive
|
|
push ax ; save for later
|
|
mov ah,MS_DRV_SET
|
|
call dos_entry ; try and select new drive
|
|
mov ah,MS_DRV_GET ; if we can select it
|
|
call dos_entry ; then it's valid
|
|
sub al,dl ; AL = 0 if drive valid
|
|
pop dx ; recover old drive
|
|
push ax ; save result
|
|
mov ah,MS_DRV_SET
|
|
call dos_entry ; reset to original drive
|
|
pop ax ; recover result
|
|
valid_drive10:
|
|
pop dx
|
|
test al,al ; set ZF if valid drive
|
|
ret
|
|
|
|
eject
|
|
; *****************************
|
|
; *** DOS Function 0F ***
|
|
; *** Open File (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func0F
|
|
func0F:
|
|
|
|
; *****************************
|
|
; *** DOS Function 10 ***
|
|
; *** Close File (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func10
|
|
func10:
|
|
|
|
; *****************************
|
|
; *** DOS Function 11 ***
|
|
; *** Search First (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func11
|
|
func11:
|
|
|
|
; *****************************
|
|
; *** DOS Function 12 ***
|
|
; *** Search Next (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func12
|
|
func12:
|
|
|
|
; *****************************
|
|
; *** DOS Function 13 ***
|
|
; *** Delete File (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func13
|
|
func13:
|
|
|
|
; *****************************
|
|
; *** DOS Function 14 ***
|
|
; *** Sequential Read (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func14
|
|
func14:
|
|
|
|
; *****************************
|
|
; *** DOS Function 15 ***
|
|
; *** Sequential Write (FCB)***
|
|
; *****************************
|
|
;
|
|
Public func15
|
|
func15:
|
|
|
|
; *****************************
|
|
; *** DOS Function 16 ***
|
|
; *** Create File (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func16
|
|
func16:
|
|
|
|
; *****************************
|
|
; *** DOS Function 17 ***
|
|
; *** Rename File (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func17
|
|
func17:
|
|
|
|
; *****************************
|
|
; *** DOS Function 21 ***
|
|
; *** Random Read (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func21
|
|
func21:
|
|
|
|
; *****************************
|
|
; *** DOS Function 22 ***
|
|
; *** Random Write (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func22
|
|
func22:
|
|
|
|
; *****************************
|
|
; *** DOS Function 23 ***
|
|
; *** File Size (FCB) ***
|
|
; *****************************
|
|
;
|
|
Public func23
|
|
func23:
|
|
|
|
; *****************************
|
|
; *** DOS Function 24 ***
|
|
; *** Set Relative Record ***
|
|
; *****************************
|
|
;
|
|
Public func24
|
|
func24:
|
|
|
|
; *****************************
|
|
; *** DOS Function 27 ***
|
|
; *** Random Block Read ***
|
|
; *****************************
|
|
;
|
|
Public func27
|
|
func27:
|
|
|
|
; *****************************
|
|
; *** DOS Function 28 ***
|
|
; *** Random Block Write ***
|
|
; *****************************
|
|
;
|
|
Public func28
|
|
func28:
|
|
; All FCB function come through here
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov ax,FD_FCB ; FCB file function
|
|
xchg ax,FD_FUNC ; recover function number
|
|
mov FD_FCBFUNC,ax ; pass FCB function number
|
|
mov FD_FCBOFF,dx ; Initialise the FCB Pointer
|
|
mov FD_FCBSEG,es
|
|
mov FD_FCBCNT,cx ; we may need record count
|
|
call fcbfdos_crit ; Execute the function
|
|
jc fcb_error ; Check for an Error
|
|
mov cx,FD_FCBCNT ; Get the number of records
|
|
jmp return_CX ; processed and return in CX
|
|
fcb_error:
|
|
jmp fcberror_exit ; Use default Error handler
|
|
|
|
|
|
|
|
eject
|
|
; *****************************
|
|
; *** DOS Function 19 ***
|
|
; *** Current Disk ***
|
|
; *****************************
|
|
|
|
Public func19
|
|
func19:
|
|
mov al,current_dsk ; Get the current logical disk
|
|
ret ; and return
|
|
|
|
|
|
; *****************************
|
|
; *** DOS Function 1A ***
|
|
; *** Set Disk Trans Adr ***
|
|
; *****************************
|
|
|
|
Public func1A
|
|
func1A:
|
|
mov dma_offset,dx ; set the PCMODE DMA Offset
|
|
mov dma_segment,es ; and then the DMA Segment
|
|
ret
|
|
|
|
; *****************************
|
|
; *** DOS Function 1B ***
|
|
; *** Def. Disk Info ***
|
|
; *****************************
|
|
;
|
|
Public func1B
|
|
func1B:
|
|
|
|
; *****************************
|
|
; *** DOS Function 1C ***
|
|
; *** Sel. Disk Info ***
|
|
; *****************************
|
|
;
|
|
Public func1C
|
|
func1C:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
xor dh,dh ; Pass the drive requested
|
|
call fdos_DISKINFO ; find out about drive
|
|
jc fdos_DI_error
|
|
|
|
mov cx,es:DDSC_SECSIZE[bx] ; Get the Physical Sector Size
|
|
call return_CX ; in bytes
|
|
|
|
mov dx,es:DDSC_NCLSTRS[bx] ; Convert the last cluster no
|
|
dec dx ; returned in DDSC to maximum
|
|
call return_DX ; number of clusters and return
|
|
|
|
mov al,es:DDSC_CLMSK[bx] ; get (sectors per cluster)-1
|
|
inc ax ; return sectors per cluster
|
|
lea bx,DDSC_MEDIA[bx] ; return address of media byte
|
|
f1B1C1F32_common:
|
|
push ds
|
|
lds di,int21regs_ptr
|
|
mov reg_DS[di],es
|
|
mov reg_BX[di],bx
|
|
pop ds
|
|
ret
|
|
|
|
; *****************************
|
|
; *** DOS Function 1F ***
|
|
; *** Get Default DPB ***
|
|
; *****************************
|
|
;
|
|
Public func1F
|
|
func1F:
|
|
|
|
; *****************************
|
|
; *** DOS Function 32 ***
|
|
; *** Get Requested DPB ***
|
|
; *****************************
|
|
;
|
|
Public func32
|
|
func32:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov dh,80h ; set top bit - free space not needed
|
|
call fdos_DISKINFO ; and make the function call
|
|
jnc f1B1C1F32_common ; exit using common code
|
|
fdos_DI_error:
|
|
jmp fcberror_exit ; exit thru FCB error
|
|
|
|
|
|
; *****************************
|
|
; *** DOS Function 36 ***
|
|
; *** Disk Free Space ***
|
|
; *****************************
|
|
;
|
|
Public func36
|
|
func36:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
xor dh,dh ; clear out DH
|
|
call fdos_DISKINFO ; find out about drive
|
|
jnc f36_OK ; CY set if we had a problem
|
|
push es
|
|
push bx
|
|
call error_exit ; generate a critical error
|
|
pop bx
|
|
pop es
|
|
mov ax,0FFFFh ; Invalid Drive Return 0FFFFh
|
|
jc f36_exit ; No Carry
|
|
f36_OK:
|
|
mov cx,es:DDSC_SECSIZE[bx] ; Get the Physical Sector Size
|
|
call return_CX ; in bytes
|
|
|
|
mov dx,es:DDSC_NCLSTRS[bx] ; Convert the last cluster no
|
|
dec dx ; returned in DDSC to maximum
|
|
call return_DX ; number of clusters
|
|
|
|
mov cx,es:DDSC_FREE[bx] ; get number of free clusters
|
|
if DELWATCH
|
|
add cx,FD_ADJUST ; now add in DELWATCH adjustment
|
|
endif
|
|
xor ax,ax
|
|
mov al,es:DDSC_CLMSK[bx] ; get the sectors per cluster -1
|
|
inc ax ; AX = sectors per cluster
|
|
|
|
mov bx,cx
|
|
call return_BX ; return free clusters
|
|
|
|
f36_exit:
|
|
jmp return_AX_CLC
|
|
|
|
fdos_DISKINFO:
|
|
;-------------
|
|
; Called by func1B, func1C, func1F, func32, func36
|
|
; Even number functions have drive in DL
|
|
; Odd numbered function use default drive (0)
|
|
;
|
|
mov ax,FD_DISKINFO ; get information about drive
|
|
xchg ax,FD_FUNC ; while getting orginal function #
|
|
test al,1 ; is it func1B/func1F ?
|
|
jz fdos_DI10 ; if so these use the default
|
|
xor dl,dl ; drive so zero DL
|
|
fdos_DI10:
|
|
mov FD_DRIVE,dx ; drive in DX
|
|
call fdos_crit
|
|
les bx,FD_DPB ; get the DPB pointer
|
|
ret
|
|
|
|
eject
|
|
; *****************************
|
|
; *** DOS Function 2F ***
|
|
; *** Get Disk Trans Adr ***
|
|
; *****************************
|
|
|
|
Public func2F
|
|
func2F:
|
|
les bx,dword ptr dma_offset ; current dma address
|
|
push ds
|
|
lds di,int21regs_ptr
|
|
mov reg_ES[di],es
|
|
mov reg_BX[di],bx
|
|
pop ds
|
|
ret
|
|
|
|
|
|
eject
|
|
; *****************************
|
|
; *** DOS Function 41 ***
|
|
; *** Delete File(s) ***
|
|
; *****************************
|
|
;
|
|
Public func41
|
|
func41:
|
|
cmp ss:remote_call,0
|
|
jne fdos_common41
|
|
mov cl,06h
|
|
|
|
; *****************************
|
|
; *** DOS Function 39 ***
|
|
; *** Create SubDirectory ***
|
|
; *****************************
|
|
;
|
|
Public func39
|
|
func39:
|
|
|
|
; *****************************
|
|
; *** DOS Function 3A ***
|
|
; *** Delete SubDirectory ***
|
|
; *****************************
|
|
;
|
|
Public func3A
|
|
func3A:
|
|
|
|
; *****************************
|
|
; *** DOS Function 3B ***
|
|
; *** Change SubDirectory ***
|
|
; *****************************
|
|
;
|
|
Public func3B
|
|
func3B:
|
|
; *****************************
|
|
; *** DOS Function 4E ***
|
|
; *** Find First File ***
|
|
; *** DOS Function 4F ***
|
|
; *** Find Next File ***
|
|
; *****************************
|
|
;
|
|
Public func4E
|
|
func4E:
|
|
Public func4F
|
|
func4F:
|
|
; Func 4F has no parameters, but using the same routine saves code
|
|
|
|
fdos_common41:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
; jmps fdos_name
|
|
|
|
fdos_name:
|
|
mov FD_NAMEOFF,dx ; Initialise Pointer
|
|
mov FD_NAMESEG,es
|
|
mov FD_ATTRIB,cx ; and attributes
|
|
jmp fdos_ax_crit
|
|
|
|
eject
|
|
; *****************************
|
|
; *** DOS Function 5B ***
|
|
; *** Create New File ***
|
|
; *****************************
|
|
;
|
|
Public func5B
|
|
func5B:
|
|
|
|
; *****************************
|
|
; *** DOS Function 3C ***
|
|
; *** Create a File ***
|
|
; *****************************
|
|
;
|
|
Public func3C
|
|
func3C:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
cmp FD_FUNC,MS_X_CREAT ; is it a standard create ?
|
|
je f3C_10
|
|
mov FD_FUNC,FD_NEW ; no, create a new file
|
|
f3C_10:
|
|
mov FD_MODE,DHM_RW ; create as read/write
|
|
jmps fdos_name ; go do it
|
|
|
|
; *****************************
|
|
; *** DOS Function 3D ***
|
|
; *** Open a File ***
|
|
; *****************************
|
|
;
|
|
Public func3D
|
|
func3D:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
cmp ss:remote_call,0
|
|
jne funcExtendedOpenCreate
|
|
mov cl,06h ; default search mode for local
|
|
; jmp funcExtendedOpenCreate ; calls (remote it's in CL)
|
|
funcExtendedOpenCreate:
|
|
; On Entry:
|
|
; FD_FUNC = function to carry out
|
|
; ES:DX -> name
|
|
; AX = open mode
|
|
; CX = file attributes
|
|
;
|
|
push ax
|
|
and al,DHM_SHAREMSK
|
|
cmp al,DHM_DENY_NONE ; any funny share bits ?
|
|
pop ax
|
|
ja open_mode_err
|
|
push ax
|
|
and al,DHM_RWMSK
|
|
cmp al,DHM_RW ; check RW bits are valid
|
|
pop ax
|
|
ja open_mode_err
|
|
mov FD_MODE,ax ; Set Open Mode
|
|
jmps fdos_name
|
|
|
|
open_mode_err:
|
|
mov ax,ED_ACC_CODE ; This is an illegal open mode
|
|
jmp error_exit ; return an error
|
|
|
|
|
|
; *****************************
|
|
; *** DOS Function 3F ***
|
|
; *** Read from Handle ***
|
|
; *****************************
|
|
;
|
|
Public func3F
|
|
func3F:
|
|
|
|
; *****************************
|
|
; *** DOS Function 40 ***
|
|
; *** Write to a Handle ***
|
|
; *****************************
|
|
;
|
|
Public func40
|
|
func40:
|
|
mov al,OK_RIF ; Valid to RETRY,IGNORE or FAIL
|
|
call set_retry
|
|
mov FD_BUFOFF,dx
|
|
mov FD_BUFSEG,es
|
|
mov FD_COUNT,cx
|
|
call fdos_handle
|
|
mov dx,FD_COUNT
|
|
jnc f40_10 ; no error, return # xfered
|
|
push FD_HANDLE
|
|
push dx ; an error, try critical error
|
|
call error_exit ; and if we get back here that
|
|
pop dx ; means we Fail/Ignore it
|
|
pop bx
|
|
jc f40_20 ; are we returning an error ?
|
|
push dx ; no, we are ignoring it
|
|
xor cx,cx ; CX:DX offset to skip
|
|
mov ax,(MS_X_LSEEK*256)+1 ; seek to current+offset
|
|
call dos_entry
|
|
pop dx ; finally return # we wanted
|
|
f40_10: ; to xfer
|
|
xchg ax,dx ; AX = return code
|
|
jmp return_AX_CLC
|
|
f40_20:
|
|
ret
|
|
|
|
; *****************************
|
|
; *** DOS Function 42 ***
|
|
; *** Move R/W Pointer ***
|
|
; *****************************
|
|
;
|
|
Public func42
|
|
func42:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov word ptr FD_OFFSET+0,dx
|
|
mov word ptr FD_OFFSET+2,cx
|
|
mov FD_METHOD,ax
|
|
call fdos_handle
|
|
jc f42_error ; Do not return the current
|
|
mov ax,word ptr FD_OFFSET+0 ; file position if
|
|
mov dx,word ptr FD_OFFSET+2 ; an error occurs
|
|
call return_DX
|
|
jmp return_AX_CLC
|
|
|
|
f42_error:
|
|
jmp error_exit
|
|
|
|
fdos_handle:
|
|
mov FD_HANDLE,bx
|
|
jmp fdos_crit
|
|
|
|
; *****************************
|
|
; *** DOS Function 43 ***
|
|
; *** Change File Mode ***
|
|
; *****************************
|
|
;
|
|
; Concurrent Password Support:-
|
|
;
|
|
; *WO* *GR* *OW* This is the format of the Password
|
|
; P---$RWED$RWED$RWED mode word which is compatible with
|
|
; the FlexOS F_PROTECT field.
|
|
; *WO* World (Ignored)
|
|
; *GR* Group (Ignored) The P flag is only used to designate
|
|
; *OW* Owner (Used) that the password is being updated.
|
|
;
|
|
Public func43
|
|
func43:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_FLAG,ax ; Requested Attributes ignored
|
|
call fdos_name ; if flags are not being set
|
|
jc f42_error
|
|
call reload_registers ; get back AL
|
|
test al,81h
|
|
jnz f43_exit
|
|
mov cx,FD_ATTRIB
|
|
call return_CX ; Return Attribs/Password
|
|
xchg ax,cx ; Also in AX
|
|
f43_exit:
|
|
jmp return_AX_CLC
|
|
|
|
; *****************************
|
|
; *** DOS Function 46 ***
|
|
; *** Force Dup Handle ***
|
|
; *****************************
|
|
;
|
|
Public func46
|
|
func46:
|
|
xchg bx,cx ; destination handle in BX
|
|
mov ah,MS_X_CLOSE ; try to close it but ignore
|
|
call dos_entry ; errors as it may be already
|
|
xchg bx,cx ; now fall thru to handle func
|
|
mov ah,MS_X_DUP2 ; do do the duplicate
|
|
|
|
; *****************************
|
|
; *** DOS Function 45 ***
|
|
; *** Duplicate Handle ***
|
|
; *****************************
|
|
;
|
|
Public func45
|
|
func45:
|
|
|
|
; *****************************
|
|
; *** DOS Function 3E ***
|
|
; *** Close a File ***
|
|
; *****************************
|
|
;
|
|
Public func3E
|
|
func3E:
|
|
mov al,OK_FAIL
|
|
call set_retry ; Valid to FAIL
|
|
mov FD_NEWHND,cx ; (in case it's force dup)
|
|
; jmps fdos_ax_handle
|
|
|
|
fdos_ax_handle:
|
|
mov FD_HANDLE,bx
|
|
jmp fdos_ax_crit
|
|
|
|
; *****************************
|
|
; *** DOS Function 5C ***
|
|
; ***Lock/Unlock File Access***
|
|
; *****************************
|
|
;
|
|
Public func5C
|
|
func5C:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_FUNC,FD_LOCK ; Lock/Unlock File
|
|
mov word ptr FD_OFFSET+0,dx ; Lock Offset (LOW)
|
|
mov word ptr FD_OFFSET+2,cx ; Lock Offset (HIGH)
|
|
mov word ptr FD_LENGTH+0,di ; Lock Length (LOW)
|
|
mov word ptr FD_LENGTH+2,si ; Lock Length (HIGH)
|
|
mov FD_LFLAG,ax ; Lock Type
|
|
jmps fdos_ax_handle
|
|
|
|
; *****************************
|
|
; *** DOS Function 47 ***
|
|
; *** Get Current Dir ***
|
|
; *****************************
|
|
;
|
|
Public func47
|
|
func47:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_PATHOFF,si ; Initialise Pointer
|
|
mov FD_PATHSEG,es
|
|
xchg ax,dx ; drive in AL
|
|
cbw ; make that AX
|
|
mov FD_DRIVE,ax
|
|
jmp fdos_ax_crit ; return garbage in AH (SPJ bug)
|
|
|
|
; *****************************
|
|
; *** DOS Function 53 ***
|
|
; *** Build DPB from BPB ***
|
|
; *****************************
|
|
;
|
|
; This function takes the BPB at DS:SI and builds a DDSC at ES:BP
|
|
;
|
|
Public func53
|
|
func53:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_BPBOFF,si ; Segment and Offset of BPB
|
|
mov FD_BPBSEG,es
|
|
mov FD_DDSCOFF,bp ; Segment and Offset of DDSC
|
|
call reload_ES
|
|
mov FD_DDSCSEG,es
|
|
jmp fdos_nocrit
|
|
;
|
|
; *****************************
|
|
; *** DOS Function 56 ***
|
|
; *** Rename/Move a File ***
|
|
; *****************************
|
|
;
|
|
Public func56
|
|
func56:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_NNAMEOFF,di ; New FileName
|
|
push es
|
|
call reload_ES ; callers ES:DI
|
|
mov FD_NNAMESEG,es ; point to new filename
|
|
pop es
|
|
mov FD_ONAMEOFF,dx ; Old FileName
|
|
mov FD_ONAMESEG,es
|
|
cmp ss:remote_call,0
|
|
jne func56_10
|
|
mov cl,17h
|
|
func56_10:
|
|
mov FD_ATTRIB,cx
|
|
jmp fdos_crit
|
|
|
|
; *****************************
|
|
; *** DOS Function 57 ***
|
|
; *** Get/Set File Time ***
|
|
; *****************************
|
|
;
|
|
Public func57
|
|
func57:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_DATE,dx
|
|
mov FD_TIME,cx
|
|
mov FD_SFLAG,ax
|
|
cmp al,1 ; allow get/set only
|
|
mov ax,ED_FUNCTION ; all else fails horribly
|
|
ja f57_error
|
|
call fdos_handle
|
|
jc f57_error
|
|
call reload_registers
|
|
test al,al
|
|
jnz f57_exit
|
|
mov cx,FD_TIME
|
|
call return_CX ; return TIME in CX
|
|
mov dx,FD_DATE
|
|
jmp return_DX ; and DATE in DX
|
|
|
|
f57_exit:
|
|
ret
|
|
|
|
f57_error:
|
|
jmp error_exit
|
|
|
|
; *****************************
|
|
; *** DOS Function 5A ***
|
|
; *** Create Unique File ***
|
|
; *****************************
|
|
;
|
|
Public func5A
|
|
func5A:
|
|
mov ax,ED_ACCESS ; assume we will have an error
|
|
test cx,DA_FIXED ; because of silly attributes
|
|
jnz func5A_40 ; did we ?
|
|
mov si,dx ; find end of pathname
|
|
xor ax,ax ; no previous char
|
|
func5A_10:
|
|
xchg ax,bx ; BL = previous char
|
|
lods es:al ; get next char
|
|
test al,al ; is it the end of the string?
|
|
jz func5A_20
|
|
call dbcs_lead ; is it a KANJI char?
|
|
jnz func5A_10
|
|
inc si ; skip 2nd char of pair
|
|
jmps func5A_10
|
|
func5A_20:
|
|
dec si ; SI -> NUL
|
|
cmp bl,'\' ; was last char a '\' ?
|
|
je func5A_30
|
|
cmp bl,'/' ; (or a '/' for unix freaks)
|
|
je func5A_30
|
|
mov es:byte ptr [si],'\' ; append a '\' to name
|
|
inc si
|
|
func5A_30:
|
|
; Here ES:DX -> start of name, ES:SI -> position to append <unique name>,0
|
|
; CX = attribute for file.
|
|
; We generate a unique name based upon the time and date - if this already
|
|
; exists we keep retrying knowing the number of files is finite and we must
|
|
; succeed eventually
|
|
push cx ! push dx ! push si ; append a unique'ish name
|
|
call func5A_append_unique_name
|
|
pop si ! pop dx ! pop cx
|
|
mov ah,MS_X_MKNEW ; try to create unique file
|
|
call dos_entry
|
|
jnc func5A_50 ; exit if we succeeded
|
|
mov es:byte ptr [si],0 ; else forget extention
|
|
cmp ax,ED_EXISTS ; we only retry if it already exists
|
|
je func5A_30
|
|
func5A_40:
|
|
jmp error_exit ; return error to caller
|
|
func5A_50:
|
|
jmp return_AX_CLC ; return handle to caller
|
|
|
|
func5A_append_unique_name:
|
|
;-------------------------
|
|
; On Entry:
|
|
; ES:DX -> start of name
|
|
; ES:SI -> position to append <unique name>,0
|
|
; CX = attribute for file.
|
|
; On Exit:
|
|
; None
|
|
;
|
|
; We append a unique 8 character filename to this based upon the current
|
|
; date/time.
|
|
push si
|
|
mov ax,120dh
|
|
int 2fh ; get date/time in AX & DX
|
|
pop di
|
|
add ax,unique_name_seed ; randomise the date otherwise we would
|
|
inc unique_name_seed ; have one second wait between names
|
|
call func5A_app_AX ; store 4 ascii bytes
|
|
xchg ax,dx ; was DX = time
|
|
call func5A_app_AX ; store 4 ascii bytes
|
|
xor ax,ax
|
|
stosb ; and a terminating NUL
|
|
ret
|
|
|
|
func5A_app_AX:
|
|
; On Entry AX = word, ES:DI -> string
|
|
; Store 4 ASCII chars at ES:DI, based upon value in AX
|
|
call func5A_app_AL ; do low byte, falling thru to do high
|
|
func5A_app_AL:
|
|
call func5A_app_NIB ; low nibble, falling thru for high
|
|
func5A_app_NIB:
|
|
push ax
|
|
and al,0fh ; mask out a nibble
|
|
add al,'A' ; make it ASCII character
|
|
stosb ; plant the string
|
|
pop ax
|
|
mov cl,4
|
|
shr ax,cl ; shift nibble
|
|
ret
|
|
|
|
|
|
; *****************************
|
|
; *** DOS Function 60 ***
|
|
; ***Perform Name Processing***
|
|
; *****************************
|
|
;
|
|
; DS:SI point to a source string which contains a relative path
|
|
; specification ES:DI points to a buffer which is at least 80
|
|
; bytes longer than the source string.
|
|
;
|
|
; The carry flag is set and AX contains an error code if the
|
|
; source string is mal formed. This function is used by the
|
|
; Ryan-McFarland COBOL compiler.
|
|
;
|
|
Public func60
|
|
func60:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_FUNC,FD_EXPAND ; Expand a relative Path
|
|
mov FD_ONAMEOFF,si ; Initialise Source Pointer
|
|
mov FD_ONAMESEG,es
|
|
mov FD_NNAMEOFF,di ; Initialise Destination
|
|
call reload_ES ; pointer
|
|
mov FD_NNAMESEG,es
|
|
jmp fdos_crit
|
|
|
|
; *****************************
|
|
; *** DOS Function 67 ***
|
|
; *** Set/Handle Count ***
|
|
; *****************************
|
|
;
|
|
; We impose a minimum of 20 handles regardless of what the caller
|
|
; requests. If the request is <=20 we use the default handle table in
|
|
; the PSP, else we allocate a memory block for the new table.
|
|
; If the old handle table was in a memory block (ie. zero offset) we
|
|
; will free that block up afterwards.
|
|
; When shrinking the handle count the error ED_HANDLE will be given if
|
|
; open files would have been lost.
|
|
;
|
|
|
|
Public func67
|
|
func67:
|
|
push ds
|
|
mov ds,current_psp ; DS -> current PSP blk
|
|
cmp bx,20 ; force to minimum value of 20
|
|
jae f67_10
|
|
mov bx,20 ; never have less than 20 handles
|
|
f67_10:
|
|
|
|
mov cx,ds:PSP_XFNMAX ; we have this many handles
|
|
sub cx,bx ; are we growing ?
|
|
jbe f67_20 ; if shrinking make sure none open
|
|
les di,ds:PSP_XFTPTR ; point to existing handle table
|
|
lea di,[di+bx] ; point to 1st handle we will lose
|
|
mov al,0FFh ; they must all be closed
|
|
repe scasb ; or we fail
|
|
mov ax,ED_HANDLE ; fail if we are in danger of losing
|
|
jne f67_error ; open handles
|
|
f67_20:
|
|
|
|
push bx ; save # of handles wanted
|
|
push ds ! pop es
|
|
mov di,offset PSP_XFT ; ES:DI -> new handle table
|
|
cmp bx,20 ; if we are setting to the
|
|
je f67_30 ; default size
|
|
add bx,15 ; calculate memory required
|
|
mov cl,4 ! shr bx,cl ; num of paragraphs required
|
|
xor di,di ; offset will be zero
|
|
mov ah,MS_M_ALLOC ; allocate the memory
|
|
call dos_entry
|
|
mov es,ax ; ES:DI -> new handle table
|
|
f67_30:
|
|
pop bx ; BX = # handles wanted
|
|
jc f67_error ; ES:DI -> new handle table
|
|
|
|
mov cx,bx ; CX = new # handles
|
|
xchg cx,ds:PSP_XFNMAX ; Update the Handle Count
|
|
|
|
mov si,di ; Update the Table Offset
|
|
xchg si,ds:PSP_XFTOFF
|
|
mov ax,es
|
|
xchg ax,ds:PSP_XFTSEG ; Update the Table Segment
|
|
mov ds,ax ; DS:SI -> old handle table
|
|
; ES:DI -> new handle table
|
|
; CX = # old handles to copy
|
|
; BX = # new handles desired
|
|
|
|
sub bx,cx ; BX = # extra "closed" handles
|
|
jae f67_40 ; negative if we are shrinking
|
|
add cx,bx ; CX = # handles we inherit
|
|
xor bx,bx ; BX = no extra "closed" handles
|
|
f67_40:
|
|
|
|
push si ; save offset old handle table
|
|
rep movsb ; Copy the existing Handles
|
|
pop si ; SI = offset old handle table
|
|
|
|
mov al,0FFh ; AL = unused handle
|
|
mov cx,bx ; mark extra handles as unused
|
|
rep stosb ; mark as unused
|
|
|
|
test si,si ; do we have memory to free ?
|
|
jnz f67_50
|
|
mov ah,MS_M_FREE
|
|
call dos_entry ; free up old handle table DMD
|
|
f67_50:
|
|
pop ds
|
|
jmp return_AX_CLC ; clear carry on return
|
|
|
|
f67_error:
|
|
pop ds ; restore DS
|
|
jmp error_exit ; and return error AX to caller
|
|
|
|
; *****************************
|
|
; *** DOS Function 68 ***
|
|
; *** Commit File ***
|
|
; *****************************
|
|
;
|
|
Public func68
|
|
func68:
|
|
call set_retry_RF ; Valid to RETRY or FAIL
|
|
mov FD_FUNC,FD_COMMIT ; Close a File Handle
|
|
jmp fdos_handle
|
|
|
|
|
|
; *****************************
|
|
; *** DOS Function 6C ***
|
|
; *** Extended Open ***
|
|
; *****************************
|
|
;
|
|
|
|
Public func6C
|
|
func6C:
|
|
mov al,OK_RF ; Valid to RETRY or FAIL
|
|
test bh,20h ; should we allow critical errors ?
|
|
jz f6C10
|
|
or al,NO_CRIT_ERRORS ; no, so remember that
|
|
f6C10:
|
|
call set_retry
|
|
mov ax,ED_FUNCTION ; assume an illegal action code
|
|
test dx,not 0113h ; now check for sensible bits
|
|
jnz f6C_error
|
|
inc dx
|
|
test dl,4 ; also reject bits 0-3 = 3
|
|
jnz f6C_error
|
|
dec dx
|
|
|
|
xchg ax,si ; ES:AX -> name
|
|
xchg ax,dx ; AX = action, ES:DX -> name
|
|
xchg ax,bx ; AX = open mode, BX = action
|
|
|
|
test bl,010h ; should we create if not there ?
|
|
jz f6C_open ; no, skip the attempt at make new
|
|
|
|
and ah,(DHM_COMMIT+DHM_NOCRIT)/100h
|
|
mov FD_FUNC,FD_NEW ; create only if not there
|
|
call funcExtendedOpenCreate ; try to open/create the file
|
|
|
|
mov cx,2 ; CX = file created
|
|
jnc f6C_exit ; return this if we succeeded
|
|
|
|
f6C_open:
|
|
call reload_registers ; all registers as per entry
|
|
xchg ax,si ; ES:AX -> name
|
|
xchg ax,dx ; AX = action, ES:DX -> name
|
|
xchg ax,bx ; AX = open mode, BX = action
|
|
push bx ; save action
|
|
and ah,(DHM_COMMIT+DHM_NOCRIT)/100h
|
|
mov FD_FUNC,MS_X_OPEN ; try an open an existing file
|
|
call funcExtendedOpenCreate
|
|
pop bx ; recover action
|
|
jc f6C_error ; return error if we can't open file
|
|
|
|
mov cx,1 ; CX = file opened
|
|
test bl,001h ; should we open if it exists ?
|
|
jnz f6C_exit ; yes, return the handle
|
|
|
|
xchg ax,bx ; BX = handle, AX = action
|
|
test al,002h ; should we replace the file ?
|
|
mov ax,ED_EXISTS ; if not close and return error
|
|
jz f6C_close_on_error
|
|
mov ah,MS_X_WRITE
|
|
xor cx,cx ; write zero bytes to truncate file
|
|
call dos_entry
|
|
jc f6C_close_on_error ; on error AX = error code, return it
|
|
xchg ax,bx ; AX = handle
|
|
mov cx,3 ; CX = file replaced
|
|
f6C_exit:
|
|
jmp return_CX ; return CX to caller
|
|
|
|
f6C_close_on_error:
|
|
; File exits, but open should be failed (error code in AX)
|
|
push ax
|
|
mov ah,MS_X_CLOSE
|
|
call dos_entry ; close that file
|
|
pop ax
|
|
f6C_error:
|
|
jmp error_exit ; generate critical error
|
|
|
|
|
|
PCMODE_DATA DSEG WORD
|
|
extrn current_psp:word
|
|
extrn current_dsk:byte
|
|
extrn dma_offset:word
|
|
extrn dma_segment:word
|
|
extrn int21regs_ptr:dword
|
|
extrn last_drv:byte
|
|
extrn remote_call:word
|
|
if DELWATCH
|
|
extrn fdos_stub:dword
|
|
endif
|
|
|
|
GLOBAL_DATA dseg word
|
|
; When creating unique files we use the date/time to make the name.
|
|
; We add this seed value to "randomise" things, INCing on failure so the next
|
|
; attempt usually succeeds.
|
|
|
|
unique_name_seed dw 0 ; so we don't have to wait 1 second
|
|
|
|
end
|