mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-22 07:54:28 +00:00
2908 lines
58 KiB
NASM
2908 lines
58 KiB
NASM
; File : $Workfile: DOSIF.ASM$
|
|
;
|
|
; Description :
|
|
;
|
|
; Original Author :
|
|
;
|
|
; Last Edited By : $Author: RGROSS$
|
|
;
|
|
; Copyright : (C) 1992 Digital Research (UK), Ltd.
|
|
; Charnham Park
|
|
; Hungerford, Berks.
|
|
; U.K.
|
|
;
|
|
; *** Current Edit History ***
|
|
; *** End of Current Edit History ***
|
|
;
|
|
; $Log: $
|
|
; DOSIF.ASM 1.1 94/06/28 16:01:14 RGROSS
|
|
; Initial PUT
|
|
; DOSIF.ASM 1.16 94/06/28 16:01:28 IJACK
|
|
; ms_x_expand returns error codes (for benefit of TRUENAME)
|
|
; DOSIF.ASM 1.15 93/11/29 19:57:24 IJACK
|
|
;
|
|
; --------
|
|
;
|
|
; DOSIF.ASM 1.13 93/09/09 10:24:50 RFREEBOR
|
|
; call_novell() now returns all allowed error codes.
|
|
;
|
|
; DOSIF.ASM 1.12 93/02/24 17:42:49 EHILL
|
|
; _get_scr_width() function added.
|
|
;
|
|
; DOSIF.ASM 1.11 93/01/21 16:19:31 EHILL
|
|
;
|
|
; DOSIF.ASM 1.10 93/01/21 14:32:32 EHILL
|
|
;
|
|
; DOSIF.ASM 1.8 92/09/11 10:46:28 EHILL
|
|
;
|
|
; DOSIF.ASM 1.7 92/08/06 09:56:07 EHILL
|
|
; Added DOS 5 calls to get and set memory allocation strategy and
|
|
; upper memory link.
|
|
;
|
|
; DOSIF.ASM 1.6 92/07/10 17:47:13 EHILL
|
|
; No comment
|
|
;
|
|
; ENDLOG
|
|
;
|
|
; This file provides all the assembler level interfaces to the
|
|
; underlying operating system that are required by COMMAND.COM.
|
|
; The type of functions calls that will be made is controlled
|
|
; by a Assemble time flag.
|
|
;
|
|
; Currently the Operating System Interfaces that are supported
|
|
; are MS-DOS and Concurrent DOS 6.0.
|
|
;
|
|
;
|
|
; Command Line Flags
|
|
; ==================
|
|
;
|
|
; MSDOS If defined then USE MSDOS function Calls
|
|
; CDOS If defined then Use Concurrent DOS Calls
|
|
;
|
|
;
|
|
; 2/Sep/87 jc Convert the Concurrent IOCTL function to use the FDOS
|
|
; command.
|
|
; 19/Oct/87 jc Handle Fail on Get current directory correctly
|
|
; 23/Feb/88 jc Use Text substitution function to get the path assigned
|
|
; to floating drives (ms_x_subst).
|
|
; 3/Mar/88 jc Support Server Password Error
|
|
; 9/Mar/88 jc Return a NULL terminated string when an error occurs on the
|
|
; ms_x_subst function.
|
|
; 15/Mar/88 jc Correct ms_x_subst register corruption bug
|
|
; 13/Apr/88 jc Support the FAR_READ and FAR_WRITE routines as well as external
|
|
; copy buffer allocation via MEM_ALLOC and MEM_FREE
|
|
; 20/May/88 jc Return the current country code to the calling application
|
|
; 25/May/88 jc Missing dataOFFSET causing garbage offset to be passed
|
|
; ms_x_subst.
|
|
; 18/Jul/88 jc Modify LOGICAL_DRV test to detect substituted physical drives
|
|
; 17/Aug/88 jc Return the current Break Status using DL not AL
|
|
; 22/Sep/88 jc Replace MS_X_SUBST with more general MS_X_EXPAND routine
|
|
; 25/Jan/89 ij If new DRDOS internal data layout get DPHTBL the new way
|
|
; 07/Feb/89 jc Add the Get and Set Global Codepage MS_X_GETCP/MS_X_SETCP
|
|
; 25/Jan/89 ij Get DPHTBL using DRDOS_DPHTBL_OFFSET equate
|
|
; 14/Apr/89 jjs Add ms_x_setdev
|
|
; 31/May/89 ij Get SYSDAT for DPHTBL using new f4458 function
|
|
; 19/May/89 jc Remove "Alternative" techniques of getting SYSDAT:DPHTABLE
|
|
; 20/Jun/89 js ms_f_parse, ms_f_delete, for DEL cmd
|
|
; 30/Aug/89 js ms_idle_ptr
|
|
; 6/Sep/89 ij network_drvs really does something on DRDOS
|
|
; 16/Oct/89 ach Added double byte character set support routines: dbcs_init,
|
|
; dbcs_expected and dbcs_lead.
|
|
; 18/Jan/90 ij HILOAD interfaces added
|
|
; 4/Apr/90 ij dbcs_init moved to cstart, use system table, then we can throw
|
|
; away the init code
|
|
; 24-May-90 ij ms_x_expand sets up ES....
|
|
; 17 Sep 90 ij TMP Control Break kludge echo's ^C to console
|
|
; 4 Oct 90 ij Use P_CAT, not P_HDS
|
|
; 15 Mar 91 jc DRDOS_DPHTBL is now called SYSDAT_DPHTBL cos thats where it lives
|
|
; 28 May 91 ejh No longer use SYSDAT to determine if drives are physical,
|
|
; logical or networked. See _physical_drive, _logical_drive and
|
|
; _network_drive.
|
|
; 23 Jun 91 ejh SUBST and ASSIGN are now external commands, so the following
|
|
; are no longer required:
|
|
; _physical_drvs, _logical_drvs, _network_drvs
|
|
; _physical_drive,_logical_drive,_network_drive
|
|
; 3 jul 91 ij except for NETDRIVE in MDOS
|
|
;
|
|
; 18 Jun 92 ejh Added get_lines_page() function.
|
|
; 24 Jun 92 ejh Added novell_copy() function.
|
|
|
|
CGROUP group _TEXT
|
|
DGROUP group _DATA
|
|
|
|
codeOFFSET equ offset CGROUP:
|
|
dataOFFSET equ offset DGROUP:
|
|
|
|
EXT_SUBST equ 1 ; External Subst and Assign commands
|
|
|
|
CRET MACRO num
|
|
ret
|
|
ENDM
|
|
|
|
ifndef ??Version ;; Turbo Assembler always knows RETF
|
|
ifndef retf ;; some versions of MASM do as well
|
|
retf macro ;; define far return macro for others
|
|
db 0cbh
|
|
endm
|
|
endif
|
|
endif
|
|
|
|
|
|
ifndef CDOSTMP
|
|
include msdos.equ
|
|
endif
|
|
|
|
ifndef DOSPLUS
|
|
include system.def
|
|
include pd.def
|
|
include ccpm.equ
|
|
;include udaa.def
|
|
include net.def
|
|
include mserror.equ
|
|
else
|
|
include f52data.def
|
|
endif
|
|
;
|
|
ifdef CDOSTMP
|
|
OK_RIF equ 00111000b ; All Responsese are Valid
|
|
OK_RI equ 00110000b ; Retry and Ignore are Valid
|
|
OK_RF equ 00011000b ; Retry and Fail are Valid
|
|
;
|
|
; Structure of DOS DPB
|
|
; --------------------
|
|
; The layout of this structure is a guess based on
|
|
; examples. It is returned by PC MODE on functions 1Fh and
|
|
; 32h and is required by various disk-related utilities
|
|
; like disk editors and CHKDSK.
|
|
|
|
DDSC_UNIT equ es:byte ptr 0 ; absolute drive number
|
|
DDSC_RUNIT equ es:byte ptr 1 ; relative unit number
|
|
DDSC_SECSIZE equ es:word ptr 2 ; sector size in bytes
|
|
DDSC_CLMSK equ es:byte ptr 4 ; sectors/cluster - 1
|
|
DDSC_CLSHF equ es:byte ptr 5 ; log2 (sectors/cluster)
|
|
DDSC_FATADDR equ es:word ptr 6 ; sector address of FAT
|
|
DDSC_NFATS equ es:byte ptr 8 ; # of FAT copies
|
|
DDSC_DIRENT equ es:word ptr 9 ; size of root directory
|
|
DDSC_DATADDR equ es:word ptr 11 ; sector address of cluster #2
|
|
DDSC_NCLSTRS equ es:word ptr 13 ; # of clusters on disk
|
|
DDSC_NFATRECS equ es:byte ptr 15 ; # of sectors per FAT
|
|
DDSC_DIRADDR equ es:word ptr 16 ; sector address of root dir
|
|
DDSC_DEVHEAD equ es:dword ptr 18 ; device driver header
|
|
DDSC_MEDIA equ es:byte ptr 22 ; current media byte
|
|
DDSC_FIRST equ es:byte ptr 23 ; "drive never accessed" flag
|
|
DDSC_LINK equ es:dword ptr 24 ; next drive's DDSC
|
|
DDSC_BLOCK equ es:word ptr 28 ; next block to allocate
|
|
DDSC_FREE equ es:word ptr 30 ; total free clusters on drive
|
|
DDSC_MAP equ es:word ptr 32 ; free blocks/FAT sector
|
|
endif
|
|
|
|
BDOS_INT equ 224 ; ##jc##
|
|
|
|
|
|
_DATA SEGMENT byte public 'DATA'
|
|
extrn __psp:word
|
|
ifndef DOSPLUS
|
|
extrn _pd:dword ; Process Descriptor Pointer
|
|
endif
|
|
extrn _country:WORD
|
|
|
|
ifdef DOSPLUS
|
|
extrn dbcs_table_ptr:dword ; points to system DBCS table
|
|
endif
|
|
|
|
ifdef CDOSTMP
|
|
;
|
|
; The following buffer is used by the P_PATH function.
|
|
; FINDFILE uses the first three fields to get the full path and
|
|
; filename of the command.
|
|
;
|
|
exec_block label byte
|
|
exec_pathoff dw ? ; Offset of ASCIIZ Load file
|
|
exec_pathseg dw ? ; Segment of ASCIIZ Load File
|
|
exec_filetype db ? ; File Type Index
|
|
|
|
fdos_data dw 7 dup(0) ; FDOS parameter Block
|
|
|
|
mpb_start dw ? ; Memory parameter Block
|
|
mpb_min dw ?
|
|
mpb_max dw ?
|
|
mpb_pdadr dw ?
|
|
mpb_flags dw ?
|
|
|
|
mfpb_start dw ? ; Memory Free Parameter Block
|
|
mfpb_res dw ?
|
|
|
|
country_data label word ; GET country data
|
|
cd_country dw ? ; Requested Country Code
|
|
cd_codepage dw ? ; Requested Code Page
|
|
cd_table dw ? ; Table Number
|
|
cd_offset dw ? ; Buffer Offset
|
|
cd_segment dw ? ; Buffer Segment
|
|
|
|
valid dw 0 ; Valid Error Responses
|
|
retry_ip dw 0 ; Critical Error Retry IP
|
|
retry_sp dw 0 ; Critical Error Retry SP
|
|
crit_flg db FALSE ; Critical Section of Error Handler
|
|
|
|
include fdos.def
|
|
endif
|
|
|
|
ifdef NETWARE
|
|
ipx label dword
|
|
ipx_offset dw 0
|
|
ipx_segment dw 0
|
|
;
|
|
; Socket Allocation by Novell
|
|
;
|
|
; Socket Nos 4000 and 4001 appear to be used by the IPX internally
|
|
; and these are NOT closed by the NET_WARE routine. All other USER
|
|
; sockets are closed.
|
|
;
|
|
; List of sockets to be closed on shutdown
|
|
; Start Count
|
|
socket label word
|
|
;; dw 0001h, 0BB8h
|
|
dw 4002h, 3FFFh - 2 ; User Socket Numbers
|
|
dw 0, 0
|
|
|
|
aes label byte ; Event Control Block
|
|
aes_link label dword ; Link Field
|
|
aes_linkoff dw 0
|
|
aes_linkseg dw 0
|
|
aes_esr label dword ; Service Routine Address
|
|
aes_esroff dw codeOFFSET aes_retf
|
|
aes_esrseg dw 0000
|
|
aes_inuse db 0 ; Flag Field
|
|
aes_workspc db 5 dup(?) ; AES WorkSpace
|
|
endif
|
|
_DATA ENDS
|
|
|
|
_TEXT SEGMENT byte public 'CODE'
|
|
assume cs:CGROUP, ds:DGROUP, es:DGROUP
|
|
|
|
extrn _int_break:near ; Control-C Break Handler
|
|
|
|
ifdef CDOSTMP
|
|
ifdef MWC
|
|
extrn _critical_error:near ; Default Critical Error Handler
|
|
CRITICAL_ERR equ _critical_error
|
|
else
|
|
extrn CRITICAL_ERROR:near ; Default Critical Error Handler
|
|
CRITICAL_ERR equ CRITICAL_ERROR
|
|
endif
|
|
endif
|
|
|
|
;
|
|
; UWORD psp_poke(WORD handle, BYTE ifn);
|
|
;
|
|
Public _psp_poke
|
|
_psp_poke:
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
|
|
ifdef CDOSTMP
|
|
mov es,__psp ; ES:0 -> our PSP
|
|
else
|
|
mov ah,MS_P_GETPSP
|
|
int DOS_INT ; for software carousel
|
|
mov es,bx
|
|
endif
|
|
les bx,es:[0034h] ; ES:BX -> external file table
|
|
add bx,4[bp] ; ES:BX -> XFT entry for our handle
|
|
mov al,6[bp] ; get new value to use
|
|
xchg al,es:[bx] ; get old value, set new value
|
|
xor ah,ah
|
|
|
|
pop es
|
|
pop bp
|
|
ret
|
|
|
|
ifndef CDOSTMP
|
|
|
|
|
|
Public _ms_drv_set
|
|
;-----------
|
|
_ms_drv_set:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dl,04[bp]
|
|
mov ah,MS_DRV_SET ; Select the Specified Disk Drive
|
|
int DOS_INT ; Nothing Returned to caller
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_drv_get
|
|
;-----------
|
|
_ms_drv_get:
|
|
;-----------
|
|
mov ah,MS_DRV_GET ; Return the Currently selected
|
|
int DOS_INT ; disk drive
|
|
cbw
|
|
ret
|
|
|
|
Public _ms_drv_space
|
|
;------------
|
|
_ms_drv_space:
|
|
;------------
|
|
;
|
|
; ret = _ms_drv_space (drive, &free, &secsiz, &nclust);
|
|
; where: drive = 0, 1-16 is drive to use
|
|
; free = free cluster count
|
|
; secsiz = bytes/sector
|
|
; nclust = clusters/disk
|
|
; ret = sectors/cluster -or- (0xFFFFh)
|
|
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp]
|
|
mov ah,MS_DRV_SPACE
|
|
int DOS_INT
|
|
push bx
|
|
mov bx,6[bp] ; get free cluster count
|
|
pop word ptr [bx]
|
|
mov bx,8[bp]
|
|
mov [bx],cx ; bytes/sector
|
|
mov bx,10[bp]
|
|
mov [bx],dx ; clusters/disk
|
|
cbw
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_s_country
|
|
;------------
|
|
_ms_s_country:
|
|
;------------
|
|
push bp
|
|
mov bp,sp
|
|
mov ax,MS_S_COUNTRY shl 8 ; Get the curremt country information
|
|
mov dx,4[bp] ; and return the current country code
|
|
int DOS_INT ; to the calling application.
|
|
mov ax,bx
|
|
pop bp
|
|
ret
|
|
|
|
|
|
Public _ms_x_mkdir
|
|
;----------
|
|
_ms_x_mkdir:
|
|
;----------
|
|
mov ah,MS_X_MKDIR
|
|
jmp ms_dx_call
|
|
|
|
|
|
Public _ms_x_rmdir
|
|
;----------
|
|
_ms_x_rmdir:
|
|
;----------
|
|
mov ah,MS_X_RMDIR
|
|
jmp ms_dx_call
|
|
|
|
|
|
Public _ms_x_chdir
|
|
;----------
|
|
_ms_x_chdir:
|
|
;----------
|
|
mov ah,MS_X_CHDIR
|
|
jmp ms_dx_call
|
|
|
|
Public _ms_x_creat
|
|
;----------
|
|
_ms_x_creat:
|
|
;----------
|
|
mov ah,MS_X_CREAT
|
|
jmp ms_open_creat
|
|
|
|
|
|
Public _ms_x_open
|
|
;---------
|
|
_ms_x_open:
|
|
;---------
|
|
mov ah,MS_X_OPEN
|
|
ms_open_creat:
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp]
|
|
mov cx,6[bp] ; get mode for new file (CREAT)
|
|
mov al,cl ; or open mode (OPEN)
|
|
int DOS_INT
|
|
jnc ms_open_ret ; AX = handle if no error
|
|
neg ax ; else mark as error code
|
|
ms_open_ret:
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_x_close
|
|
;----------
|
|
_ms_x_close:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp] ; get the open handle
|
|
mov ah,MS_X_CLOSE ; get the function
|
|
jmp ms_call_dos ; call DOS, handle errors
|
|
|
|
Public _ms_x_unique
|
|
;----------
|
|
_ms_x_unique:
|
|
;----------
|
|
mov ah,MS_X_MKTEMP
|
|
jmp ms_open_creat
|
|
|
|
Public _ms_x_fdup
|
|
;----------
|
|
_ms_x_fdup:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov cx,4[bp] ; get the destination handle
|
|
mov bx,6[bp] ; Get the current handle
|
|
mov ah,MS_X_DUP2 ; get the function
|
|
jmp ms_call_dos ; call DOS, handle errors
|
|
|
|
|
|
Public _far_read
|
|
;---------
|
|
_far_read:
|
|
;---------
|
|
mov ah,MS_X_READ
|
|
jmp far_read_write
|
|
|
|
Public _far_write
|
|
;----------
|
|
_far_write:
|
|
;----------
|
|
mov ah,MS_X_WRITE
|
|
far_read_write:
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov bx,4[bp] ; get file handle
|
|
lds dx,dword ptr 6[bp] ; get buffer address
|
|
mov cx,10[bp] ; get byte count
|
|
int DOS_INT ; call the DOS
|
|
jnc far_rw_ok ; skip if no error
|
|
neg ax ; else make it negative error code
|
|
far_rw_ok:
|
|
pop ds
|
|
pop bp
|
|
ret
|
|
|
|
|
|
Public _ms_x_read
|
|
;---------
|
|
_ms_x_read:
|
|
;---------
|
|
mov ah,MS_X_READ
|
|
jmp ms_read_write
|
|
|
|
Public _ms_x_write
|
|
;----------
|
|
_ms_x_write:
|
|
;----------
|
|
mov ah,MS_X_WRITE
|
|
ms_read_write:
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp] ; get file handle
|
|
mov dx,6[bp] ; get buffer address
|
|
mov cx,8[bp] ; get byte count
|
|
int DOS_INT ; call the DOS
|
|
jnc ms_rw_ok ; skip if no error
|
|
neg ax ; else make it negative error code
|
|
ms_rw_ok:
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_x_unlink
|
|
;-----------
|
|
_ms_x_unlink:
|
|
;-----------
|
|
mov ah,MS_X_UNLINK
|
|
jmp ms_dx_call
|
|
|
|
|
|
Public _ms_x_lseek
|
|
;----------
|
|
_ms_x_lseek:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov ah,MS_X_LSEEK ; get the function
|
|
mov bx,4[bp] ; get the file handle
|
|
mov dx,6[bp] ; get the offset
|
|
mov cx,8[bp]
|
|
mov al,10[bp] ; get the seek mode
|
|
int DOS_INT
|
|
jnc ms_lseek_ok ; skip if no errors
|
|
neg ax ; make error code negative
|
|
cwd ; sign extend to long
|
|
ms_lseek_ok:
|
|
mov bx,dx ; AX:BX = DRC long return
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_x_ioctl
|
|
;----------
|
|
_ms_x_ioctl:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp] ; get our handle
|
|
mov ah,MS_X_IOCTL ; get IO Control function
|
|
mov al,0 ; get file/device status
|
|
int DOS_INT ; do INT 21h
|
|
jnc ms_x_i10
|
|
neg ax
|
|
ms_x_i10:
|
|
pop bp ;
|
|
ret
|
|
|
|
Public _ms_x_setdev
|
|
;------------
|
|
_ms_x_setdev:
|
|
;------------
|
|
push bp
|
|
mov bp, sp
|
|
mov bx, 4[bp] ; handle
|
|
mov dx, 6[bp] ; byte value to set
|
|
sub dh, dh
|
|
mov ah, MS_X_IOCTL
|
|
mov al, 1
|
|
int DOS_INT
|
|
jnc ms_x_sd10
|
|
neg ax
|
|
ms_x_sd10:
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_x_chmod
|
|
;----------
|
|
_ms_x_chmod:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov ah,MS_X_CHMOD
|
|
mov dx,4[bp]
|
|
mov cx,6[bp]
|
|
mov al,8[bp]
|
|
int DOS_INT
|
|
jnc ms_chmod_ok
|
|
neg ax ; make error code negative
|
|
jmp ms_chmod_ret
|
|
ms_chmod_ok:
|
|
sub ax,ax ; assume no error
|
|
cmp byte ptr 8[bp],0 ; getting attributes
|
|
jne ms_chmod_ret ; return ax = 0 if setting & no error
|
|
xchg ax,cx ; return ax = attrib otherwise
|
|
ms_chmod_ret:
|
|
pop bp
|
|
ret
|
|
|
|
|
|
Public _ms_x_curdir
|
|
;-----------
|
|
_ms_x_curdir:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
mov si,6[bp] ; Get the buffer address and
|
|
mov byte ptr [si],0 ; put a zero in the first byte in
|
|
mov ah,MS_X_CURDIR ; the command is FAILED
|
|
push word ptr 4[bp]
|
|
call ms_dx_call
|
|
pop dx
|
|
pop si
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_x_exit
|
|
;---------
|
|
_ms_x_exit:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
|
|
ifdef NETWARE
|
|
push es ; If this is Novell Netware and
|
|
mov ax,__psp ; the command processor is terminating
|
|
mov es,ax ; ie PSP_PARENT == PSP then do the
|
|
cmp ax,es:word ptr 16h ; special Novell Close down sequence
|
|
pop es
|
|
jnz ms_x_exit10
|
|
|
|
mov ax,7A00h ; Check for IPX being present using
|
|
int 2Fh ; the Multi-Plex Interrupt.
|
|
cmp al,0FFh
|
|
jz net_ware
|
|
|
|
ms_x_exit10:
|
|
endif
|
|
mov al,04[bp] ; Get the Return Code
|
|
mov ah,MS_X_EXIT ; terminate process function
|
|
int DOS_INT ; call the DOS
|
|
pop bp
|
|
ret
|
|
|
|
ifdef NETWARE
|
|
;
|
|
; The following routine attempts to clean-up after a Novell
|
|
; session. It does so in the following manner:-
|
|
;
|
|
; 1) Close all file handles (May be Networked !!)
|
|
; 2) Close all User Sockets
|
|
; 3) Remove all User Events from Internal lists
|
|
; 4) Use CDOS terminate function
|
|
;
|
|
net_ware:
|
|
mov ipx_offset,di
|
|
mov ipx_segment,es
|
|
|
|
mov cx,20 ; Close all the possible handles
|
|
mov bx,0 ; used by the command processor
|
|
net_w05: ; in case any have been redirected
|
|
mov ah,MS_X_CLOSE ; accross the Network
|
|
int DOS_INT
|
|
inc bx
|
|
loop net_w05
|
|
|
|
mov si,dataOFFSET socket
|
|
net_w10:
|
|
mov cx,word ptr 02[si] ; Get the number of sockets to close
|
|
mov dx,word ptr 00[si] ; starting at Socket No.
|
|
jcxz net_w30 ; Terminate on a 0 Count
|
|
push si
|
|
net_w20:
|
|
push cx
|
|
push dx ; Save Count and Socket No.
|
|
xchg dl,dh ; Swap socket no to High/Low
|
|
mov bx,1 ; Close Socket Function
|
|
call ipx ; Close Socket.
|
|
pop dx
|
|
pop cx
|
|
inc dx ; Increment Socket No
|
|
loop net_w20 ; and Loop
|
|
pop si
|
|
add si,4 ; Point to next entry in the array
|
|
jmp net_w10 ; and repeat till count is 0
|
|
|
|
net_w30: ; All sockets have been closed
|
|
mov aes_esrseg,cs
|
|
mov ax,0FFFFh ; Create Special event with the
|
|
mov bx,7 ; maximum time delay
|
|
push ds
|
|
pop es ; Pass the address of the Special
|
|
mov si,dataOFFSET aes ; Event control block call the IPX
|
|
call ipx
|
|
|
|
net_w40:
|
|
les si,aes_link ; Remove all entries from the Link
|
|
; Which are not owned by the IPX
|
|
net_w50:
|
|
mov bx,es ; get the AES segment
|
|
cmp bx,ipx_segment ; and check for a match
|
|
jnz net_w60 ; Remove this entry
|
|
les si,es:dword ptr [si] ; get the next entry and try again
|
|
jmp short net_w50
|
|
|
|
net_w60:
|
|
or bx,si ; End of List
|
|
jz net_w70 ; Yes terminate our entry
|
|
mov bx,0006h ; Cancel this event
|
|
call ipx
|
|
jmp short net_w40
|
|
|
|
net_w70:
|
|
mov bx,0006h ; Cancel our event
|
|
push ds
|
|
pop es
|
|
mov si,dataOFFSET aes
|
|
call ipx
|
|
|
|
net_exit:
|
|
mov dh,0 ; Standard Exit
|
|
mov dl,04[bp] ; With the supplied ExitCode
|
|
mov cx,P_EXITCODE ; Set the ExitCode for the Parent
|
|
int BDOS_INT
|
|
mov cx,P_TERMCPM ; Use a Concurrent Terminate Call
|
|
int BDOS_INT ; because Novell has taken over 4Ch
|
|
|
|
aes_retf: ; Dummy AES routine
|
|
retf
|
|
endif
|
|
|
|
;
|
|
; ms_x_expand(dstbuf, srcbuf) returns the full path of SRCBUF
|
|
;
|
|
Public _ms_x_expand
|
|
;-----------
|
|
_ms_x_expand:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
push di
|
|
mov si,06[bp] ; Get the source String Address
|
|
mov di,04[bp] ; Get the destination string
|
|
mov byte ptr [di],0 ; address and force it to be a NULL
|
|
push ds
|
|
pop es ; ES:DI -> destination
|
|
mov ah,60h ; terminated string in case of errors
|
|
int DOS_INT
|
|
jc ms_exp_ret ; skip if error
|
|
xor ax,ax ; signal no errors
|
|
ms_exp_ret:
|
|
neg ax ; make error negative, 0 = 0
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
CRET 4
|
|
|
|
Public _ms_x_wait
|
|
;---------
|
|
_ms_x_wait: ; retrieve child return code
|
|
;---------
|
|
mov ah,MS_X_WAIT ; Top byte is abort code ie ^C
|
|
int DOS_INT ; Bottom byte is return code
|
|
ret
|
|
|
|
Public _ms_x_first
|
|
;----------
|
|
_ms_x_first:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,8[bp] ; get DMA buffer address
|
|
mov ah,MS_F_DMAOFF
|
|
int DOS_INT
|
|
mov dx,4[bp] ; get ASCII string
|
|
mov cx,6[bp] ; get attribute
|
|
mov ah,MS_X_FIRST ; get search function
|
|
jmp ms_call_dos ; call DOS, check for errors
|
|
|
|
Public _ms_x_next
|
|
;---------
|
|
_ms_x_next:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp] ; get DMA buffer address
|
|
mov ah,MS_F_DMAOFF
|
|
int DOS_INT
|
|
mov ah,MS_X_NEXT ; get the function
|
|
jmp ms_call_dos ; get DX, call DOS, handle errors
|
|
|
|
ms_dx_call: ; call DOS with parameter in DX
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp]
|
|
ms_call_dos:
|
|
int DOS_INT
|
|
jnc ms_dos_ok ; no carry = no error
|
|
neg ax ; else make it negative
|
|
jmp ms_dos_ret ; and return with error
|
|
ms_dos_ok:
|
|
sub ax,ax ; return 0 if no error
|
|
ms_dos_ret:
|
|
pop bp ; return 0 or negative error code
|
|
ret
|
|
|
|
|
|
Public _ms_x_rename
|
|
;-----------
|
|
_ms_x_rename:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
push di
|
|
push ds
|
|
pop es
|
|
mov ah,MS_X_RENAME
|
|
mov di,6[bp] ; ES:DI = new name
|
|
push word ptr 4[bp] ; make it look like DRC call
|
|
call ms_dx_call ; DX = 4[bp], call DOS, handle errors
|
|
pop di ; remove parameter
|
|
pop di
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_x_datetime
|
|
; ret = _ms_x_datetime (gsflag, h, &time, &date);
|
|
;-------------
|
|
_ms_x_datetime:
|
|
;-------------
|
|
push bp
|
|
mov bp,sp
|
|
mov ah,MS_X_DATETIME ; set/get time stamp function
|
|
mov al,4[bp] ; get/set subfunction (0/1)
|
|
mov bx,8[bp] ; get address of time
|
|
mov cx,[bx] ; get time
|
|
mov bx,10[bp] ; get address of date
|
|
mov dx,[bx] ; get date
|
|
mov bx,6[bp] ; get handle
|
|
int DOS_INT ; call the DOS
|
|
jc ms_dt_ret ; skip if error
|
|
sub ax,ax ; signal no errors
|
|
cmp byte ptr 4[bp],0 ; geting time/date?
|
|
jne ms_dt_ret ; skip if setting
|
|
mov bx,8[bp] ; get time address
|
|
mov [bx],cx ; update time
|
|
mov bx,10[bp] ; get date address
|
|
mov [bx],dx ; update date
|
|
ms_dt_ret:
|
|
neg ax ; make error negative, 0 = 0
|
|
pop bp
|
|
ret
|
|
|
|
|
|
;
|
|
; The following routines allow COMMAND.COM to manipulate
|
|
; the system time and date. Four functions are provided and
|
|
; these are MS_GETDATE, MS_SETDATE, MS_GETTIME and MS_SETTIME
|
|
;
|
|
; Date information is passed and return in a structure which
|
|
; has the following format.
|
|
;
|
|
; WORD Year (1980 - 2099)
|
|
; BYTE Month
|
|
; BYTE Day
|
|
; BYTE Day of the Week (Ignored on SET DATE)
|
|
|
|
Public _ms_getdate
|
|
_ms_getdate:
|
|
push bp
|
|
mov bp,sp
|
|
mov ah,MS_T_GETDATE ; get the current date from DOS
|
|
int DOS_INT
|
|
mov bx,4[bp] ; and get the structure address
|
|
mov [bx],cx ; save the year
|
|
xchg dh,dl ; swap month and day
|
|
mov 2[bx],dx ; and save
|
|
mov 4[bx],al ; and finally save the day number
|
|
pop bp ; and exit
|
|
ret
|
|
|
|
Public _ms_setdate
|
|
_ms_setdate:
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp] ; and get the structure address
|
|
mov cx,0[bx] ; det the year
|
|
mov dx,2[bx] ; get the month and day
|
|
xchg dh,dl ; swap month and day
|
|
mov ah,MS_T_SETDATE ; set the current date
|
|
int DOS_INT
|
|
cbw ; 0000 = Ok and FFFF = Bad
|
|
pop bp ; and exit
|
|
ret
|
|
|
|
|
|
; Time information is passed and return in a structure which
|
|
; has the following format.
|
|
;
|
|
; BYTE Hours (0 - 23)
|
|
; BYTE Minutes (0 - 59)
|
|
; BYTE Seconds (0 - 59)
|
|
; BYTE Hundredths of a second (0 - 99)
|
|
|
|
Public _ms_gettime
|
|
_ms_gettime:
|
|
push bp
|
|
mov bp,sp
|
|
mov ah,MS_T_GETTIME ; get the current date from DOS
|
|
int DOS_INT
|
|
mov bx,4[bp] ; and get the structure address
|
|
xchg cl,ch
|
|
mov [bx],cx ; save the hours and minutes
|
|
xchg dh,dl
|
|
mov 2[bx],dx ; save seconds and hundredths
|
|
pop bp ; and exit
|
|
ret
|
|
|
|
Public _ms_settime
|
|
_ms_settime:
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp] ; and get the structure address
|
|
mov cx,[bx] ; get the hours and minutes
|
|
xchg cl,ch
|
|
mov dx,2[bx] ; get seconds and hundredths
|
|
xchg dh,dl
|
|
mov ah,MS_T_SETTIME ; get the current date from DOS
|
|
int DOS_INT
|
|
cbw ; 0000 = Ok and FFFF = Bad
|
|
pop bp ; and exit
|
|
ret
|
|
|
|
Public _ms_idle_ptr
|
|
;------------
|
|
_ms_idle_ptr:
|
|
;------------
|
|
push es
|
|
push si
|
|
push di
|
|
mov ax, 4458h
|
|
int DOS_INT ; ptr in ES:AX
|
|
mov dx, es
|
|
pop di
|
|
pop si
|
|
pop es
|
|
ret
|
|
|
|
Public _ms_switchar
|
|
;-----------
|
|
_ms_switchar:
|
|
;-----------
|
|
mov ax,3700h
|
|
int DOS_INT
|
|
sub ah,ah
|
|
mov al,dl
|
|
ret
|
|
if 0
|
|
Public _ms_p_getpsp
|
|
;-----------
|
|
_ms_p_getpsp:
|
|
;-----------
|
|
mov ah,51h ; Note: SeCRET DOS 2.x entry
|
|
int DOS_INT
|
|
xchg ax,bx
|
|
ret
|
|
endif
|
|
Public _ms_f_verify
|
|
;-----------
|
|
_ms_f_verify:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov ah,MS_F_VERIFY
|
|
mov al,4[bp] ;get 0/1 al parameter
|
|
int DOS_INT
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_f_getverify
|
|
;--------------
|
|
_ms_f_getverify:
|
|
;--------------
|
|
mov ah,MS_F_GETVERIFY
|
|
int DOS_INT
|
|
cbw
|
|
ret
|
|
|
|
ifndef CDOSTMP
|
|
Public _ms_f_parse
|
|
;-----------
|
|
_ms_f_parse:
|
|
;-----------
|
|
push bp
|
|
mov bp, sp
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
push ds
|
|
pop es
|
|
mov di, 4[bp] ; fcb
|
|
mov si, 6[bp] ; filename
|
|
mov al, 8[bp] ; flags
|
|
mov ah, MS_F_PARSE
|
|
int DOS_INT
|
|
|
|
cbw ; return code in ax
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_f_delete
|
|
;------------
|
|
_ms_f_delete:
|
|
;------------
|
|
push bp
|
|
mov bp, sp
|
|
mov dx, 4[bp] ; fcb
|
|
mov ah, MS_F_DELETE
|
|
int DOS_INT
|
|
|
|
cbw ; return code
|
|
pop bp
|
|
ret
|
|
endif
|
|
;
|
|
; The SET BREAK function returns the previous Break Flag Status
|
|
;
|
|
Public _ms_set_break
|
|
;------------
|
|
_ms_set_break:
|
|
;------------
|
|
push bp
|
|
mov bp,sp
|
|
mov dl,04[bp]
|
|
mov ax,(MS_S_BREAK SHL 8) + 2
|
|
int DOS_INT
|
|
pop bp
|
|
mov al,dl
|
|
cbw
|
|
ret
|
|
|
|
if 0
|
|
Public _ms_get_break
|
|
;------------
|
|
_ms_get_break:
|
|
;------------
|
|
mov ax,MS_S_BREAK SHL 8
|
|
int DOS_INT
|
|
mov al,dl
|
|
cbw
|
|
ret
|
|
endif
|
|
|
|
;
|
|
; mem_alloc(BYTE FAR * NEAR * bufaddr, UWORD * bufsize, UWORD min, UWORD max);
|
|
;
|
|
; max 10[bp]
|
|
; min 08[bp]
|
|
; bufsize 06[bp]
|
|
; buffadr 04[bp]
|
|
;
|
|
Public _mem_alloc
|
|
;---------
|
|
_mem_alloc:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,10[bp] ; Start with request maximum size
|
|
mem_all10:
|
|
mov ah,MS_M_ALLOC ; Attempt to allocate the maximum
|
|
int DOS_INT ; memory requested by the user.
|
|
jnc mem_all20 ; Allocation OK
|
|
cmp bx,08[bp] ; Is this less than the requested
|
|
jae mem_all10 ; No then allocate this amount
|
|
xor ax,ax ; Force the Buffer address and Buffer
|
|
mov bx,ax ; Size to Zero
|
|
|
|
mem_all20:
|
|
mov cx,bx ; Save the Buffer Size
|
|
mov bx,04[bp] ; Update the Buffer Address
|
|
mov word ptr 00[bx],0 ; Offset 0
|
|
mov word ptr 02[bx],ax ; Segment AX
|
|
mov bx,06[bp] ; Now Update the Buffer Size
|
|
mov word ptr 00[bx],cx ; and return to the caller
|
|
pop bp
|
|
ret
|
|
;
|
|
; mem_free(BYTE FAR * NEAR * bufaddr);
|
|
;
|
|
; buffadr 04[bp]
|
|
;
|
|
Public _mem_free
|
|
;---------
|
|
_mem_free:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
xor ax,ax
|
|
mov bx,04[bp] ; Get the Buffer Pointer address
|
|
xchg ax,word ptr 02[bx] ; and from this the segment of the
|
|
cmp ax,0 ; allocated memory. If the memory
|
|
jz mem_free10 ; has already been freed the quit
|
|
push es ; Otherwise Free the Memory
|
|
mov es,ax
|
|
mov ah,MS_M_FREE
|
|
int DOS_INT
|
|
pop es
|
|
mem_free10:
|
|
pop bp
|
|
ret
|
|
|
|
Public _msdos
|
|
;-------
|
|
_msdos:
|
|
;-------
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
push di
|
|
|
|
mov ah,4[bp]
|
|
mov dx,6[bp]
|
|
int DOS_INT
|
|
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
ret
|
|
|
|
Public _ioctl_ver
|
|
;---------
|
|
_ioctl_ver:
|
|
;---------
|
|
ifdef DOSPLUS
|
|
mov ax,4452h ; Get DOS Plus BDOS version Number
|
|
else
|
|
mov ax,4451h ; Get Concurrent BDOS Version
|
|
endif
|
|
int DOS_INT ; Real DOS returns with Carry Set
|
|
jc cdos_v10
|
|
and ax,not 0200h ; Reset the Networking Bit
|
|
ret
|
|
cdos_v10:
|
|
xor ax,ax
|
|
ret
|
|
|
|
ifdef DOSPLUS
|
|
;
|
|
; Get CodePage information form the system. Return both the currently
|
|
; active CodePage and the System CodePage.
|
|
;
|
|
; ms_x_getcp(&globalcp, &systemcp);
|
|
;
|
|
Public _ms_x_getcp
|
|
;-----------
|
|
_ms_x_getcp:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov ax,MS_X_GETCP ; Get the CodePage Information
|
|
int DOS_INT ; and return an error if not
|
|
jc ms_x_getcp10 ; supported.
|
|
mov ax,bx ; Now update the callers
|
|
mov bx,04[bp] ; Global and System Codepage
|
|
mov word ptr [bx],ax ; variables
|
|
mov bx,06[bp]
|
|
mov word ptr [bx],dx
|
|
xor ax,ax
|
|
|
|
ms_x_getcp10:
|
|
neg ax ; Negate the error code has
|
|
pop bp ; no effect on 0
|
|
ret
|
|
;
|
|
; Change the current CodePage
|
|
;
|
|
; ms_x_setcp(globalcp);
|
|
;
|
|
Public _ms_x_setcp
|
|
;-----------
|
|
_ms_x_setcp:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,04[bp] ; Get the requested CodePage
|
|
mov ax,MS_X_SETCP ; and make this the default
|
|
int DOS_INT
|
|
jc ms_x_getcp10
|
|
xor ax,ax
|
|
pop bp
|
|
ret
|
|
endif
|
|
endif
|
|
|
|
ifdef CDOSTMP
|
|
|
|
|
|
Public _ms_drv_set
|
|
;-----------
|
|
_ms_drv_set:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dl,04[bp] ; Get the Specified drive
|
|
or dl,80h ; Prevent any Select Errors
|
|
mov cl,DRV_SET ; and go select the bugger
|
|
int BDOS_INT
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_drv_get
|
|
;-----------
|
|
_ms_drv_get:
|
|
;-----------
|
|
mov cl,DRV_GET ; Return the Currently selected
|
|
int BDOS_INT ; disk drive
|
|
cbw
|
|
ret
|
|
|
|
Public _ms_drv_space
|
|
;------------
|
|
_ms_drv_space:
|
|
;------------
|
|
;
|
|
; ret = _ms_drv_space (drive, &free, &secsiz, &nclust);
|
|
; where: drive = 0, 1-16 is drive to use
|
|
; free = free cluster count
|
|
; secsiz = bytes/sector
|
|
; nclust = clusters/disk
|
|
; ret = sectors/cluster -or- (0xFFFFh)
|
|
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC, FD_DISKINFO
|
|
mov ax,04[bp]
|
|
mov FD_DRIVE,ax
|
|
call fdos_entry
|
|
or ax,ax ; Check for Errors
|
|
mov ax,0FFFFh
|
|
jnz ms_drv_exit ; Error Exit
|
|
|
|
push es ; Save ES
|
|
push di
|
|
les di,FD_DPB ; Get the DPB Address
|
|
|
|
mov ax,es:DDSC_FREE[di] ; Get the number of free
|
|
mov bx,06[bp] ; clusters on the drive
|
|
mov [bx],ax
|
|
|
|
mov ax,es:DDSC_SECSIZE[di] ; Get the Physical Sector Size
|
|
mov bx,08[bp] ; in bytes
|
|
mov [bx],ax
|
|
|
|
mov ax,es:DDSC_NCLSTRS[di] ; Get the disk size in
|
|
mov bx,10[bp] ; clusters and save in DX
|
|
mov [bx],ax
|
|
|
|
mov al,es:DDSC_CLMSK[di] ; Get the sectors per Cluster -1
|
|
cbw ; and save in AX
|
|
inc ax
|
|
pop di
|
|
pop es
|
|
|
|
ms_drv_exit:
|
|
pop bp
|
|
CRET 8
|
|
|
|
Public _ms_s_country
|
|
;------------
|
|
_ms_s_country:
|
|
;------------
|
|
push bp
|
|
mov bp,sp
|
|
mov ax,04[bp] ; Get the data Block Offset
|
|
|
|
mov cd_country,0 ; Get the Current Country
|
|
mov cd_codepage,0 ; Current CodePage
|
|
mov cd_table,0 ; Country Information
|
|
mov cd_offset,ax ; Save the Buffer Offset
|
|
mov cd_segment,ds ; and the Buffer Segment
|
|
|
|
mov dx,dataOFFSET country_data
|
|
mov cl,S_GETCOUNTRY ; Get the country information
|
|
int BDOS_INT ; and return the current country
|
|
pop bp ; code to the caller
|
|
CRET 2
|
|
|
|
Public _ms_x_mkdir
|
|
;----------
|
|
_ms_x_mkdir:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_MKDIR ; Make Directory
|
|
|
|
mkdir_10:
|
|
mov ax,04[bp]
|
|
mov FD_NAMEOFF,ax
|
|
mov FD_NAMESEG,ds
|
|
call fdos_entry
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_x_rmdir
|
|
;----------
|
|
_ms_x_rmdir:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_RMDIR
|
|
jmp mkdir_10
|
|
|
|
Public _ms_x_chdir
|
|
;----------
|
|
_ms_x_chdir:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_CHDIR
|
|
jmp mkdir_10
|
|
|
|
Public _ms_x_creat
|
|
;----------
|
|
_ms_x_creat:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_CREAT
|
|
jmp ms_open_creat
|
|
|
|
|
|
Public _ms_x_open
|
|
;---------
|
|
_ms_x_open:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_OPEN
|
|
ms_open_creat:
|
|
mov ax,4[bp]
|
|
mov FD_NAMEOFF,ax
|
|
mov FD_NAMESEG,ds
|
|
mov ax,6[bp] ; get mode for new file (CREAT)
|
|
mov FD_MODE,ax ; or the OPEN mode
|
|
call fdos_entry ; Call the FDOS and return either
|
|
pop bp ; a handle or error code
|
|
CRET 4
|
|
|
|
Public _ms_x_close
|
|
;----------
|
|
_ms_x_close:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov ax,4[bp] ; get the open handle
|
|
mov FD_FUNC,FD_CLOSE
|
|
mov FD_HANDLE,ax
|
|
call fdos_entry
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_x_unique
|
|
;----------
|
|
_ms_x_unique:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_MKTEMP
|
|
jmp ms_open_creat
|
|
|
|
Public _ms_x_fdup
|
|
;----------
|
|
_ms_x_fdup:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_FDUP
|
|
mov ax,4[bp] ; get the destination handle
|
|
mov FD_NEWHND,ax
|
|
mov ax,6[bp] ; Get the current handle
|
|
mov FD_HANDLE,ax
|
|
call fdos_entry
|
|
pop bp
|
|
CRET 4
|
|
|
|
Public _far_read
|
|
;---------
|
|
_far_read:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_READ
|
|
jmp far_read_write
|
|
|
|
Public _far_write
|
|
;----------
|
|
_far_write:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_WRITE
|
|
|
|
far_read_write:
|
|
mov ax,4[bp] ; get file handle
|
|
mov FD_HANDLE,ax
|
|
mov ax,6[bp] ; get buffer offset address
|
|
mov FD_BUFOFF,ax
|
|
mov ax,8[bp] ; get buffer Segment address
|
|
mov FD_BUFSEG,ax
|
|
mov ax,10[bp] ; get byte count
|
|
mov FD_COUNT,ax
|
|
call fdos_entry
|
|
or ax,ax
|
|
jnz far_rw_fail
|
|
mov ax,FD_COUNT ; Get the Byte Count
|
|
far_rw_fail:
|
|
pop bp
|
|
CRET 6
|
|
|
|
Public _ms_x_read
|
|
;---------
|
|
_ms_x_read:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_READ
|
|
jmp ms_read_write
|
|
|
|
Public _ms_x_write
|
|
;----------
|
|
_ms_x_write:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_WRITE
|
|
|
|
ms_read_write:
|
|
mov ax,4[bp] ; get file handle
|
|
mov FD_HANDLE,ax
|
|
mov ax,6[bp] ; get buffer address
|
|
mov FD_BUFOFF,ax
|
|
mov FD_BUFSEG,ds
|
|
mov ax,8[bp] ; get byte count
|
|
mov FD_COUNT,ax
|
|
call fdos_entry
|
|
or ax,ax
|
|
jnz ms_rw_fail
|
|
mov ax,FD_COUNT ; Get the Byte Count
|
|
ms_rw_fail:
|
|
pop bp
|
|
CRET 6
|
|
|
|
Public _ms_x_unlink
|
|
;-----------
|
|
_ms_x_unlink:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_UNLINK
|
|
jmp mkdir_10
|
|
|
|
|
|
Public _ms_x_lseek
|
|
;----------
|
|
_ms_x_lseek:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_LSEEK ; get the function
|
|
mov ax,4[bp] ; get the file handle
|
|
mov FD_HANDLE,ax
|
|
mov ax,6[bp] ; get the offset
|
|
mov word ptr FD_OFFSET+0,ax
|
|
mov ax,8[bp]
|
|
mov word ptr FD_OFFSET+2,ax
|
|
mov ax,10[bp] ; get the seek mode
|
|
mov FD_METHOD,ax
|
|
call fdos_entry
|
|
cwd
|
|
or ax,ax
|
|
jnz ms_lseek_fail ; skip if errors
|
|
mov ax,word ptr FD_OFFSET+0 ; Return the New Location
|
|
mov dx,word ptr FD_OFFSET+2
|
|
ms_lseek_fail:
|
|
mov bx,dx ; AX:BX = DRC long return
|
|
pop bp
|
|
CRET 8
|
|
|
|
|
|
Public _ms_x_ioctl
|
|
;----------
|
|
_ms_x_ioctl:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov ax,4[bp] ; get Enquiry Handle
|
|
mov FD_FUNC,FD_IOCTL ; Use the IOCTL function
|
|
mov FD_HANDLE,ax ; For Handle AX
|
|
mov FD_CTLFUNC,0000 ; Get the Handle Status
|
|
mov FD_CTLSTAT,0 ; Invalidate CTLSTAT
|
|
call fdos_entry ; Call the FDOS
|
|
mov ax,FD_CTLSTAT ; and return the STATUS
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_x_setdev
|
|
;------------
|
|
_ms_x_setdev:
|
|
;------------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov ax,4[bp] ; get Handle
|
|
mov FD_HANDLE,ax
|
|
mov FD_FUNC,FD_IOCTL ; Use the IOCTL function
|
|
mov FD_CTLFUNC,1 ; Set device info
|
|
mov ax, 6[bp] ; status to set
|
|
sub ah, ah
|
|
mov FD_CTLSTAT,ax
|
|
call fdos_entry ; Call the FDOS
|
|
mov ax,FD_CTLSTAT ; and return the STATUS
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_x_chmod
|
|
;----------
|
|
_ms_x_chmod: ; ms_x_chmod(path, attrib, get/set)
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_CHMOD
|
|
mov ax,4[bp] ; Get the FileName
|
|
mov FD_NAMEOFF,ax
|
|
mov FD_NAMESEG,ds
|
|
mov ax,6[bp] ; Get the Required Attributes
|
|
mov FD_ATTRIB,ax
|
|
mov ax,8[bp] ; Finally Get the GET/SET flag
|
|
mov FD_FLAG,ax
|
|
call fdos_entry ; Returns with AX equal to the
|
|
or ax,ax ; error code or with the file
|
|
js chmod10 ; attributes.
|
|
mov ax,FD_ATTRIB
|
|
chmod10:
|
|
pop bp
|
|
CRET 6
|
|
|
|
|
|
Public _ms_x_curdir
|
|
;-----------
|
|
_ms_x_curdir:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_GETDIR
|
|
mov ax,04[bp] ; Get the drive
|
|
mov FD_DRIVE,ax
|
|
mov bx,06[bp] ; and then the path
|
|
mov byte ptr [bx],0 ; Put a Zero byte in the buffer in
|
|
mov FD_PATHOFF,bx ; case the command fails and the
|
|
mov FD_PATHSEG,ds ; user selects the FAIL Option
|
|
call fdos_entry
|
|
pop bp
|
|
CRET 4
|
|
|
|
;
|
|
; ms_x_expand(dstbuf, srcbuf) returns the full path of SRCBUF
|
|
;
|
|
Public _ms_x_expand
|
|
;-----------
|
|
_ms_x_expand:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_EXPAND
|
|
mov ax,06[bp] ; Get Source Buffer Offset
|
|
mov FD_ONAMEOFF,ax
|
|
mov FD_ONAMESEG,ds
|
|
mov bx,04[bp] ; Get the destination string
|
|
mov byte ptr [bx],0 ; address and force it to be a NULL
|
|
mov FD_NNAMEOFF,bx ; terminated string in case of errors
|
|
mov FD_NNAMESEG,ds
|
|
call fdos_entry
|
|
pop bp
|
|
CRET 4
|
|
|
|
Public _ms_x_wait
|
|
;---------
|
|
_ms_x_wait: ; retrieve child return code
|
|
;---------
|
|
mov cl,P_EXITCODE ; Return the Exit Code
|
|
mov dx,0FFFFh ; Get the Exit Code
|
|
int BDOS_INT
|
|
CRET 0
|
|
|
|
Public _ms_x_first
|
|
;----------
|
|
_ms_x_first:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
|
|
mov dx,8[bp] ; get DMA buffer address
|
|
mov cl,F_DMAOFF
|
|
call bdos_entry
|
|
|
|
mov dx,ds ;##jc##
|
|
mov cl,F_DMASEG ;##jc##
|
|
call bdos_entry ;##jc##
|
|
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
|
|
mov FD_FUNC,FD_FFIRST ; Search First
|
|
mov ax,04[bp] ; Get the FileName
|
|
mov FD_NAMEOFF,ax
|
|
mov FD_NAMESEG,ds
|
|
mov ax,06[bp] ; Get the Attributes
|
|
mov FD_ATTRIB,ax
|
|
mov FD_COUNT, 0 ; Search for a File at a time
|
|
call fdos_entry
|
|
cmp ax,1 ; Did we match 1 entry
|
|
jnz ms_x_f10 ; No so return Error Code
|
|
mov ax,0 ; Return Zero on sucess
|
|
ms_x_f10:
|
|
pop bp
|
|
CRET 6
|
|
|
|
Public _ms_x_next
|
|
;---------
|
|
_ms_x_next:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
|
|
mov dx,4[bp] ; get DMA buffer address
|
|
mov cl,F_DMAOFF
|
|
call bdos_entry
|
|
|
|
mov dx,ds ;##jc##
|
|
mov cl,F_DMASEG ;##jc##
|
|
call bdos_entry ;##jc##
|
|
|
|
mov al,OK_RF ; Retry or Fail
|
|
call fdos_retry
|
|
|
|
mov FD_FUNC,FD_FNEXT ; Search Next
|
|
mov FD_NEXTCNT, 0 ; Search for a File at a time
|
|
call fdos_entry
|
|
cmp ax,1 ; Did we match 1 entry
|
|
jnz ms_x_n0 ; No so return Error Code
|
|
mov ax,0 ; Return Zero on sucess
|
|
ms_x_n0:
|
|
pop bp
|
|
CRET 2
|
|
|
|
|
|
Public _ms_x_rename
|
|
;-----------
|
|
_ms_x_rename:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_RENAME
|
|
mov ax,04[bp] ; Get the Old Name
|
|
mov FD_ONAMEOFF,ax
|
|
mov FD_ONAMESEG,ds
|
|
mov ax,06[bp] ; Get the New Name
|
|
mov FD_NNAMEOFF,ax
|
|
mov FD_NNAMESEG,ds
|
|
call fdos_entry
|
|
pop bp
|
|
CRET 4
|
|
|
|
Public _ms_x_datetime
|
|
;-------------
|
|
_ms_x_datetime: ; ms_x_datetime (gsflag, h, &time, &date);
|
|
;-------------
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RIF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov FD_FUNC,FD_DATETIME ; set/get Time Stamp
|
|
mov ax,4[bp] ; get/set subfunction (0/1)
|
|
mov FD_SFLAG,ax
|
|
mov ax,6[bp] ; get handle
|
|
mov FD_HANDLE,ax
|
|
mov bx,8[bp] ; get address of time
|
|
mov ax,[bx] ; get time
|
|
mov FD_TIME,ax ; and Save
|
|
mov bx,10[bp] ; get address of date
|
|
mov ax,[bx] ; get date
|
|
mov FD_DATE,ax
|
|
call fdos_entry
|
|
or ax,ax ; Skip if Failed
|
|
jnz ms_dt_ret
|
|
mov ax,FD_TIME
|
|
mov bx,8[bp] ; get time address
|
|
mov [bx],ax ; update time
|
|
mov ax,FD_DATE
|
|
mov bx,10[bp] ; get date address
|
|
mov [bx],ax ; update date
|
|
xor ax,ax
|
|
ms_dt_ret:
|
|
pop bp
|
|
CRET 8
|
|
|
|
|
|
;
|
|
; The following routines allow COMMAND.COM to manipulate
|
|
; the system time and date. Four functions are provided and
|
|
; these are GETDATE, SETDATE, GETTIME and SETTIME
|
|
;
|
|
; Date information is passed and return in a structure which
|
|
; has the following format.
|
|
;
|
|
; WORD Year (1980 - 2099)
|
|
; BYTE Month
|
|
; BYTE Day
|
|
; BYTE Day of the Week (Ignored on SET DATE)
|
|
|
|
Public _ms_getdate
|
|
;-----------
|
|
_ms_getdate:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,04[bp] ; Get the structure address
|
|
mov cl,T_GETDATE ; and call the BDOS
|
|
call bdos_entry
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_setdate
|
|
;----------
|
|
_ms_setdate:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp] ; and get the structure address
|
|
mov cl,T_SETDATE ; and call the BDOS to do the work
|
|
call bdos_entry ; Return 0 Good and FFFF Bad
|
|
pop bp
|
|
CRET 2
|
|
|
|
|
|
; Time information is passed and return in a structure which
|
|
; has the following format.
|
|
;
|
|
; BYTE Hours (0 - 23)
|
|
; BYTE Minutes (0 - 59)
|
|
; BYTE Seconds (0 - 59)
|
|
; BYTE Hundredths of a second (0 - 99)
|
|
|
|
Public _ms_gettime
|
|
;----------
|
|
_ms_gettime:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,04[bp] ; Get the Time Structure address
|
|
mov cl,T_GETTIME ; and call the OS
|
|
call bdos_entry
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_settime
|
|
;----------
|
|
_ms_settime:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp] ; and get the structure address
|
|
mov cl,T_SETTIME ; and call the BDOS SET Time Function
|
|
call bdos_entry ; Return 0 Good and FFFF Bad
|
|
pop bp
|
|
CRET 2
|
|
|
|
Public _ms_f_verify
|
|
;-----------
|
|
_ms_f_verify:
|
|
;-----------
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
mov ax,04[bp] ; Get the required state
|
|
les bx,_pd ; Update the Verify flag in
|
|
and es:P_SFLAG[bx],not PSF_VERIFY ; current PD
|
|
or ax,ax ; Set the Flag
|
|
jz ms_fv10 ; No
|
|
or es:P_SFLAG[bx],PSF_VERIFY ; Flag set in PD
|
|
ms_fv10:
|
|
pop es
|
|
pop bp
|
|
ret
|
|
|
|
Public _ms_f_getverify
|
|
;--------------
|
|
_ms_f_getverify:
|
|
;--------------
|
|
push es
|
|
xor ax,ax ; Assume the flag is RESET
|
|
les bx,_pd ; now test the state of the
|
|
test es:P_SFLAG[bx],PSF_VERIFY ; flag in the current PD
|
|
jz ms_fgv10 ; Verify = OFF
|
|
inc ax ; Verify = ON
|
|
ms_fgv10:
|
|
pop es
|
|
ret
|
|
|
|
;
|
|
; mem_alloc(BYTE FAR * NEAR * bufaddr, UWORD * bufsize, UWORD min, UWORD max);
|
|
;
|
|
; max 10[bp]
|
|
; min 08[bp]
|
|
; bufsize 06[bp]
|
|
; buffadr 04[bp]
|
|
;
|
|
Public _mem_alloc
|
|
;---------
|
|
_mem_alloc:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
|
|
mov mpb_start,0
|
|
mov ax,08[bp] ; Get the Minimum and Maximum values
|
|
mov mpb_min,ax ; and fill in the parameter block
|
|
mov ax,10[bp]
|
|
mov mpb_max,ax
|
|
mov mpb_pdadr,0
|
|
mov mpb_flags,0
|
|
|
|
mov cx,M_ALLOC ; Call the Concurrent Allocate function
|
|
mov dx,dataOFFSET mpb_start ;
|
|
call bdos_entry
|
|
xor cx,cx ; Assume that the function fails
|
|
mov dx,cx ; and zero the start and size fields
|
|
cmp ax,0
|
|
jnz mem_all10
|
|
mov cx,mpb_min ; Get the Allocation Size
|
|
mov dx,mpb_start ; and the starting segment
|
|
|
|
mem_all10:
|
|
mov bx,04[bp] ; Update the Buffer Address
|
|
mov word ptr 00[bx],0 ; Offset 0
|
|
mov word ptr 02[bx],dx ; Segment DX
|
|
mov bx,06[bp] ; Now Update the Buffer Size
|
|
mov word ptr 00[bx],cx ; and return to the caller
|
|
pop bp
|
|
ret
|
|
;
|
|
; mem_free(BYTE FAR * NEAR * bufaddr);
|
|
;
|
|
; buffadr 04[bp]
|
|
;
|
|
Public _mem_free
|
|
;---------
|
|
_mem_free:
|
|
;---------
|
|
push bp
|
|
mov bp,sp
|
|
xor ax,ax
|
|
mov bx,04[bp] ; Get the Buffer Pointer address
|
|
xchg ax,word ptr 02[bx] ; and from this the segment of the
|
|
cmp ax,0 ; allocated memory. If the memory
|
|
jz mem_free10 ; has already been freed the quit
|
|
mov mfpb_start,ax ; Otherwise Free the Memory
|
|
mov mfpb_res,0
|
|
mov cx,M_FREE
|
|
mov dx,dataOFFSET mfpb_start
|
|
call bdos_entry
|
|
|
|
mem_free10:
|
|
pop bp
|
|
ret
|
|
;
|
|
; findfile(BYTE *loadpath, UWORD *loadtype)
|
|
;
|
|
Public _findfile
|
|
_findfile:
|
|
push bp
|
|
mov bp,sp
|
|
mov al,OK_RF ; Retry, Ignore or Fail
|
|
call fdos_retry
|
|
mov ax,word ptr 04[bp]
|
|
mov exec_pathoff,ax
|
|
mov exec_pathseg,ds
|
|
mov cx,P_PATH
|
|
mov dx,dataOFFSET exec_block
|
|
call ppath_entry
|
|
or ax,ax
|
|
jnz ff_error
|
|
mov al,exec_filetype
|
|
cbw
|
|
mov bx,word ptr 06[bp]
|
|
mov word ptr [bx],ax
|
|
xor ax,ax
|
|
ff_error:
|
|
pop bp
|
|
ret
|
|
|
|
;
|
|
fdos_retry:
|
|
xor ah,ah
|
|
mov valid,ax ; Save the Valid Error responses
|
|
pop retry_ip ; Get the return Address
|
|
mov retry_sp,sp ; and Stack Pointer
|
|
jmp retry_ip
|
|
;
|
|
; FDOS_ENTRY is an internal function entry point which makes the
|
|
; F_DOS function call. As the F_DOS data area used by COMMAND.COM
|
|
; is always FDOS_DATA.
|
|
;
|
|
; WORD PASCAL critical_error(error, valid, drive, mode, server);
|
|
;
|
|
; critical_error will return an WORD response which (R,I,A,F)
|
|
; after displaying the appropriate error message and get the
|
|
; correct response from the user.
|
|
;
|
|
fdos_entry:
|
|
mov cl,F_DOS
|
|
mov dx,dataOFFSET fdos_data
|
|
ppath_entry:
|
|
call bdos_entry
|
|
cmp ax,ED_LASTERROR ; Did an Error Occur
|
|
jb fdos_exit ; No So Exit OK
|
|
cmp crit_flg,TRUE ; Already in handler
|
|
jz fdos_exit ; Yes Skip Critical Error
|
|
cmp ax,ED_PROTECT ; Is this a Physical Error
|
|
jg fdos_exit ; if so then simulate a
|
|
cmp ax,ED_GENFAIL ; Critical Error by calling
|
|
jge fdos_e05 ; the COMMAND routine Critical
|
|
; error
|
|
cmp ax,ED_NETPWD ; Now check for DR-NET errors
|
|
jg fdos_exit ; if so then simulate a
|
|
cmp ax,ED_NETLOG ; Critical Error by calling
|
|
jge fdos_e05 ; the COMMAND routine Critical
|
|
; error
|
|
fdos_exit:
|
|
ret
|
|
|
|
fdos_e05:
|
|
push retry_ip ; Save Retry IP and SP and valid
|
|
push retry_sp ; responses
|
|
push valid
|
|
mov crit_flg,TRUE ; Start Critical Section
|
|
mov cx,es ; Save the Segment Regsiter
|
|
push ax ; Save the Error Code
|
|
push valid ; Save the Valid Responses (R,I,F)
|
|
les bx,_pd ; Get the PD address
|
|
mov es,es:P_UDA[bx] ; and then the UDA address
|
|
xor ah,ah ; Zero the top byte of AX and
|
|
mov al,es:byte ptr 15h ;;U_ERR_DRV ; Get the Failing Drive
|
|
push ax ; Save on the Stack
|
|
mov al,es:byte ptr 14h ;;U_ERR_RW ; Get the Error Mode
|
|
push ax ; and Save
|
|
|
|
mov ax,00FFH ; Default Server NO is (INVALID)
|
|
les bx,_pd ; Get the PD address Again
|
|
mov bx,es:P_NDA[bx] ; and then the NDA address
|
|
cmp bx,0 ; Are we attached to DR-NET
|
|
jz fdos_e08 ; NO
|
|
mov es,bx ; ES -> DR-Net NDA
|
|
mov al,es:byte ptr 0Ch ;; NDA_CXRTN
|
|
|
|
fdos_e08:
|
|
push ax ; Pass the DR-NET Server No.
|
|
mov es,cx ; Restore ES
|
|
call CRITICAL_ERR ; Handle the Critical Error. Parameters
|
|
; are removed by the CALLEE
|
|
mov crit_flg,FALSE ; Critical Section complete
|
|
pop valid ; Restore our original RETRY IP
|
|
pop retry_sp ; and SP values which have been
|
|
pop retry_ip ; corrupted by the "CRITICAL_ERROR"
|
|
; routine during message printing
|
|
cmp ax,0 ; Ignore the Error
|
|
jz fdos_exit ; Then Exit with no Error
|
|
|
|
cmp ax,1 ; Retry the Operation
|
|
jnz fdos_e10 ; using information saved by FDOS_RETRY
|
|
mov sp,retry_sp ; Reset the Stack Pointer
|
|
jmp retry_ip ; and retry the Operation
|
|
|
|
fdos_e10:
|
|
cmp ax,3 ; FAIL this function
|
|
mov ax,ED_FAIL ; Fail the function
|
|
jz fdos_exit ; Yes otherwise ABORT
|
|
|
|
call _int_break ; Simulate a Control C to terminate
|
|
; We are never coming back
|
|
;
|
|
; BDOS_ENTRY is the usual method of calling the Operating System.
|
|
; In order to provide a DOS compatible environment this function.
|
|
; does Control-C checking on function exit.
|
|
;
|
|
bdos_entry:
|
|
int BDOS_INT
|
|
push es
|
|
les bx,_pd ; Get our process descriptor address
|
|
test es:P_SFLAG[bx],PSF_CTLC ; Check if a Control-C has been typed
|
|
jnz bdos_e10 ; Jump to Abort Handler
|
|
mov bx,ax ; Restore BX and Return.
|
|
pop es
|
|
ret
|
|
|
|
bdos_e10:
|
|
and es:P_SFLAG[bx],not PSF_CTLC
|
|
pop es
|
|
bdos_e20:
|
|
mov cl,C_RAWIO ; Flush the Character buffer until
|
|
mov dl,0FFh ; Return the character or 00 if queue
|
|
int BDOS_INT ; is empty. Repeat till the Keyboard
|
|
or al,al ; Buffer has been flushed
|
|
jnz bdos_e20
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
mov cl,C_WRITESTR
|
|
mov dx,offset break_str ; echo ^C to screen
|
|
int BDOS_INT
|
|
pop ds
|
|
call _int_break ; Place the Control Break Code on the
|
|
; Stack and the call the error handler
|
|
; ** We will never return **
|
|
|
|
break_str db '^C$'
|
|
|
|
endif
|
|
|
|
ifndef DOSPLUS
|
|
Public __BDOS
|
|
;-------
|
|
__BDOS:
|
|
;-------
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
push di
|
|
mov cl,4[bp]
|
|
mov dx,6[bp]
|
|
int BDOS_INT
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
ret
|
|
;
|
|
endif
|
|
|
|
ifdef DOSPLUS
|
|
ifndef EXT_SUBST
|
|
Public _physical_drvs ; Physical Drives returns a LONG
|
|
_physical_drvs: ; Vector with bits set for every drive
|
|
mov ax,0 ; start with drive A:
|
|
mov cx,16 ; check the first 16 drives
|
|
mov bx,0
|
|
p_d10:
|
|
push ax ; pass drive no. to _physical_drive
|
|
call _physical_drive ; call it
|
|
cmp ax,0 ; check return value
|
|
pop ax ; restore ax
|
|
jz p_d20 ; if zero skip setting the bit in
|
|
or bx,1 ; the bitmap
|
|
p_d20:
|
|
ror bx,1 ; shift bitmap right
|
|
inc ax ; next drive
|
|
loop p_d10 ; Loop 16 Times
|
|
mov cx,10 ; Finally check the last 10 drives
|
|
mov dx,0
|
|
p_d30:
|
|
push ax ; pass drive no. to _physical_drive
|
|
call _physical_drive ; call it
|
|
cmp ax,0 ; check return val
|
|
pop ax ; restore ax
|
|
jz p_d40 ; id zero skip setting the bit in
|
|
or dx,1 ; the bitmap
|
|
p_d40:
|
|
ror dx,1 ; shift bitmap right
|
|
inc ax ; next drive
|
|
loop p_d30 ; Loop 10 Times
|
|
|
|
mov cl,6 ; Now rotate the contents of
|
|
ror dx,cl ; DX 6 more times for correct
|
|
; alignment of the Physical Drive Vector
|
|
mov ax,bx
|
|
mov bx,dx ; Return the long value in both
|
|
; AX:BX and AX:DX
|
|
ret
|
|
|
|
Public _logical_drvs ; Logical Drives returns a LONG
|
|
_logical_drvs: ; vector with bits set for every
|
|
|
|
mov cx,16 ; check the first 16 drives
|
|
mov ax,0 ; start with drive A:
|
|
mov bx,ax
|
|
|
|
l_d10:
|
|
push ax ; pass the drive to _logical_drive
|
|
call _logical_drive ; call it
|
|
cmp ax,0 ; check return value
|
|
pop ax ; restore ax
|
|
jz l_d20 ; skip if zero return
|
|
or bx,1 ; set bit in bitmap
|
|
l_d20:
|
|
ror bx,1 ; shift bitmap right
|
|
inc ax ; next drive
|
|
loop l_d10 ; Loop 16 Times
|
|
|
|
mov cx,10 ; Finally check the last 10 drives
|
|
mov dx,0
|
|
l_d30:
|
|
push ax ; pass the drive to _logical_drive
|
|
call _logical_drive ; call it
|
|
cmp ax,0 ; check return value
|
|
pop ax ; restore ax
|
|
jz l_d40 ; skip if zero return
|
|
or dx,1 ; set bit in bitmap
|
|
l_d40:
|
|
ror dx,1 ; shift bitmap right
|
|
inc ax ; next drive
|
|
loop l_d30 ; Loop 10 Times
|
|
|
|
mov cl,6 ; Now rotate the contents of
|
|
ror dx,cl ; DX 6 more times for correct
|
|
; alignment of bits
|
|
mov ax,bx
|
|
mov bx,dx ; Return the long value in both
|
|
ret ; AX:BX and AX:DX
|
|
|
|
Public _network_drvs ; Network Drives returns a LONG
|
|
_network_drvs: ; vector with bits set for every drive
|
|
xor ax,ax ; Start with BX:AX as
|
|
mov bx,ax ; zeros.
|
|
mov cx,'Z'-'A' ; We look at drives A-Z
|
|
n_d10:
|
|
add ax,ax ; we move the dword vector
|
|
adc bx,bx ; one place left
|
|
push ax
|
|
push bx ; save the vector
|
|
mov ah,MS_X_IOCTL
|
|
mov al,9 ; is device local ?
|
|
mov bl,cl ; drive number in BL
|
|
int DOS_INT
|
|
pop bx
|
|
pop ax ; recover the vector
|
|
jc n_d20 ; if an error skip network bit
|
|
test dx,1000h ; is device local ?
|
|
jz n_d20 ; if not then
|
|
or ax,1 ; set bit for this drive
|
|
n_d20:
|
|
loop n_d10
|
|
mov dx,bx ; long value in both AX:BX and AX:DX
|
|
ret
|
|
public _physical_drive
|
|
_physical_drive PROC NEAR
|
|
|
|
; BOOLEAN physical_drive(WORD);
|
|
; returns true if given drive (0-25) is physical.
|
|
;
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
push es
|
|
push si
|
|
push di
|
|
push dx
|
|
push cx
|
|
push bx
|
|
|
|
mov bx,4[bp] ; get the drive number
|
|
inc bx ; A=1, B=2, etc
|
|
mov ax,4409h ; IOCTL Network/Local
|
|
int 21h ; do it
|
|
jc not_phys ; carry means invalid drive
|
|
and dx,1000h ;
|
|
cmp dx,0
|
|
jne not_phys ; its a network drive
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov si,offset func60_in
|
|
mov di,offset func60_out
|
|
mov ax,4[bp] ; insert drive letter in input string
|
|
add al,'A'
|
|
mov [si],al ;
|
|
mov ah,60h ; Expand Path string
|
|
int 21h ; do it
|
|
jc not_phys ; carry set means invalid drive
|
|
|
|
mov ax,4[bp] ; if drive letter changes then drive is
|
|
add al,'A' ; substed
|
|
cmp al,cs:[func60_out]
|
|
jne not_phys
|
|
|
|
mov ax,-1
|
|
jmp phys_exit
|
|
not_phys:
|
|
mov ax,0
|
|
phys_exit:
|
|
pop bx
|
|
pop cx
|
|
pop dx
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop ds
|
|
pop bp
|
|
ret
|
|
|
|
func60_in db "d:con",0
|
|
func60_out db 0,0,0,0,0,0,0,0,0,0
|
|
|
|
_physical_drive ENDP
|
|
|
|
;
|
|
; This function translates a logical to physical drive.
|
|
;
|
|
Public _pdrive
|
|
;------
|
|
_pdrive:
|
|
;------
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov si,offset func60_in
|
|
mov di,offset func60_out
|
|
mov ax,4[bp] ; insert drive letter in input string
|
|
add al,'A'
|
|
mov [si],al
|
|
mov ah,60h ; Expand Path string
|
|
int 21h ; do it
|
|
mov ax,4[bp] ; assume invalid, hence no change
|
|
jc pdrive_exit ; carry set means invalid drive
|
|
mov al,cs:[func60_out]
|
|
sub al,'A'
|
|
pdrive_exit:
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop ds
|
|
pop bp
|
|
CRET 2
|
|
|
|
public _logical_drive
|
|
_logical_drive PROC NEAR
|
|
|
|
; BOOLEAN logical_drive(WORD);
|
|
; returns TRUE if given drive (0-25) is logical
|
|
;
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
push es
|
|
push si
|
|
push di
|
|
push dx
|
|
push cx
|
|
push bx
|
|
|
|
mov bx,4[bp] ; get the drive number
|
|
inc bx ; A=1, B=2, etc
|
|
mov ax,4409h ; IOCTL Network/Local
|
|
int 21h ; do it
|
|
jc not_logical ; carry means invalid drive
|
|
and dx,1000h ;
|
|
cmp dx,0
|
|
jne not_logical ; its a network drive
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov si,offset func60_in
|
|
mov di,offset func60_out
|
|
mov ax,4[bp] ; insert drive letter in input string
|
|
add al,'A'
|
|
mov [si],al ;
|
|
mov ah,60h ; Expand Path string
|
|
int 21h ; do it
|
|
jc not_logical ; carry set means invalid drive
|
|
|
|
mov ax,4[bp] ; if drive letter changes then drive is
|
|
add al,'A' ; substed
|
|
cmp al,cs:[func60_out]
|
|
je not_logical
|
|
|
|
mov ax,-1
|
|
jmp logical_exit
|
|
not_logical:
|
|
mov ax,0
|
|
logical_exit:
|
|
pop bx
|
|
pop cx
|
|
pop dx
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop ds
|
|
pop bp
|
|
ret
|
|
|
|
_logical_drive ENDP
|
|
|
|
public _network_drive
|
|
_network_drive PROC NEAR
|
|
|
|
; BOOLEAN network_drive(WORD);
|
|
; returns TRUE if given drive (0-25) is networked
|
|
;
|
|
push bp
|
|
mov bp,sp
|
|
push dx
|
|
push cx
|
|
push bx
|
|
|
|
mov bx,4[bp] ; get the drive number
|
|
inc bx ; A=1, B=2, etc
|
|
mov ax,4409h ; IOCTL Network/Local
|
|
int 21h ; do it
|
|
jc not_networked ; carry means invalid drive
|
|
and dx,1000h ;
|
|
cmp dx,0
|
|
jne not_networked ; its a network drive
|
|
|
|
mov ax,-1
|
|
jmp network_exit
|
|
not_networked:
|
|
mov ax,0
|
|
network_exit:
|
|
pop bx
|
|
pop cx
|
|
pop dx
|
|
pop bp
|
|
ret
|
|
|
|
_network_drive ENDP
|
|
|
|
endif ;EXT_SUBST
|
|
|
|
else ;!DOSPLUS
|
|
|
|
Public _physical_drvs ; Physical Drives returns a LONG
|
|
_physical_drvs: ; Vector with bits set for every
|
|
mov cx,DRV_LOGINVEC ; Physical or Networked Drive
|
|
int BDOS_INT ; attached to the system
|
|
xor dx,dx ; Return the LONG value in both
|
|
mov bx,dx ; AX:DX and AX:BX for maximum
|
|
ret ; compatibility
|
|
|
|
Public _network_drvs ; Network Drives returns a LONG
|
|
_network_drvs: ; vector with bits set for every
|
|
push es ; physical drive which has been
|
|
mov ax,0 ; mapped to a remote DRNET server
|
|
mov dx,ax
|
|
les bx,_pd ; Get Our Process Descriptor
|
|
mov cx,es:P_NDA[bx] ; and then the NDA Segment
|
|
jcxz n_d20 ; Skip Drive Test if no NDA
|
|
mov es,cx ; Get the RCT Address
|
|
les bx,es:dword ptr 04h ;; NDA_RCT ; From the NDA
|
|
mov cx,16
|
|
n_d10:
|
|
test es:RCT_DSK[bx],080h ; Is this a Remote drive
|
|
jz n_d15 ; No
|
|
or ax,1 ; Set Drive Bit
|
|
n_d15:
|
|
ror ax,1 ; Rotate Drive Bit Vector
|
|
add bx,2 ; Update the Drive Pointer
|
|
loop n_d10 ; Loop Till Done
|
|
n_d20:
|
|
mov bx,dx ; Return the long value in both
|
|
pop es ; AX:BX and AX:DX
|
|
ret
|
|
|
|
ifndef EXT_SUBST
|
|
|
|
Public _logical_drvs ; Logical Drives returns a LONG
|
|
_logical_drvs: ; vector with bits set for every
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
les si,_pd ; Get Our Process Descriptor
|
|
mov si,es:P_CAT[si] ; and then the address of the
|
|
mov cx,16 ; first HDS and check the first
|
|
mov ax,0 ; 16 Drives
|
|
mov bx,ax
|
|
|
|
l_d10:
|
|
mov di,es:word ptr [si] ; Has this drive got an HDS
|
|
test di,di ; then skip setting the bit in
|
|
jz l_d20 ; the vector register
|
|
cmp es:byte ptr [di],bl ; Is the HDS pointing to same drive
|
|
jz l_d20 ; Yes then this is a Physical Drive
|
|
or ax,1
|
|
l_d20:
|
|
ror ax,1
|
|
add si,2
|
|
inc bx
|
|
loop l_d10 ; Loop 16 Tines
|
|
|
|
mov cx,10 ; Finally check the last 10 HDS
|
|
mov dx,0
|
|
l_d30:
|
|
mov di,es:word ptr [si] ; Has this drive got an HDS
|
|
test di,di ; then skip setting the bit in
|
|
jz l_d40 ; the vector register
|
|
cmp es:byte ptr [di],bl ; Is the HDS pointing to same drive
|
|
jz l_d40 ; Yes then this is a Physical Drive
|
|
or dx,1
|
|
l_d40:
|
|
ror dx,1
|
|
add si,2
|
|
inc bx
|
|
loop l_d30 ; Loop 10 Tines
|
|
|
|
mov cl,6 ; Now rotate the contents of
|
|
ror dx,cl ; DX 6 more times for correct
|
|
; alignment of bits
|
|
pop di
|
|
pop si
|
|
pop es
|
|
mov bx,dx ; Return the long value in both
|
|
ret ; AX:BX and AX:DX
|
|
|
|
|
|
;
|
|
; This function use the CONCURRENT 5.xx CP/M function to translate
|
|
; a logical to physical drive.
|
|
;
|
|
Public _pdrive
|
|
;------
|
|
_pdrive:
|
|
;------
|
|
push bp
|
|
mov bp,sp
|
|
mov dl,4[bp] ; get the logical drive
|
|
mov cl,175 ; Logical to Physical Xlat
|
|
int BDOS_INT
|
|
cbw
|
|
pop bp
|
|
CRET 2
|
|
|
|
endif ;!EXT_SUBST
|
|
endif ;!DOSPLUS
|
|
|
|
|
|
Public _toupper
|
|
|
|
UCASE equ 18 ; offset of dword ptr to uppercase func
|
|
|
|
;-------
|
|
_toupper proc near
|
|
;-------
|
|
; Return the uppercase equivilant of the given character.
|
|
; The uppercase function defined in the international info block is
|
|
; called for characters above 80h.
|
|
;
|
|
; char ch; char to be converted
|
|
; char result; uppercase equivilant of ch
|
|
;
|
|
; result = toupper(ch);
|
|
|
|
push bp
|
|
mov bp, sp
|
|
|
|
mov ax, 4[bp]
|
|
mov ah, 0 ; al = character to be converted
|
|
cmp al, 'a' ; al < 'a'?
|
|
jb exit_toupper ; yes - done (char unchanged)
|
|
cmp al, 'z' ; al <= 'z'?
|
|
jbe a_z ; yes - do ASCII conversion
|
|
cmp al, 80h ; international char?
|
|
jb exit_toupper ; no - done (char unchanged)
|
|
|
|
; ch >= 80h -- call international routine
|
|
call dword ptr [_country+UCASE]
|
|
jmp exit_toupper
|
|
|
|
a_z:
|
|
; 'a' <= ch <= 'z' -- convert to uppercase ASCII equivilant
|
|
and al, 0DFh
|
|
|
|
exit_toupper:
|
|
pop bp
|
|
ret
|
|
|
|
_toupper endp
|
|
|
|
|
|
|
|
ifdef DOSPLUS
|
|
if 0
|
|
Public _hiload_status
|
|
;----------
|
|
_hiload_status:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,100h ; get hiload state
|
|
mov ax,(MS_X_IOCTL*256)+57h ; IO Control function
|
|
int DOS_INT ; do INT 21h
|
|
pop bp ;
|
|
ret
|
|
|
|
Public _hiload_set
|
|
;----------
|
|
_hiload_set:
|
|
;----------
|
|
push bp
|
|
mov bp,sp
|
|
mov dx,4[bp] ; get state
|
|
mov dh,2 ; set hiload state
|
|
mov ax,(MS_X_IOCTL*256)+57h ; IO Control function
|
|
int DOS_INT ; do INT 21h
|
|
pop bp ;
|
|
ret
|
|
endif
|
|
|
|
Public _get_upper_memory_link
|
|
_get_upper_memory_link:
|
|
|
|
mov ax,5802h
|
|
int 21h
|
|
cbw
|
|
ret
|
|
|
|
Public _set_upper_memory_link
|
|
_set_upper_memory_link:
|
|
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp]
|
|
mov ax,5803h
|
|
int 21h
|
|
pop bp
|
|
ret
|
|
|
|
Public _get_alloc_strategy
|
|
_get_alloc_strategy:
|
|
|
|
mov ax,5800h
|
|
int 21h
|
|
ret
|
|
|
|
Public _set_alloc_strategy
|
|
_set_alloc_strategy:
|
|
|
|
push bp
|
|
mov bp,sp
|
|
mov bx,4[bp]
|
|
mov ax,5801h
|
|
int 21h
|
|
pop bp
|
|
ret
|
|
|
|
Public _alloc_region
|
|
|
|
_alloc_region:
|
|
push es
|
|
xor ax,ax
|
|
mov es,ax ; assume no block allocated
|
|
mov ah,MS_M_ALLOC
|
|
mov bx,1
|
|
int 21h ; allocate a small block
|
|
jc _alloc_region10
|
|
mov es,ax
|
|
mov ah,MS_M_SETBLOCK
|
|
mov bx,0FFFFh
|
|
int 21h ; find out how big the block is
|
|
mov ah,MS_M_SETBLOCK
|
|
int 21h ; now grow to take up the block
|
|
_alloc_region10:
|
|
mov ax,es ; return address of block
|
|
pop es
|
|
ret
|
|
|
|
Public _free_region
|
|
|
|
_free_region:
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
mov es,4[bp]
|
|
mov ah,MS_M_FREE
|
|
int 21h ; free the block
|
|
pop es
|
|
pop bp
|
|
ret
|
|
|
|
endif
|
|
|
|
; The Double Byte Character Set lead byte table.
|
|
; Each entry in the table except the last specifies a valid lead byte range.
|
|
;
|
|
; 0 +---------------+---------------+
|
|
; | start of | end of | DBCS table entry 0
|
|
; | range 0 | range 0 |
|
|
; 2 +---------------+---------------+
|
|
; | start of | end of | DBCS table entry 1
|
|
; | range 1 | range 1 |
|
|
; +---------------+---------------+
|
|
; :
|
|
; n +---------------+---------------+
|
|
; | 0 | 0 | end of DBCS table
|
|
; | | |
|
|
; +---------------+---------------+
|
|
|
|
|
|
Public _dbcs_expected
|
|
|
|
_dbcs_expected proc near
|
|
;-------------
|
|
; Returns true if double byte characters are to be expected.
|
|
; A call to dbcs_init() MUST have been made.
|
|
; Entry
|
|
; none
|
|
; Exit
|
|
; ax = 1 - double byte characters are currently possible
|
|
; 0 - double byte characters are not currently possible
|
|
|
|
ifdef DOSPLUS
|
|
push ds
|
|
push si
|
|
lds si, dbcs_table_ptr ; DS:SI -> system DBCS table
|
|
lodsw ; ax = first entry in DBCS table
|
|
test ax, ax ; empty table?
|
|
jz de_exit ; yes - return 0 (not expected)
|
|
mov ax, 1 ; return 1 (yes you can expect DBCS)
|
|
de_exit:
|
|
pop si
|
|
pop ds
|
|
else
|
|
xor ax,ax ; CDOS doesn't support them
|
|
endif
|
|
ret
|
|
_dbcs_expected endp
|
|
|
|
|
|
Public _dbcs_lead
|
|
|
|
_dbcs_lead proc near
|
|
;---------
|
|
; Returns true if given byte is a valid lead byte of a 16 bit character.
|
|
; A call to init_dbcs() MUST have been made.
|
|
; Entry
|
|
; 2[bp] = possible lead byte
|
|
; Exit
|
|
; ax = 1 - is a valid lead byte
|
|
; 0 - is not a valid lead byte
|
|
|
|
ifdef DOSPLUS
|
|
push bp
|
|
mov bp, sp
|
|
push ds
|
|
push si
|
|
|
|
mov bx, 4[bp] ; bl = byte to be tested
|
|
lds si,dbcs_table_ptr ; ds:si -> system DBCS table
|
|
lodsw ; any entries ?
|
|
test ax,ax
|
|
jz dl_not_valid ; no DBC entries
|
|
|
|
dl_loop:
|
|
lodsw ; al/ah = start/end of range
|
|
test ax, ax ; end of table?
|
|
jz dl_not_valid ; yes - exit (not in table)
|
|
cmp al, bl ; start <= bl?
|
|
ja dl_loop ; no - try next range
|
|
cmp ah, bl ; bl <= end?
|
|
jb dl_loop ; no - try next range
|
|
|
|
mov ax, 1 ; return 1 - valid lead byte
|
|
|
|
dl_not_valid:
|
|
pop si
|
|
pop ds
|
|
pop bp
|
|
else
|
|
xor ax,ax ; CDOS doesn't support them
|
|
endif
|
|
ret
|
|
_dbcs_lead endp
|
|
|
|
|
|
PUBLIC _extended_error
|
|
_extended_error PROC NEAR
|
|
|
|
mov ah,59h
|
|
mov bx,0
|
|
int 21h
|
|
neg ax
|
|
ret
|
|
|
|
_extended_error ENDP
|
|
|
|
PUBLIC _get_lines_page
|
|
_get_lines_page PROC NEAR
|
|
|
|
push bp
|
|
push es
|
|
|
|
mov ax,1130h
|
|
mov bx,0
|
|
mov dx,24 ; preset dx to 24 in case function not supported
|
|
int 10h
|
|
|
|
mov ax,dx ; returns (no. rows)-1 in dx
|
|
inc ax
|
|
|
|
pop es
|
|
pop bp
|
|
ret
|
|
|
|
_get_lines_page ENDP
|
|
|
|
PUBLIC _get_scr_width
|
|
_get_scr_width PROC NEAR
|
|
|
|
push bp
|
|
mov ah,0fh
|
|
int 10h
|
|
xor al,al
|
|
xchg ah,al
|
|
pop bp
|
|
ret
|
|
|
|
_get_scr_width ENDP
|
|
|
|
PUBLIC _novell_copy
|
|
_novell_copy PROC NEAR
|
|
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
push di
|
|
|
|
mov ax,11f0h
|
|
mov si,4[bp] ; si = source handle
|
|
mov di,6[bp] ; di = destination handle
|
|
mov dx,8[bp] ; lo word of source length
|
|
mov cx,10[bp] ; hi word of source length
|
|
clc ; start with carry cleared
|
|
|
|
int 2fh ; do it
|
|
|
|
jc novcop_failure ; carry set means novell couldn't handle it
|
|
|
|
cmp ax,11f0h
|
|
je novcop_failure ; ax hasn't changed, so novell isn't there
|
|
|
|
mov ax,1 ; success !
|
|
jmp novcop_exit
|
|
|
|
novcop_failure:
|
|
mov ax,0
|
|
novcop_exit:
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
ret
|
|
|
|
_novell_copy ENDP
|
|
|
|
PUBLIC _call_novell
|
|
_call_novell PROC NEAR
|
|
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
mov ah,8[bp]
|
|
mov al,0ffh
|
|
push ds
|
|
pop es
|
|
mov si,4[bp]
|
|
mov di,6[bp]
|
|
int 21h
|
|
|
|
cmp al,0
|
|
jne call_nov_err
|
|
jc call_nov_err
|
|
|
|
mov ax,0
|
|
jmp call_nov_exit
|
|
|
|
call_nov_err:
|
|
mov ah,0 ;; clear ah, BUT allow all ret' values in al
|
|
call_nov_exit:
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop bp
|
|
ret
|
|
|
|
_call_novell ENDP
|
|
|
|
PUBLIC _nov_station
|
|
_nov_station PROC NEAR
|
|
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
|
|
mov ax,0eeffh
|
|
int 21h
|
|
cmp ax,0ee00h
|
|
je ns_err
|
|
|
|
mov si,4[bp]
|
|
mov [si],cx
|
|
mov 2[si],bx
|
|
mov 4[si],ax
|
|
mov ax,0
|
|
jmp ns_exit
|
|
|
|
ns_err:
|
|
mov ax,-1
|
|
|
|
ns_exit:
|
|
pop si
|
|
pop bp
|
|
ret
|
|
|
|
_nov_station ENDP
|
|
|
|
public _nov_connection
|
|
_nov_connection PROC NEAR
|
|
|
|
push es
|
|
push si
|
|
|
|
if 0
|
|
mov ax,0
|
|
mov es,ax
|
|
mov si,0
|
|
mov ax,0ef03h
|
|
int 21h
|
|
|
|
mov ax,es
|
|
cmp ax,0
|
|
jne nc_ok
|
|
cmp si,0
|
|
jne nc_ok
|
|
mov ax,-1
|
|
jmp nc_exit
|
|
|
|
nc_ok:
|
|
mov al,es:23[si]
|
|
mov ah,0
|
|
endif
|
|
|
|
mov ax,0dc00h
|
|
int 21h
|
|
jc nc_err
|
|
sub ah,ah
|
|
jmp nc_exit
|
|
|
|
nc_err:
|
|
mov al,-1;
|
|
|
|
nc_exit:
|
|
pop si
|
|
pop es
|
|
ret
|
|
|
|
_nov_connection ENDP
|
|
|
|
_TEXT ENDS
|
|
END
|