Files
DR-DOS-OpenDOS/IBMDOS/MISC.A86
2020-11-04 23:59:28 +01:00

1830 lines
46 KiB
Plaintext

; File : $MISC.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$
; MISC.A86 1.29 94/11/30 14:40:17
; fixed error return for function 6602
; MISC.A86 1.28 94/07/13 15:31:04
; Pass name to share on Int21/5D02 (close file by name)
; MISC.A86 1.27 93/11/29 14:18:16
; Fix bug in get extended country info if not current country
; MISC.A86 1.25 93/11/19 17:00:14
; If 21/38 get country info fails for current codepage, try any codepage
; MISC.A86 1.24 93/11/16 15:57:08
; int 21/5D06 clears CY flag
; MISC.A86 1.23 93/10/21 19:31:16
; Move Int 21/5D03+5D04 support (close all files by machine/psp) into share
; MISC.A86 1.22 93/10/18 17:41:45
; fix for >255 open files (PNW Server)
; MISC.A86 1.21 93/09/03 20:28:57
; Add intl/dbcs support for int 21/6523 (query yes/no char)
; MISC.A86 1.20 93/07/26 20:42:13
; Seperate int21/3306
; MISC.A86 1.12 93/03/05 18:12:33
; Fix DS corruption for NLSFUNC calls
; ENDLOG
;
VALID_SIG equ 0EDC1h
include pcmode.equ
include i:msdos.equ
include i:mserror.equ
include i:psp.def
include i:driver.equ
include i:char.def
include i:country.def
include i:doshndl.def
include i:redir.equ
include i:fdos.equ
NLSFUNC equ TRUE
;
GLOBAL_DATA DSEG WORD
extrn default_country:byte
extrn Ucasetbl:word
extrn FileUcasetbl:word
extrn FileCharstbl:word
extrn Collatingtbl:word
extrn DBCS_tbl:word
extrn NoYesChars:byte
extrn info1_len:abs
extrn info2_len:abs
extrn info4_len:abs
extrn info5_len:abs
extrn info6_len:abs
extrn info7_len:abs
extrn dos_version:word
extrn country_filename:byte
PCM_CODE CSEG BYTE
extrn dbcs_lead:near
extrn device_write:near ; Write to a Character Device
extrn device_read:near ; Read from a Character Device
extrn dos_entry:near
extrn error_exit:near
extrn error_ret:near
extrn func5F_common:near
extrn get_dseg:near
extrn valid_drive:near
extrn ifn2dhndl:near
extrn int21_func:near
extrn invalid_function:near
extrn patch_version:word
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
extrn toupper:near
extrn xlat_xlat:word
;
; *****************************
; *** DOS Function 34 ***
; *** Get The Indos Flag ***
; *****************************
Public func34
func34:
mov bx,offset indos_flag
; jmp return_DSBX_as_ESBX ; return ES:BX -> indos flag
Public return_DSBX_as_ESBX
return_DSBX_as_ESBX:
;-------------------
; On Entry:
; DS:BX to be returned to caller in ES:BX
; On Exit:
; ES/DI trashed
;
les di,ss:int21regs_ptr
mov es:reg_ES[di],ds
mov es:reg_BX[di],bx
ret
;
; *****************************
; *** DOS Function 52 ***
; *** Get Internal Data ***
; *****************************
;
;
Public func52
func52:
mov bx,offset func52_data
jmps return_DSBX_as_ESBX ; return ES:BX -> internal data
;
; *****************************
; *** DOS Function 5D ***
; *** Private DOS Func ***
; *****************************
;
;
Public func5D
func5D:
if DOS5
cmp al,7
jae f5d_05
mov si,dx ; ES:SI -> callers structure
mov bx,es:word ptr 20[si]
mov ss:owning_psp,bx ; update PSP from there
cmp WindowsHandleCheck,26h
jne f5D_05 ; check if Windows is running
mov bx,es:word ptr 18[si]
mov ss:machine_id,bx ; no, update machine_id
f5D_05:
else
push ds
push es ! pop ds ; restore users DS
callf ss:win386_remote_machine
pop ds
endif
cbw ; zero AH for valid functions
xchg ax,bx ; sub function in BX
cmp bx,func5D_ftl ; Assume Illegal Subfunction
jb f5D_10 ; check that it is a valid
mov bx,func5D_ftl ; subfunction
f5D_10:
shl bx,1
push func5D_ft[bx] ; save function address
shr bx,1
xchg ax,bx ; restore BX
ret ; go to function
f5D_msnet:
mov ax,I2F_REDIR_5D ; magic number to redirect
jmp func5F_common ; calls to extentions
;
;
; The registers for some of the following sub-functions are passed
; in the following structure.
;
RDC_AX equ es:word ptr 00[di] ; User AX
RDC_BX equ es:word ptr 02[di] ; User BX
RDC_CX equ es:word ptr 04[di] ; User CX
RDC_DX equ es:word ptr 06[di] ; User DX
RDC_SI equ es:word ptr 08[di] ; User SI
RDC_DI equ es:word ptr 10[di] ; User DI
RDC_DS equ es:word ptr 12[di] ; User DS
RDC_ES equ es:word ptr 14[di] ; User ES
RDC_RES equ es:word ptr 16[di] ; Remote Machine ID (High Word)
RDC_UID equ es:word ptr 18[di] ; Remote Machine ID (Low Word)
RDC_PID equ es:word ptr 20[di] ; Process ID
;
; *****************************
; *** DOS Function 5D00 ***
; *** Remote DOS Call ***
; *****************************
;
;
f5D00:
mov remote_call,0ffh ; set remote op flag
push es
les di,int21regs_ptr ; stack image the copy registers
pop ds
mov cx,6
rep movsw ; Copy AX, BX, CX, DX, SI, DI
inc di ! inc di ; Skip BP in the destination
movsw ! movsw ; finally copy DS and ES
push ss ! pop ds ; DS -> PCMDSEG
call reload_registers ; load up the new registers
jmp int21_func ; then execute that function
; *****************************
; *** DOS Function 5D01 ***
; *** Commit all files ***
; *****************************
;
f5D01:
;-----
; We are being asked to commit all files to disk
; By pretending to be FCB's we force use of IFN's, and we commit all possible
; files in the range 0-255, ignoring errors from unopened handles.
;
mov remote_call,DHM_FCB ; pretend to be FCB, forces use of IFN
xor bx,bx ; start with handle zero
f5D01_10:
mov ah,MS_X_COMMIT
call dos_entry ; commit this file
inc bx ; onto next candidate
cmp bx,0FFh ; runout yet ?
jb f5D01_10 ;
ret
; *****************************
; *** DOS Function 5D02 ***
; *** Close file by name ***
; *****************************
;
f5D02:
;-----
; Close file by name. We do a search first to find out about the file.
; As long as it's local we call share with the directory cluster/index
; to close it if it's open.
;
mov di,dx ; ES:DI -> register block
mov dx,RDC_DX
mov es,RDC_DS ; ES:DX -> filename to close
push dma_offset
push dma_segment
mov dma_offset,offset fcb_search_buf
mov dma_segment,ds
mov cx,DA_RO+DA_SYSTEM+DA_HIDDEN
mov ah,MS_X_FIRST ; look for this file
call dos_entry ; to get dir entry info
pop dma_segment
pop dma_offset
jc f5Dret
mov al,fcb_search_buf ; get drive #
test al,al ; reject networked drives
js f5Dret
dec ax ; make drive zero based
mov cx,word ptr fcb_search_buf+0Dh
; CX = directory count
mov dx,word ptr fcb_search_buf+0Eh
; DX = parent directory cluster
lea bx,fcb_search_buf+1 ; DS:BX -> name
mov di,S_CLOSE_IF_OPEN
; jmps f5D_common
f5D_common:
callf lock_tables ; protect SHARE with a critical section
callf share_stub[di]
callf unlock_tables ; safe again
f5Dret:
ret
; *****************************
; *** DOS Function 5D03 ***
; *** Close files by machine***
; *****************************
;
; *****************************
; *** DOS Function 5D04 ***
; *** Close by Machine/PSP ***
; *****************************
f5D03:
f5D04:
;-----
; Close all files for given PSP
;
mov di,S_CLOSE_FILES
jmps f5D_common
; *****************************
; *** DOS Function 5D05 ***
; *****************************
;
f5D05:
; On Entry:
; RDC.BX = Share File # to look to
; RDC.CX = Share Record # to look for
; On Exit:
; AX = DOSHNDL Attribute Word
; BX = machine ID
; CX = locked blocks count
; ES:DI -> buffer containing full pathname
;
;
callf lock_tables ; protect SHARE with a critical section
callf share_stub+S_GET_LIST_ENTRY
callf unlock_tables ; safe again
jnc f5Dret ; just return if it went OK
jmp error_ret ; else return error code in AX
; *****************************
; *** DOS Function 5D06 ***
; *** Get Internal Data ***
; *****************************
;
f5D06:
mov cx,offset swap_indos ; Calculate Size of Swap
sub cx,offset internal_data ; Swap INDOS Array
call return_CX ; CX = Swap Indos length
mov dx,offset swap_always ; Calculate Size of Swap
sub dx,offset internal_data ; Swap ALWAYS Array
call return_DX ; DX = Swap Always length
mov si,offset internal_data
call return_DSSI
mov ax,5D06h
jmp return_AX_CLC
;
; *****************************
; *** DOS Function 5D0A ***
; ***Set Extended Error Info***
; *****************************
;
f5D0A:
mov si,dx ; ES:SI -> parameter block
lods es:word ptr [si]
mov error_code,ax ; copy the appropriate fields
lods es:word ptr [si]
mov error_class,ah
mov error_action,al
lods es:word ptr [si]
mov error_locus,ah
add si,2*WORD ; skip to device
lods es:word ptr [si]
mov error_dev,ax
lods es:word ptr [si]
mov error_dev+2,ax
xor ax,ax ; return AL=0
ret
;
; *****************************
; *** Get switch character ***
; *****************************
;
;
Public func37
func37:
cmp al,1 ! jb f37_getswitch ; Get the current Switch Character
je f37_setswitch ; Set the Switch Character
cmp al,3 ! je f37_s03 ; Sub-Func 03 Return Unchanged
mov dl,0ffh ! jb f37_return_DX ; Sub-Func 02 Return DL == 0FFh
mov al,0FFh ; else invalid sub-function
f37_s03:
ret
f37_getswitch:
mov dl,switch_char
f37_return_DX:
jmp return_DX ; return current setting in DX
f37_setswitch:
mov switch_char,dl
ret
;**************************************************
;**************************************************
;*** ***
;*** Miscellaneous Isolated Functions ***
;*** ***
;**************************************************
;**************************************************
;
; *****************************
; *** DOS Function 30 ***
; *** Get Version Number ***
; *****************************
Public func30
func30:
if DOS5
mov es,current_psp ; version is kept in the PSP
mov ax,PSP_VERSION
else
mov ax,dos_version ; version returned in AX
endif
ReturnVersionNumber:
xor bx,bx ; zero BX and CX
xor cx,cx
call return_BX
call return_CX
jmp return_AX_CLC
;
; *****************************
; *** DOS Function 33 ***
; *** Get/Set Cntl-Break ***
; *****************************
Public func33
; WARNING - called on USER stack
func33:
cmp al,2 ; range check subfunction
jbe f33_10
mov dl,bootDrv ; assume we want boot drive
cmp al,5 ; did we ?
je f33_30
if DOS5
cmp al,6 ; get true version ?
je f33_60
endif
mov reg_AL[bp],0FFh ; return AL = FF
ret ; Illegal function request
f33_10:
and dl,01h ; force a valid value
cmp al,1 ; check for get or set
jae f33_20
mov dl,break_flag ; it's a get, so use existing setting
f33_20:
xchg dl,break_flag ; replace current setting
je f33_40
f33_30:
mov reg_DL[bp],dl ; return setting in DL
f33_40:
ret
if DOS5
f33_60:
mov reg_BX[bp],TRUE_VERSION ; return version number
mov ax,patch_version
mov reg_DX[bp],ax ; return revision+HMA
ret
endif
;
; *****************************
; *** DOS Function 25 ***
; *** Set Interrupt Vector ***
; *****************************
;
; WARNING - use no stack as device drivers have called us re-entrantly
Public func25
func25:
mov bx,es ; is really dos_DS - save for later
xor di,di ; replace with the values in dos_DS:DX
mov es,di ; es -> zero segment
xor ah,ah ; the interrupt number
mov di,ax ; 0:di -> vector
shl di,1 ! shl di,1 ; 4 bytes per vector
cli
xchg ax,dx ; Get New Offset
stosw ; and Save
xchg ax,bx ; Get New Segment
stosw ; and Save
sti
xchg ax,dx ; recover entry AL to (preserve it)
ret
; *****************************
; *** DOS Function 35 ***
; *** Get Interrupt Vector ***
; *****************************
; WARNING - use no stack as device drivers have called us re-entrantly
Public func35
func35:
xor bx,bx
mov ds,bx ; DS:0 -> vector table
mov bl,al ; BX = the interrupt number
shl bx,1 ! shl bx,1 ; 4 bytes per vector
lds bx,ds:dword ptr [bx] ; DS:BX -> vector
les di,ss:int21regs_ptr
mov es:reg_BX[di],bx
mov es:reg_ES[di],ds
jmp get_dseg ; restore DS for return
;PC-DOS Verify and Break Flags Support
;
; *****************************
; *** DOS Function 2E ***
; *** Set/Reset Verify ***
; *****************************
Public func2E
func2E:
and al,1 ; only use bottom bit
mov verify_flag,al ; store for use later
ret
; *****************************
; *** DOS Function 54 ***
; *** Get Verify Setting ***
; *****************************
Public func54
func54:
mov al,verify_flag ; return verify flag
ret
; *****************************
; *** DOS Function 63 ***
; *** Get Lead Byte Table ***
; *****************************
;
Public func63
func63:
cmp al, 1 ; subfunction #?
jb f63_get_tbl ; subfunction 0
je f63_set_flg ; subfunction 1
cmp al, 2 ; subfunction 2?
je f63_get_flg ; yes
mov ax, ED_FUNCTION ; invalid subfunction number
jmp error_exit ; so quit
f63_get_flg:
; Get the current state of the DOS interim character console flag.
; If this flag is set int 21h functions 07h, 08h, 0Bh, 0Ch are supposed
; to return "interim character information" which I assume is incomplete
; characters. (In languages like Korean a given double byte character
; may be built by the user entering several keystrokes which form
; incomplete characters.)
mov es, current_psp
mov dl, PSP_RIC ; Return Interim Character flag
jmp return_DX ; flag returned in dl
f63_set_flg:
; Set the current state of the DOS interim character console flag.
; dos_DL = 0 - clear flag, dos_DL = 1 - set flag
mov es, current_psp
mov PSP_RIC, dl ; record flag
ret
f63_get_tbl:
; Get the current DBCS table address.
mov si,offset DBCS_tbl+2; skip the table size entry
; jmp return_DSSI
return_DSSI:
;-----------
; On Entry:
; DS:SI to be returned to caller
; On Exit:
; AX preserved
;
les di,ss:int21regs_ptr
mov es:reg_DS[di],ds
mov es:reg_SI[di],si
ret
;
; *****************************
; *** DOS Function 29 ***
; *** Parse String ***
; *****************************
Public func29
func29:
;
; Entry:
; DS:SI -> line to parse
; ES:DI -> resulting fcb
; Exit:
; DS:SI -> terminating delimeter past parsed filename
; ES:DI -> filled in fcb (Affects 16 bytes: DnnnnnnnnTTT0000)
;
push ds
push es
call reload_ES
pop ds
call parse
call return_DSSI ; return result of parse
pop ds
mov al,dh ; return result in AL
ret
;-----
parse: ; parse DOS filename delimited by TAB,SPACE,or .,+:;=|"/\[]<> or ctrl
;-----
; Entry:
; DS:SI -> line to parse
; ES:DI -> fcb to parse into
; AL == bit options:
; Bit 0 == 1: scan off leading delimiters
; Bit 1 == 1: change drive only if specified
; Bit 2 == 1: change name " " "
; Bit 3 == 1: change type " " "
; Exit:
; DS:SI -> terminating delimeter past parsed filename
; ES:DI -> filled in fcb (Affects 16 bytes: DnnnnnnnnTTT0000)
; DH == 1 if wild, 0FFh if the drive is invalid, 0 otherwise
;
push di ; (<--keep DI last on stack)
cld ; ChSh
xor dx,dx ; DH = default return value (0)
xchg al,dl ; put flags into DL, AL = 0
mov cx,1
test dl,0010b ; should we initialize drive?
call nz_store_al ; do conditional store
mov al,' ' ; use spaces for filename & typ
mov cl,8
test dl,0100b ; should we initialize the name?
call nz_store_al
mov cl,3
test dl,1000b ; should we initialize the typ?
call nz_store_al
xor ax,ax ; zero-out the 4 post-typ bytes
stos ax
stos ax
pop di ! push di ; restore DI to start of FCB
deblank_loop:
lods al ; grab char
cmp al,' ' ; is it a blank?
je deblank_loop ; Y: keep looping
cmp al,'I'-'@' ; is it a tab?
je deblank_loop ; Y: keep looping
test dl,0001b ; skip-delimiter-bit set?
jz parse_drive ; N: go start parsing
skip_delim_loop:
call check_delimiters ; check AL for delimiterness
jb parse_dec_ret ; found terminator, dec SI & leave
mov dl,dh ; flag no-more-delimiter-skip (DL = 0)
je deblank_loop ; found separator, go deblank after it
parse_drive:
dec si
cmp byte ptr 1[si],':' ; is the drive specified?
jne parse_name
lods ax ; get drive, junk colon
and al,01011111b ; upper case it
sub al,'@' ; AL = 1-relative drive #
push ax ! push ds ; Save the drive code and call
call get_dseg ; Restore our Data Segment
call valid_drive ; routine to validate drive ZR == OK
pop ds ! pop ax ; Restore drive code and User DS
jz parse_d10
dec dh ; flag drive error (0FFh)
parse_d10:
mov es:[di],al ; insert drive in fcb
parse_name:
inc di ; DI -> fname
mov cx,8
call parse_item ; parse an up-to 8 char filename
cmp dl,'.' ; was the delimeter a '.'?
jne parse_dec_ret ; N: the parse is complete
mov cl,3
call parse_item ; parse an up-to 3 char filetype
parse_dec_ret:
dec si ; bump SI back to point to delimeter
parse_ret:
pop di
ret
;-----------
nz_store_al:
;-----------
; Entry:
; DI -> destination to conditionally initialize
; CX == length of destination
; AL == byte to initialize with
; ZF set: do not initialize destination
; Exit:
; DI -> past destination (initial DI+CX)
; Changed:
; CX,DI
;
jnz skip_store ; should we initialize?
rep stosb ; Y: store them bytes
skip_store:
add di,cx ; bump DI to post-dest position
ret
;==========
parse_item: ; Parses item into fcb if item is specified
;==========
;
; Entry:
; SI -> item to parse (name or type)
; DI -> fcb area to parse it into
; CX == length of item
; DH == parse_return
; Exit:
; SI -> past ending delimeter
; DI -> past fcb area (initial DI + CX)
; CH == If zero on enter zero on exit else 0-255
; DH == updated parse_return w/possible wild bit set
; DL == character delimiter @(SI-1)
; Changed:
; AX,CX,DX,SI,DI
;
mov ah,FALSE ; specified item flag
parse_item_loop:
lods al ; get char
call check_delimiters ; is it a delimiter?
jbe pi_pad_ret ; Y: the parse is complete
jcxz parse_item_loop ; if the name is full, skip the char
mov ah,al ; flag name as present
cmp al,'?' ; is it a single wild char?
je pi_set_wild ; Y: set wild flag
cmp al,'*' ; is it a multi-char wild card?
jne pi_store ; N: store it
mov al,'?' ; Y: fill with '?' to end of name
rep stosb
pi_set_wild:
or dh,1 ; set wild flag
jcxz parse_item_loop ; skip store if name is now filled
pi_store:
dec cx ; another char done
call dbcs_lead ; is it the 1st byte of kanji ?
jne pi_store10
inc si ; skip 2nd byte
jcxz parse_item_loop ; can I copy both ?
dec cx ; yes, do so
stosb
dec si ; point at second byte
lodsb ; so we can copy it too..
pi_store10:
stos al ; put the char in the fcb
jmps parse_item_loop
pi_pad_ret:
mov dl,al ; DL = ending delimeter
or ah,ah ; the the item specified?
jz pi_ret ; N: skip padding
mov al,' ' ; Y: pad to end with spaces
rep stosb
pi_ret:
add di,cx ; bump DI out to end
ret
;----------------
check_delimiters:
;----------------
;
; Entry:
; AL == char to check in list of delimiters
; Exit:
; AL == char changed to uppercase
; CF set if it is one of the terminators: |"/\[]<> & ctrl chars != TAB
; ZF set if it is one of the separators: .,+:;= SPACE & TAB
; OR one of the non-ctrl terminators
;
cmp al,'a' ; check for lower case
jb not_lower
cmp al,'z'
ja not_lower
and al,01011111b ; uppercase it, CF clear, ZF clear
ret
not_lower:
push cx ! push di ! push es
push cs ! pop es ; ES = Code segment
mov di,offset parse_separators
mov cx,length parse_separators
repne scasb ; is AL a separator?
je cpd_pop_ret ; Y: return ZF set
mov cl,length parse_terminators
repne scasb ; is AL a terminator?
stc ; (set CF if true)
je cpd_pop_ret ; Y: return CF & ZF set
cmp al,' ' ; (AL == ' ') ZF set, (AL < ' ') CF set
cpd_pop_ret:
pop es ! pop di ! pop cx
ret
;
; *****************************
; *** DOS Function 2A ***
; *** Get Current Date ***
; *****************************
Public func2A
func2A:
;
; entry: None
;
; exit: cx = year (1980-2099)
; dh = month (1-12)
; dl = day (1-31)
; al = DOS returns day of week here
;
call ReadTimeAndDate ; Get the current Time and Date
mov cx,1980
add cx,yearsSince1980
; mov dl,dayOfMonth
; mov ah,month
mov dx,word ptr dayOfMonth
mov al,dayOfWeek
jmps f2C_10 ; exit via common routine
; *****************************
; *** DOS Function 2C ***
; *** Get Current Time ***
; *****************************
Public func2C
func2C:
;
; entry: None
;
; exit: ch = hours (0-23)
; cl = minutes (0-59)
; dh = seconds (0-59)
; dl = Hunredths seconds (0-99)
; al = 0
;
call ReadTimeAndDate ; Get the current Time and Date
mov cx,biosDate+2 ; Get the Hour and Minute
mov dx,biosDate+4 ; Get the Seconds and Hundredths
xor ax,ax ; return AL = 0
f2C_10:
call return_CX ; and return to caller
jmp return_DX
; *****************************
; *** DOS Function 2B ***
; *** Set Current Date ***
; *****************************
Public func2B
func2B:
;
; entry: cx = year (1980-2099)
; dh = month (1-12)
; dl = day (1-31)
;
; exit: al = 00H success
; = FFH failure
;
call ConvertDate ; Convert to BIOS date
jc f2B_20 ; Abort on Error
push cx ; save the converted date
call ReadTimeAndDate ; Get the current Time and Date
pop biosDate ; new date, existing time
f2B_10: ; Set the current Time and Date
call rw_clock_common ; make sure clock is there/setup regs
call device_write ; Update the Date and Time
xor ax,ax
ret
f2B_20:
mov al,0FFh ; return FAILURE
ret
; *****************************
; *** DOS Function 2D ***
; *** Set Current Time ***
; *****************************
Public func2D
func2D:
;
; entry: ch = hours (0-23)
; cl = minutes (0-59)
; dh = seconds (0-59)
; dl = hundredth seconds (0-99)
;
; exit: al = 00H success
; = FFH failure
;
cmp ch,23 ; Range check hours
ja f2B_20
cmp cl,59 ; Range check minutes
ja f2B_20
cmp dh,59 ; Range check seconds
ja f2B_20
cmp dl,99 ; Range check hundredths
ja f2B_20
push cx ; save hours/mins
push dx ; save secs/hundredths
call ReadTimeAndDate ; Get the current Time and Date
pop biosDate+4 ; leave the date alone
pop biosDate+2 ; but update the time
jmps f2B_10 ; Update the Date and Time
Public ReadTimeAndDate
ReadTimeAndDate: ; Get the current Time and Date
call rw_clock_common ; make sure clock is there/setup regs
call device_read ; read the Date and Time
mov ax,biosDate ; get the BIOS date and convert
cmp ax,daysSince1980 ; (but only if necessary)
jne NewDate
ret
NewDate:
mov daysSince1980,ax ; so we won't have to convert next time
inc ax ; Day number starting 1 Jan 1980
mov cx,ax ; save day count
inc ax ; convert to a sunday as 1/1/80 is tues
xor dx,dx
mov bx,7
div bx
mov dayOfWeek,dl ; save day of week
xor dx,dx
mov ax,cx ; recover day count
xor di,di ; assume zero leap days
sub ax,60 ; less than 60 days
jc no_leap_days ; means no leap days to subtract
mov bx,1461 ; 1461 = days in four years
div bx ; get number of leap years since 1980
inc ax ; include 1980
sub cx,ax ; normalize years to 365 days
mov di,ax ; save proper leap day count
no_leap_days:
xor dx,dx
xchg ax,cx ; DX:AX = years since 1980 * 365
mov bx,365
div bx ; get number of years since 1980
or dx,dx ; check for zero days left
jnz days_left
dec ax ; dec year count
mov dx,365 ; set day count to last day of last year
days_left:
mov yearsSince1980,ax ; save the year
xchg ax,si ; save in SI
xor bx,bx
mov cx,12
get_month: ; find the appropriate month
cmp dx,totaldays[bx]
jbe got_month
inc bx ! inc bx
loop get_month
got_month:
shr bx,1 ; BX = month
mov month,bl
dec bx
shl bx,1 ; BX = index to previous months
sub dx,totaldays[bx] ; get days into this month
cmp bx,2 ; if it's FEB 29th we've lost a day
jne not_leap_yr ; check it's FEB
test si,3
jnz not_leap_yr ; but is it a leap year ?
shr si,1 ! shr si,1 ; divide years by 4
inc si ; include this year
cmp si,di ; compare against leap day adjustment
jne not_leap_yr
inc dx ; put 29th feb back again
not_leap_yr:
mov dayOfMonth,dl ; save the day of the month
ret
ConvertDate:
sub cx,1980 ; Base year is 1980
jc xset_date_error
cmp cx,2100-1980 ; Year in valid range ?
jnc xset_date_error
mov bl,dh ; Month to BL
xor bh,bh
dec bx ; Adjust month to 0-11
cmp bl,12 ; Month in valid range ?
jnc xset_date_error
mov al,dl ; Day of month
cbw
test cl,3 ; Leap year ?
jnz not_leap_year ; Jump if not
cmp dh,3 ; After February ?
cmc
adc al,ah ; Increment days in current year if so
cmp dl,29 ; Day of month 29 ?
jz day_valid ; Valid if so
not_leap_year:
dec dx
cmp dl,monthdays[bx] ; Day of month within range for non-leap
; year ?
jnc xset_date_error
day_valid:
shl bx,1
add ax,totaldays[bx] ; Get total days in current year
push ax
mov ax,365
mul cx ; Convert year to days since 1-1-1980
mov cx,ax
; if total (ax) >= 60 (Feb 29 1980) then
; leap$days = (total - 60) / (365 * 4) + 1
sub ax,60 ; Before first leap year date
jc noleap ; Jump if so
mov bx,365*4 ; 4 years worth of days (365 * 4)
sub dx,dx
div bx ; Get number of leap years - 1
inc ax
add cx,ax ; CX now has total days including leap
; days
noleap:
dec cx
pop ax
add cx,ax ; Get total days since 1-1-1980
clc
ret
xset_date_error:
stc
ret
rw_clock_common:
mov cx,6 ; read/write 6 characters
mov dx,offset biosDate ; DX -> 6 byte buffer
les si,clk_device ; Get the address of the Clock Device
cmp si,-1 ; Has a valid device been selected
jne rw_clock_common10
add sp,WORD ; discard near return address
rw_clock_common10:
ret
; *****************************
; *** DOS Function 38 ***
; *** Get/Set Country Data ***
; *****************************
Public func38
func38:
xor ah,ah ; Generate 16 Bit country
cmp al,0FFh ; FF means country code in BX
jne f38_10
xchg ax,bx ; AX = real country code
f38_10:
xchg ax,dx ; DX = country
test dx,dx ; dos_AL = 0 get the current country
jz f38_get
inc ax ; now check for dos_DX = FFFF
jz f38_set ; which means set country code
dec ax ; no, return buffer to normal
f38_get:
test dx,dx ; Get current?
jnz f38_g10 ; Yes
mov dx,cur_country ; use current country
f38_g10:
; look for (and if neccessary load) type 1 info into buffer
xchg ax,di ; ES:DI -> buffer
mov bx,cur_cp ; bx=codepage
call f38_get_info ; get info in current codepage
jnc f38_g20
push ss ! pop ds
xor bx,bx ; now try any codepage
call f38_get_info ; if none for current codepage
jc f38_error ; No Match Found
f38_g20:
lea si,EXCI_CI_DATAOFF[si] ; point at CI_, not EXCI_ data
mov bx,CI_CODE[si] ; Return the selected country code
mov cx,CI_STATICLEN/2
rep movsw
if NLSFUNC
push ss
pop ds
; call get_dseg ; DS back to PCMODE
endif
call return_BX ; return country code in BX
xchg ax,bx
jmp return_AX_CLC ; and in AX
f38_get_info:
push es ! push di ! push dx ; save pointer to buffer
mov al,1 ; Get data list seperators etc...
call f65_get_info ; DS:SI -> extended country info buffer
pop dx ! pop di ! pop es ; ES:DI -> users buffer
ret
f38_set:
mov bx,cur_cp ; bx=codepage
and bx,f38_flag ; force CP to zero if 1st time here
call f38_set_country ; Update the Internal Data Structures
jc f38_error
f38_s20:
mov f38_flag,0FFFFh ; Country Code Set Successfully
mov ax,cur_country ; and return the current country
jmp return_AX_CLC ; to the user
f38_error:
if NLSFUNC
push ss
pop ds
; call get_dseg ; DS back to PCMODE
endif
mov ax,ED_FILE ; This is the Error to return
jmp error_exit
f38_set_country:
; On Entry:
; BX = codepage
; DX = country
; On Exit:
; AX = error code
; preserve codepage/country info if there is an error (ie do type 1 last!)
;
mov al,2 ; Get uppercase & filename table
mov di,offset Ucasetbl
mov cx,info2_len
call f38_update
jc f38_seterr
mov al,4 ; Get uppercase & filename table
mov di,offset FileUcasetbl
mov cx,info4_len
call f38_update
jc f38_seterr
mov al,5 ; Get Legal file characters
mov di,offset FileCharstbl
mov cx,info5_len
call f38_update
jc f38_seterr
mov al,6 ; Get Collating table
mov di,offset Collatingtbl
mov cx,info6_len
call f38_update
jc f38_seterr
mov al,7 ; Get double byte character set table
mov di,offset DBCS_tbl
mov cx,info7_len
call f38_update
jc f38_seterr
mov al,1 ; Get data list seperators etc...
mov di,offset country_data ; do last since this updates
mov cx,info1_len ; cur_country/cur_cp
call f38_update
; jc f38_seterr
; clc
ret
f38_seterr:
mov ax,ED_FILE ; return file not found error
ret
f38_update:
push ds ; save important registers
push bx ; codepage
push cx ; count for move
push dx ; country
push di ; destination offset for move
push ds ; destination segment
call f65_get_info ; DS:SI -> buffer with country info
pop es ; destination seg in ES
pop di ; ES:DI -> destination of move
pop dx ; country
pop cx ; bytes to move
pop bx ; codepage back again
jc f38_update10 ; any problems ?
rep movsb ; no, copy the data
f38_update10:
pop ds ; DS back to PCMDSEG
ret
; *****************************
; *** DOS Function 65 ***
; *** Extended Country Data ***
; *****************************
;
;CODEPAGE equ 437 ; Return Standard Code Page
;
; Get Extended Country Code Sub-Functions
;
func65_dt dw 0FFFFh ; 00 Illegal Sub-Function
dw offset country_data ; 01 Extended Country Info
dw offset Ucasetbl ; 02 UpperCase Table
dw 0FFFFh ; 03 Invalid Subfunction
dw offset FileUcasetbl ; 04 FileName Upper Case Table
dw offset FileCharstbl ; 05 Valid Filename Characters
dw offset Collatingtbl ; 06 Collating Sequence
dw offset DBCS_tbl ; 07 DBCS Environment Vector
func65_dtl equ (offset $ - offset func65_dt)/2
Public func65
func65:
cmp al,func65_dtl ; is sub-function 0-7 ?
jb func65_read_table
sub al,20h ; now check for 20-22
jb f65_invalid
je func6520 ; it's upper case character
sub al,2
je func6522
jb func6521
sub al,1 ; how about 6523 ?
jnz f65_invalid
; jmp func6523
func6523:
;--------
; On Entry:
; DX = character to check
; On Exit:
; AX = 0, No
; AX = 1, Yes
; AX = 2, neither
;
push ds
pop es
mov di,offset NoYesChars ; 'NnYy'
cbw ; assume No (AX=0)
xchg ax,dx ; AX = char, DX = answer
call dbcs_lead ; is it 1st of a DBCS pair
jne func6523_10
scasw ; check 'N'
je func6523_30
inc dx ; assume Yes (DX=1)
scasw ; check 'Y'
jmps func6523_20
func6523_10:
scasb ; check 'N'
je func6523_30
scasb ; check 'n'
je func6523_30
inc dx ; assume Yes (DX=1)
scasb ; check 'Y'
je func6523_30
scasb ; check 'y'
func6523_20:
je func6523_30
inc dx ; it's neither (DX=2)
func6523_30:
xchg ax,dx ; return result in AX
jmp return_AX_CLC ; Return the Code Page
func6522:
;--------
; Upper case ASCIIZ string at ES:DX
mov cx,0FFFFh ; calculate the length
mov di,dx ; of the string
; mov al,0
repne scasb
not cx ; CX = length, including 0
; jmp func6521 ; now use upper case CX bytes
func6521:
;--------
; Upper case string of CX bytes at ES:DX
mov si,dx
mov di,dx ; point SI & DI at string
f6521_10:
lods es:al ; read a character
call dbcs_lead ; is it 1st of a DBCS pair
jne f6521_20
stosb ; store 1st byte of this pair
movs es:byte ptr [di],es:byte ptr [si]
; copy 2nd byte
dec cx ; 1st byte of pair
loopnz f6521_10 ; go around for another one
ret ; time to go...
f6521_20:
call toupper ; upper case the character
stosb ;
loop f6521_10 ; go and do another one
ret
func6520:
;--------
; Upper case character DL
xchg ax,dx ; character in AX
call toupper ; upper case it
mov dl,al ; return in AL and DL
jmp return_DX ; set return code
f65_invalid:
;-----------
; short jump to invalid function
jmp invalid_function
func65_read_table:
;-----------------
cmp cx,5 ; Check for valid buffer size
jb f65_invalid
cbw ; Get the request sub-function
mov si,ax ; into SI
shl si,1
mov si,func65_dt[si]
inc si ; is SI = 0FFFFh
jz f65_invalid ; if so it's an invalid function
dec si
cmp dx,0ffffh
jne f65_21 ; FFFF means
mov dx,cur_country ; use default country
f65_21:
cmp bx,0ffffh
jne f65_22 ; FFFF means
mov bx,cur_cp ; use default codepage
f65_22:
call f65_get_info ; DS:SI -> extended info for this pair
mov ax,ED_FILE ; On Error return File Not Found
jnc f65_23 ; for any error
push ss ! pop ds
jmp error_exit ; so Quit
f65_23:
les bx,ss:int21regs_ptr ; point to callers registers
mov ax,es:reg_AX[bx] ; get the subfunction number
mov cx,es:reg_CX[bx] ; this much data is requested
mov di,es:reg_DI[bx] ; Get the Parameter Block Offset
mov es,es:reg_ES[bx] ; and Segment
stosb ; fill in Info ID
cmp al,1 ; 1 is special - the rest
jne f65_30 ; want a DWORD ptr
cmp cx,EXCI_MAXLEN ; Check CX against the sub-function 1
jbe f65_25 ; maximum and force CX to this value
mov cx,EXCI_MAXLEN ; if it is greater
f65_25:
call return_CX ; Return the number of bytes transfered
sub cx,EXI_DATA_LEN ; Adjust count for 3 byte header
mov ax,cx ! stosw ; fill in EXCI_LENGTH
push cx ; Save the count and copy as much
cmp cx,EXCI_STATLEN ; valid data a possible. IE at most
jbe f65_27 ; EXCI_STATLEN bytes
mov cx,EXCI_STATLEN
f65_27:
rep movsb ; just copy the data
pop cx ; Zero the rest of the data
sub cx,EXCI_STATLEN ; Skip if no space left in users
jbe f65_40 ; buffer otherwise STOSB
xor al,al ! rep stosb
jmps f65_40
;
; All function 65 sub-functions apart from 01 (Extended Country Info.)
; pass use this code to update the users parameter block.
;
f65_30:
mov cx,5
call return_CX
mov ax,si ! stosw ; fill in the DWORD ptr to the data
mov ax,ds ! stosw
f65_40:
push ss
pop ds
; call get_dseg ; back to PCMDSEG
mov ax,cur_cp ; ##jc## Is the Requested or Current
jmp return_AX_CLC ; Return the Code Page
; *****************************
; *** DOS Function 66 ***
; ***Get/Set Global CodePage***
; *****************************
;
Public func66
func66:
cbw
dec ax ! jz f66_10 ; AL = 1, Get the Current CodePage
dec ax ! jz f66_20 ; AL = 2, Set the Current CodePage
jmp invalid_function ; Illegal Sub-Function return an Error
f66_10: ; Get the Current Code Page Info
mov bx,cur_cp ; Current CodePage
call return_BX
mov dx,SYS_CP ; System CodePage
jmp return_DX
f66_20: ; Set the Current CodePage
mov dx,cur_country ; The Codepage has changed, so update
call f38_set_country ; Country Info and tables
jnc f66_30 ; Reset the Current CodePage if
mov ax,ED_FILE ; and return the error
jmp error_exit
f66_30:
mov bx,cur_cp ; select the new codepage
call f66_select_cp ; Prepare CodePage Devices
jnc f66_40 ; No Errors Skip Error Handler
mov ax,-65 ; Update Error Status do not generate
call error_ret ; a critical error but return
; "access denied" to the application
f66_40:
ret
f65_get_info:
; On Entry:
; AL = info type
; BX = codepage (zero means any)
; DX = country
; On Exit:
; CY set if error
; DS:SI -> buffer with info in it
;
; NB. Remember to to Xlat fixups !
;
cmp dx,cur_country ; is it default country ?
jne f65_p30 ; have we already got correct country ?
test bx,bx ; CP zero special case and we will
jz f65_p20 ; accept anything for this country
cmp bx,cur_cp ; otherwise is the codepage
jne f65_p30 ; in the default system ?
f65_p20:
cbw ; make info type a word
mov si,ax ; into index register
shl si,1 ; now a word offset
mov si,func65_dt[si] ; pick up offset of correct table
jmps f65_p90
f65_p30:
push ax
call f65_locate_and_read ; get info into a buffer at DS:SI
pop ax
jc f65_p_exit
f65_p90:
cmp al,1 ; was it country info ?
jne f65_p95 ; no, skip the fixup
mov CI_CASEOFF+EXCI_CI_DATAOFF[si],offset xlat_xlat
mov CI_CASESEG+EXCI_CI_DATAOFF[si],ss
f65_p95:
clc
f65_p_exit:
ret
;
; **********************************************************************
; *** Function 65 support - routines for seeking a country/codepage ***
; *** and loading the required information into the temp data area ***
; **********************************************************************
;
; **************************************************
; *** Open country.sys and search for the ***
; *** table of offsets for the given country/ ***
; *** codepage, read it in and exit. ***
; **************************************************
f65_locate_and_read:
; Locate and Read info AL for Country DX Codepage BX
if NLSFUNC
mov di,offset country_filename
; point at pathname to country.sys
xchg ax,cx ; get info into CL
mov ax,14feh ; then call magic backdoor
nlsfunc_int2f:
stc ; assume an error
int 2fh ; to do the hard work
ret
else
push ax
call f65x_find_info ; Will need to load up the info
pop ax
jc f65_lr_exit ; so do it if we can.
mov dx,offset f65xx_temp_area
mov cx,256 ; read 256 bytes into local buffer
push ax
call f65x_load_info ; Load required info
pop ax
jc f65_lr_exit
mov ah,MS_X_CLOSE ; All done so
mov bx,c_handle ; Close the file first
call dos_entry ; before leaving
; jc f65_lr_exit
mov si,offset f65xx_temp_area ; Tell subroutines where info is
f65_lr_exit:
ret
;
; Entry: dx=country code, bx=codepage
; Exit : carry set, and country.sys closed if failure
; country.sys open ready for more reads if success
;
f65x_find_info:
push es ; Save es
push ds
pop es ; Make es=ds
mov f65xx_country,dx
mov f65xx_codepage,bx
mov dx,offset country_filename
mov ax,(MS_X_OPEN*256)+0 ; Attempt to open country.sys
test dx,dx
stc
jz f65x_40
call dos_entry ; Handle should come back in ax
jc f65x_40
f65x_10:
mov c_handle,ax ; Save handle
mov dx,f65xx_country
cmp f65xx_code,dx ; do we already have the information?
jne f65x_30 ; No - get it from country.sys
f65x_20:
cmp f65xx_cp,bx ; Does codepage agree too?
je f65x_35 ; Yes so exit with no more ado
f65x_30:
mov dx,007Eh
xor cx,cx ; Seek within country.sys
mov bx,c_handle
mov ax,(MS_X_LSEEK*256)+0 ; seek from begining
call dos_entry
jc f65x_err
mov ah,MS_X_READ ; Now read the signature bytes and
mov bx,c_handle ; check them
mov cx,2
mov dx,offset f65xx_sig
call dos_entry
jc f65x_err
cmp f65xx_sig,VALID_SIG
jne f65x_err ; If signature bad exit
f65x_32:
mov ah,MS_X_READ ; Read from country.sys header until
mov bx,c_handle ; Country/codepage found or NULL
mov cx,f65xx_ptable_len
mov dx,offset f65xx_code
call dos_entry
jc f65x_err
cmp f65xx_code,0 ; Found NULL so reqd combination
je f65x_err ; was not found
mov dx,f65xx_code ; Get the country/codepage values
mov bx,f65xx_cp ; read from Country.SYS
cmp dx,f65xx_country ; Check against the requested
jne f65x_32 ; Country.
cmp f65xx_codepage,0 ; If a codepage match is not
jz f65x_35 ; then return success
cmp bx,f65xx_codepage ; Check against the requested
jne f65x_32 ; Codepage
f65x_35:
mov f65xx_country,dx ; Force the Search Country and
mov f65xx_codepage,bx ; CodePage to be Updated
f65x_40:
pop es ; combination found so exit
ret
f65x_err:
pop es
mov ah,MS_X_CLOSE ; On error close country.sys
mov bx,c_handle ; and set the carry flag before
call dos_entry ; leaving
stc
ret
;
; **************************************************
; *** Load the type of information requested ***
; *** For the country currently active in the ***
; *** offset table ***
; **************************************************
;
; Entry: al=type of info, dx=offset of buffer to read info into cx=no of bytes
; Exit : carry set, and country.sys closed if failure
;
f65x_load_info:
push es
push cx
push dx
push ds ; Make es=ds
pop es
dec al ; 1=Data , 2=uppercase, 4=fuppercase
sub bh,bh ; 5=filechars, 6=Collating table
mov bl,al ; 7=DBCS table
shl bx,1 ; Retrieve relevant offset
mov dx,f65xx_data[bx]
xor cx,cx ; Seek within country.sys
mov bx,c_handle
mov ax,(MS_X_LSEEK*256)+0 ; seek from begining
call dos_entry
pop dx ; Get buffer address back
pop cx ; and number of bytes to read
jc f65x_err
test ax,ax ; zero offset is a problem
jz f65x_err ; (probably DBCS with old COUNTRY.SYS)
mov ah,MS_X_READ ; Now read that info into our data area
mov bx,c_handle
call dos_entry ; Return when read is done
jc f65x_err
pop es
ret
endif
;
; This function scans the complete device list and prepares
; all devices which support codepage.
;
; On Entry:
; BX = codepage
; On Exit:
; AX = error code
DA_CODEPAGE equ DA_CHARDEV+DA_IOCTL+DA_GETSET
f66_select_cp:
if NLSFUNC
mov ax,14ffh ; then call magic backdoor
jmps nlsfunc_int2f ; to do the hard work
else
push ds
mov f66_cp,bx ; Save requested CodePage
mov preperr,0000 ; Initialize Prepare Error
push ds ! pop es
mov bx,offset dev_root ; Get the Root of the Device List
f66_p10: ; Skip the NUL Device and check
lds bx,ds:DH_NEXT[bx] ; each character device for CodePage
cmp bx,0FFFFh ! jz f66_p50 ; Support.
mov ax,ds:DH_ATTRIB[bx]
and ax,DA_CODEPAGE ; Check for a Character Device which
cmp ax,DA_CODEPAGE ; supports IOCTL strings and GETSET
jne f66_p10 ; otherwise skip the device
push bx
lea si,DH_NAME[bx] ; Found a matching device so
mov di,offset prepname ; open the device and select the
mov cx,8 ; requested codepage
f66_p20:
lodsb
cmp al,' ' ! jz f66_p30
stosb
loop f66_p20
f66_p30:
xor al,al ! stosb
mov ax,(MS_X_OPEN*256)+1 ; Open the device name for
mov dx,offset prepname ; Write Access
call dos_entry
jc f66_perr
mov bx,ax ; Save Device Handle in BX
mov si,es:f66_cp ; Get Requested CodePage in SI
mov dx,offset cp_packet ; Offset of CodePage Struct
mov cx,006Ah ; Get Unknown CodePage
mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function
call dos_entry ; Make function Call
jc f66_p32 ; Error so Select requested Code Page
cmp si,es:cp_cpid ! jz f66_p35 ; If this the currently selected
f66_p32: ; skip the select CodePage
mov es:cp_cpid,si
mov dx,offset cp_packet ; Offset of CodePage Struct
mov cx,004Ah ; Select Unkown CodePage
mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function
call dos_entry ; Make function Call
jnc f66_p35 ; No Error so skip the error
f66_p33:
mov es:preperr,ax ; save
f66_p35:
mov ah,MS_X_CLOSE ; Close the device and check
call dos_entry ; for more devices to be prepared
jmps f66_p40
f66_perr:
mov es:preperr,ax ; Save the error code and try the
f66_p40: ; next device in the chain
pop bx ; Restore the Device offset
jmps f66_p10 ; and continue
f66_p50: ; All device have been prepared
pop ds ; now return the last error code
mov ax,preperr ; in AX
or ax,ax
ret
endif
PCMODE_DSIZE DSEG PARA
extrn swap_indos:word
PCM_RODATA CSEG WORD
;
; Get Internal Data DOS function 5Dh
;
func5D_ft dw f5D00
dw f5D01 ; Commit All
dw f5D02 ; Close File By Name
dw f5D03 ; Close All Host Files
dw f5D04 ; Close Process Host Files
dw f5D05 ; Get Open File List
dw f5D06 ; Get DOS Data Area
dw f5D_msnet ; f5D07 ; Get Truncate Flag used
; with Redirected Dev I/O
dw f5D_msnet ; f5D08 ; Set Truncate Flag with
; with Redirected Dev I/O
dw f5D_msnet ; f5D09 ; Close All Spool Streams
dw f5D0A ; Set Extended Error Info
func5D_ftl equ (offset $ - offset func5D_ft)/2
dw invalid_function
;
; Data used by the Binary format Time and Date routines
;
totaldays dw 0,31,59,90,120,151,181,212,243,273,304,334,0ffffh
monthdays db 31,28,31,30,31,30,31,31,30,31,30,31
parse_separators db TAB,'.,+:;='
parse_terminators db '|"/\[]<>'
PCMODE_DATA DSEG WORD
extrn internal_data:word
extrn error_code:word
extrn error_class:byte
extrn error_action:byte
extrn error_locus:byte
extrn error_dev:word
extrn indos_flag:word
extrn bootDrv:byte
extrn current_psp:word
extrn break_flag:byte
extrn dma_offset:word
extrn dma_segment:word
extrn fcb_search_buf:byte
extrn func52_data:byte ; Internal Data Table Area
extrn int21regs_ptr:dword
extrn lock_tables:dword
extrn unlock_tables:dword
extrn share_stub:dword
extrn remote_call:word ; set to FF if remote machine operation
extrn swap_always:word
extrn switch_char:byte
extrn owning_psp:word
extrn machine_id:word
extrn country_data:byte
extrn cur_country:word
extrn cur_cp:word
extrn verify_flag:byte
extrn clk_device:dword ; Clock Device Driver Address
extrn biosDate:word
extrn daysSince1980:word
extrn yearsSince1980:word
extrn month:byte
extrn dayOfWeek:byte
extrn dayOfMonth:byte
extrn hour:byte
extrn minute:byte
extrn second:byte
extrn hundredth:byte
if DOS5
extrn WindowsHandleCheck:byte
else
extrn win386_remote_machine:dword
endif
SYS_CP equ 437 ; System CodePage
GLOBAL_DATA dseg word
f38_flag dw 0 ; Country Code Selected Successfully
if not NLSFUNC
extrn dev_root:dword
f66_cp rw 1 ; INT21/66 Local Variable
cp_packet dw 2 ; Packet Size
cp_cpid dw 0 ; Request CodePage
db 0,0 ; Packet Terminators
preperr rw 1 ; Prepare function Error Code
prepname rb 9 ; Reserved for ASCIIZ Device Name
;
; Area for country.sys current pointer table
; (these are all offsets into country.sys)
;
f65xx_code rw 1 ; Country code
f65xx_cp rw 1 ; Code page
rw 1 ; +1 reserved
f65xx_data rw 1 ; Data area
rw 1 ; Upper case table
rw 1 ; +1 reserved
rw 1 ; Filename upper case table
rw 1 ; Legal file characters
rw 1 ; Collating table
rw 1 ; Double byte character set lead byte table
f65xx_ptable_len equ offset $ - offset f65xx_code
f65xx_temp_area rb 256 ; Data area for extended country info
f65xx_codepage rw 1
f65xx_country rw 1
f65xx_sig rw 1 ; Signature
c_handle rw 1
endif ;not NLSFUNC
end