Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2121 lines
74 KiB

PAGE ,132
;
; (C) Copyright Microsoft Corp. 1987-1990
; MS-DOS 5.00 - NLS Support - KEYB Command
;
;
; File Name: KEYBCMD.ASM
; ----------
;
;
; Description:
; ------------
; Contains transient command processing modules for KEYB command.
;
; Procedures contained in this file:
; ----------------------------------
; KEYB_COMMAND: Main routine for command processing.
; PARSE_PARAMETERS: Validate syntax of parameters included
; on command line.
; BUILD_PATH: Find KEYBOARD.SYS file and validate language and/or
; code page.
; INSTALL_INT_VECTORS: Install our INT 9, INT 2F Drivers
; NUMLK_ON: Turn on the NUM LOCK LED
; FIND_FIRST_CP: Determine first code page for given language in the
; Keyboard Definition file.
;
; Include Files Required:
; -----------------------
; KEYBMSG.INC
; KEYBEQU.INC
; KEYBSYS.INC
; KEYBI9C.INC
; KEYBI9.INC
; KEYBI2F.INC
; KEYBSHAR.INC
; KEYBDCL.INC
; KEYBTBBL.INC
; COMMSUBS.INC
; KEYBCPSD.INC
; POSTEQU.SRC
; DSEG.SRC
;
; External Procedure References:
; ------------------------------
; FROM FILE KEYBTBBL.ASM:
; TABLE_BUILD - Create the shared area containing all keyboard tables.
; STATE_BUILD - Build all states within the table area
; FROM FILE KEYBMSG.ASM:
; KEYB_MESSAGES - All messages
;
; Change History:
;
; Modified for DOS 3.40 - Nick Savage , IBM Corporation
; Wilf Russell, IBM Canada Laboratory
; DCR ???? -KEYBAORD SECURITY LOCK - CNS
;
;
; PTM 3906 - KEYB messages do not conform
; to spec. Error message does
; 3/24/88 not pass back the bogus command
; line argument. - CNS
;
; PTMP3955 ;KEYB component to free environment and close handles 0 - 4
;
; 3/24/88
;
; 9/26/89 jwg Moved code from resident module and reduce code size.
;
;;;;;;;;;;;;;
PUBLIC KEYB_COMMAND
;*****************CNS********************
PUBLIC ID_TAB_OFFSET
;*****************CNS********************
PUBLIC CP_TAB_OFFSET
PUBLIC STATE_LOGIC_OFFSET
PUBLIC SYS_CODE_PAGE
PUBLIC KEYBCMD_LANG_ENTRY_PTR
PUBLIC DESIG_CP_BUFFER
PUBLIC DESIG_CP_OFFSET
PUBLIC KEYBSYS_FILE_HANDLE
PUBLIC NUM_DESIG_CP
PUBLIC TB_RETURN_CODE
PUBLIC FILE_BUFFER
PUBLIC FB
;*****************CNS********************
PUBLIC ID_PTR_SIZE
PUBLIC LANG_PTR_SIZE
PUBLIC CP_PTR_SIZE
PUBLIC NUM_ID
PUBLIC NUM_LANG
PUBLIC NUM_CP
PUBLIC SHARED_AREA_PTR
;*****************CNS********************
PUBLIC SD_SOURCE_PTR
PUBLIC TEMP_SHARED_DATA
PUBLIC FOURTH_PARM
PUBLIC ONE_PARMID
PUBLIC FTH_PARMID
PUBLIC ID_FOUND
PUBLIC BAD_ID
PUBLIC ALPHA
EXTRN PARSE_PARAMETERS:NEAR
extrn pswitches:byte
;***CNS
EXTRN SECURE_FL:BYTE
EXTRN CUR_PTR:WORD
EXTRN OLD_PTR:WORD
EXTRN ERR_PART:WORD
;***CNS
.xlist
INCLUDE SYSMSG.INC ; message retriever
.list
MSG_UTILNAME <KEYB> ; identify to message retriever
CODE SEGMENT PUBLIC 'CODE'
.xlist
INCLUDE KEYBEQU.INC
INCLUDE KEYBSYS.INC
INCLUDE KEYBI9.INC
INCLUDE KEYBI9C.INC
INCLUDE KEYBI2F.INC
INCLUDE KEYBSHAR.INC
INCLUDE KEYBDCL.INC
INCLUDE KEYBTBBL.INC
INCLUDE COMMSUBS.INC
INCLUDE KEYBCPSD.INC
.xlist
INCLUDE POSTEQU.INC
INCLUDE DSEG.INC
.list
ASSUME CS:CODE,DS:CODE
;;;;;;;;;;;;;
;
; Module: KEYB_COMMAND
;
; Description:
; Main routine for transient command processing.
;
; Input Registers:
; DS - points to our data segment
;
; Output Registers:
; Upon termination, if an error has occurred in which a keyboard table
; was not loaded, the AL register will contain the a error flag. This
; flag is defined as follows:
; AL:= 1 - Invalid language, code page, or syntax
; 2 - Bad or missing Keyboard Definition File
; 3 - KEYB could not create a table in resident memory
; 4 - An error condition was received when communicating
; with the CON device
; 5 - Code page requested has not been designated
; 6 - The keyboard table for the requested code page cannot
; be found in resident keyboard table.
;
; Logic:
; IF KEYB has NOT been previously loaded THEN
; Set SHARED_AREA_PTR to TEMP_SHARED_AREA
; INSTALLED_KEYB := 0
; Get HW_TYPE (set local variable)
; ELSE
; Set SHARED_AREA_PTR to ES:SHARED_AREA
; Get HW_TYPE (set local variable)
; Set TABLE_OK := 0
; INSTALLED_KEYB := 1
;
; IF CPS-CON has been loaded THEN
; INSTALLED_CON := 1
;
;*********************************** CNS *************************************
; Call PARSE_PARAMETERS := Edit ID or language, code page,
; and path parameters,ID on command line
;*********************************** CNS *************************************
; Check all return codes:
; IF any parameters are invalid THEN
; Display ERROR message
; ELSE
; IF no language parm specified
; AND code page is not invalid
; AND syntax is valid THEN
; Process QUERY:
; IF KEYB is installed THEN
; Get and display active language from SHARED_DATA_AREA
; Get invoked code page from SHARED_DATA_AREA
; Convert to ASCII
; Display ASCII representation of code page, CR/LF
;*********************************** CNS *************************************
; IF ALTERNATE FLAG SET
; Get and display active ID from SHARED_DATA_AREA
; Convert to ASCII
; Display ASCII representation of ID, CR/LF
;*********************************** CNS *************************************
; IF CPS-CON is installed THEN
; Get selected code page info from CON
; Convert to ASCII
; Display ASCII representation of code page, CR/LF
; EXIT without staying resident
;
; ELSE
; Call BUILD_PATH := Determine location of Keyboard definition file
; Open the file
; IF error in opening file THEN
; Display ERROR message and EXIT
; ELSE
; Save handle
; Set address of buffer
; READ header of Keyboard definition file
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; Check signature for correct file
; IF file signature is correct THEN
; READ language table
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; Use table to verify language parm
; Set pointer values
; IF code page was specified
; READ language entry
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; READ Code page table
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; Use table to verify code page parm
; Set pointer values
; IF CPS-CON is not installed THEN
; Set number of code pages = 1
; IF CODE_PAGE_PARM was specified THEN
; Copy CODE_PAGE_PARM into table of code pages to build
; ELSE
; Call FIND_FIRST_CP := Define the system code page (1st in Keyb Def file)
; Copy SYSTEM_CP into table of code pages to build
; ELSE
; Issue INT 2F ; 0AD03H to get table of Designated code pages
; Set number of designated code pages (HWCP + Desig CP)
; Issue INT 2F ; 0AD02H to get invoked code page
; IF CODE_PAGE_PARM was specified THEN
; Check that CODE_PAGE_PARM is in the list of designated code pages
; IF CODE_PAGE_PARM is in the list of designated code pages THEN
; Copy specified CP into table of code pages to build
; IF a CP has been selected AND is inconsistent with specified CP
; Issue WARNING message
; ELSE
; Display ERROR message
; ELSE
; IF a code page has been invoked THEN
; Copy invoked code page into table of code pages to build
; ELSE
; Call FIND_FIRST_CP := Define the system code page (1st in Keyb Def file)
; Copy SYSTEM_CP into table of code pages to build
;
; IF KEYB has not been previously installed THEN
; Call FIND_SYS_TYPE := Determine system type
; Call INSTALL_INT_9 := Install INT 9 handler
; Call FIND_KEYB_TYPE := Determine the keyboard type
;
; Call TABLE_BUILD := Build the TEMP_SHARED_DATA_AREA
;
; IF return codes from TABLE_BUILD are INVALID THEN
; IF KEYB_INSTALLED := 0 THEN
; Call REMOVE_INT_9
; Display corresponding ERROR message
; EXIT without staying resident
; ELSE
; IF any of the designated CPs were invalid in the build THEN
; Issue WARNING message
; Close the Keyboard definition file
; IF KEYB had NOT already been installed THEN
; IF keyboard is a Ferrari_G AND system is not an XT THEN
; Call NUMLK_ON := Turn the NUM LOCK LED on
; IF extended INT 16 support required THEN
; Install extended INT 16 support
; Call INSTALL_INT_9_NET := Let network know about INT 9
; Call INSTALL_INT_2F := Install the INT 2F driver
; Activate language
; Get resident end and copy TEMP_SHARED_DATA_AREA into SHARED_DATA_AREA
; EXIT but stay resident
; ELSE
; IF this was not a query call AND exit code was valid THEN
; Activate language
; Get resident end and copy TEMP_SHARED_DATA_AREA into SHARED_DATA_AREA
; EXIT without staying resident
; END
;
;;;;;;;;;;;;;
INVALID_PARMS EQU 1 ; EXIT return codes
BAD_KEYB_DEF_FILE EQU 2
MEMORY_OVERFLOW EQU 3
CONSOLE_ERROR EQU 4
CP_NOT_DESIGNATED EQU 5
KEYB_TABLE_NOT_LOAD EQU 6
BAD_DOS_VER EQU 7
EXIT_RET_CODE DB 0
;******************** CNS ***********
ID_VALID EQU 0
ID_INVALID EQU 1
NO_ID EQU 2
LANGUAGE_VALID EQU 0
LANGUAGE_INVALID EQU 1 ; Return Codes
NO_LANGUAGE EQU 2 ; from
NO_IDLANG EQU 3
;******************** CNS ***********
CODE_PAGE_VALID EQU 0 ; EDIT_LANGUAGE_CODE
CODE_PAGE_INVALID EQU 1
NO_CODE_PAGE EQU 2
VALID_SYNTAX EQU 0
INVALID_SYNTAX EQU 1
ACT_KEYB EQU 2
ACT_ID EQU 3
ACT_KEYB_CP EQU 4
ACT_CON_CP EQU 5
INV_L EQU 6 ; message numbers...
INV_I EQU 7
INV_CP EQU 8
INV_S EQU 18
INV_FN EQU 9
INV_KEYB_Q EQU 10
INV_CON_Q EQU 11
NOT_DESIG EQU 12
NOT_SUPP EQU 13
NOT_VALID EQU 14
WARNING_1 EQU 15
INV_COMBO EQU 16
MEMORY_OVERF EQU 17
help_1st equ 300
help_last equ 306
CR_LF DB 10,13,'$'
FOURTH_PARM DB 0 ; switch was specified
ONE_PARMID DB 0 ; id given as positional
FTH_PARMID DB 0 ; id given as switch
ID_FOUND DB 0 ; id was good (in k.d. file)
BAD_ID DB 0 ; id was bad (from parse)
ALPHA DB 0 ; first parm a language id
ID_DISPLAYED DB 0 ; Indicating ID already displayed
SUBLIST_NUMBER LABEL BYTE ; sublist for numbers
DB 11 ; size
DB 0
PTR_TO_NUMBER DW ? ; offset ptr
SEG_OF_NUMBER DW ? ; segment
DB 1
DB 10100001B ; flag
DB 4 ; max width (YST)
DB 1 ; min width
DB " " ; filler
SUBLIST_ASCIIZ LABEL BYTE ; sublist for asciiz
DB 11 ; size
DB 0
PTR_TO_ASCIIZ DW ? ; offset ptr
SEG_OF_ASCIIZ DW ? ; segment
DB 1
DB 00010000B ; flag
DB 2 ; max width
DB 2 ; min width
DB " " ; filler
NUMBER_HOLDER DW ? ; used for message retriever
;***CNS
SUBLIST_COMLIN LABEL BYTE ; sublist for asciiz
DB 11 ; size
DB 0
PTR_TO_COMLIN DW ? ; offset ptr
SEG_OF_COMLIN DW ?
DB 0
DB LEFT_ALIGN+CHAR_FIELD_ASCIIZ ; flag
DB 0 ; max width
DB 1 ; min width
DB " " ; filler
STRING_HOLDER DB 64 DUP(0)
;***CNS
FILE_BUFFER DB FILE_BUFFER_SIZE dup (0); Buffer for Keyboard Def file
FB EQU FILE_BUFFER ;m for 32 language entries)
DESIG_CP_BUFFER DW 28 DUP(?) ; (Room for 25 code pages)
DESIG_CP_BUF_LEN DW $-DESIG_CP_BUFFER ; Length of code page buffer
NUM_DESIG_CP DW 0
CP_TAB_OFFSET DD ?
;****************** CNS ******************
TOTAL_SIZE DW 0
PASS_LANG DW 0
ID_TAB_OFFSET DD ?
;****************** CNS ******************
STATE_LOGIC_OFFSET DD -1
KEYBSYS_FILE_HANDLE DW ?
TB_RETURN_CODE DW 1
DESIG_CP_OFFSET DW OFFSET DESIG_CP_BUFFER
SYS_CODE_PAGE DW 0
DESIG_LIST DW 0
QUERY_CALL DB 0
KB_MASK EQU 02h
SIGNATURE DB 0FFh,'KEYB '
SIGNATURE_LENGTH DW 8
;****************** CNS ***************************
NUM_ID DW 0
ERR4ID DB 0
NUM_LANG DW 0
NUM_CP DW 0
ID_PTR_SIZE DW SIZE KEYBSYS_ID_PTRS
;****************** CNS ***************************
LANG_PTR_SIZE DW SIZE KEYBSYS_LANG_PTRS
CP_PTR_SIZE DW SIZE KEYBSYS_CP_PTRS
KEYBCMD_LANG_ENTRY_PTR DD ?
KEYB_INSTALLED DW 0
CON_INSTALLED DW 0
SHARED_AREA_PTR DD 0
GOOD_MATCH DW 0
;****************** CNS ***************************;
LANGUAGE_ASCII DB '??',0
CMD_PARM_LIST PARM_LIST <>
;---------- TABLES FOR EXTENDED KEYBOARD SUPPORT CTRL CASE ---------
RPL_K8 LABEL BYTE ;-------- CHARACTERS ---------
DB 27,-1,00,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5
DB 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, -
DB -1,127,148,17,23,5 ; =, Bksp, Tab, Q, W, E
DB 18,20,25,21,09,15 ; R, T, Y, U, I, O
DB 16,27,29,10,-1,01 ; P, [, ], Enter, Ctrl, A
DB 19,04,06,07,08,10 ; S, D, F, G, H, J
DB 11,12,-1,-1,-1,-1 ; K, L, ;, ', `, LShift
DB 28,26,24,03,22,02 ; \, Z, X, C, V, B
DB 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift
DB 150,-1,' ',-1 ; *, Alt, Space, CL
;--------- FUNCTIONS ---------
DB 94,95,96,97,98,99 ; F1 - F6
DB 100,101,102,103,-1,-1 ; F7 - F10, NL, SL
DB 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5
DB 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
DB 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12
L_CTRL_TAB EQU $-RPL_K8
;;;;;;;;;;;;;;;;
; Program Code
;;;;;;;;;;;;;;;;
KEYB_COMMAND PROC NEAR
CALL SYSLOADMSG ;load messages
JNC VERSION_OK ;if no carry then version ok
CALL SYSDISPMSG ;error..display version error
MOV AL,BAD_DOS_VER ;bad DOS version
MOV EXIT_RET_CODE,AL
JMP KEYB_EXIT_NOT_RESIDENT ;exit..non resident
VERSION_OK:
MOV SEG_OF_NUMBER,CS ;initialize..
MOV SEG_OF_ASCIIZ,CS ; ..sublists
MOV BP,OFFSET CMD_PARM_LIST ;pointer for parm list
MOV WORD PTR SHARED_AREA_PTR,ES ; ES segment
KEYB_INSTALL_CHECK:
MOV AX,0AD80H ; KEYB install check
INT 2FH
CMP AL,-1 ; If flag is not 0FFh THEN
JE INSTALLED_KEYB
MOV WORD PTR SHARED_AREA_PTR+2,OFFSET TSD
JMP short CON_INSTALL_CHECK
INSTALLED_KEYB:
MOV KEYB_INSTALLED,1 ; Set KEYB_INSTALLED flag = YES
MOV WORD PTR SHARED_AREA_PTR,ES ; Save segment of SHARED_DATA_AREA
MOV WORD PTR SHARED_AREA_PTR+2,DI ;Save offset of SHARED_DATA_AREA
MOV AX,ES:[DI].KEYB_TYPE
MOV HW_TYPE,AX
MOV ES:[DI].TABLE_OK,0 ; Do not allow processing
PUSH CS ; while building table
POP ES ; Reset ES until required
CON_INSTALL_CHECK:
MOV AX,0AD00H ; CONSOLE install check
INT 2FH
CMP AL,-1 ; If flag is not 0FFh THEN
jnz call_first_stage
MOV CON_INSTALLED,1 ; Set CON_INSTALLED flag = YES
CALL_FIRST_STAGE:
PUSH CS
POP ES
CALL PARSE_PARAMETERS ; Validate parameter list
test pswitches,1 ; /? option?
jz no_help ; brif not
mov ax,help_1st ; first help msg
help_loop:
push ax
MOV BX,STDOUT ; to standard out
xor cx,cx ; no replacements
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_ASCIIZ ; ptr to sublist
CALL SYSDISPMSG
pop ax
inc ax
cmp ax,help_last
jbe help_loop
mov exit_ret_code,invalid_parms ; return "invalid parms"
jmp KEYB_EXIT_NOT_RESIDENT
no_help:
BEGIN_PARM_CHECK: ; CHECK ALL RETURN CODES
MOV DL,[BP].RET_CODE_3
CMP DL,1 ; Check for invalid syntax
JNE VALID1
JMP ERROR3
VALID1:
MOV DL,[BP].RET_CODE_1 ; Check for invalid language parm
CMP DL,1
JNE VALID2
JMP ERROR1
VALID2:
MOV DL,[BP].RET_CODE_2 ; Check for invalid code page parm
CMP DL,1
JNE VALID3
JMP ERROR2
VALID3:
MOV DL,[BP].RET_CODE_1 ; Check for query command
CMP DL,2
JE QUERY
;******************************* CNS **
CMP DL,3 ; Get a status of the codepage
JE QUERY ; language, and possible ID code
;******************************* CNS **
JMP NOT_QUERY
; IF QUERY is requested THEN
QUERY:
MOV QUERY_CALL,DL
MOV AX,KEYB_INSTALLED ; If KEYB is installed THEN
or ax,ax
JE QUERY_CONTINUE1
MOV DI,WORD PTR SHARED_AREA_PTR+2 ; Get offset of
MOV ES,WORD PTR SHARED_AREA_PTR ; shared area
MOV BX,WORD PTR ES:[DI].ACTIVE_LANGUAGE ; Get active language
or bx,bx ; if no language...
JE I_MESSAGE ; then id was specified
L_MESSAGE:
MOV WORD PTR LANGUAGE_ASCII,BX ; Display Language
LEA SI,LANGUAGE_ASCII ; sublist points to...
MOV PTR_TO_ASCIIZ,SI ; language code asciiz string
MOV AX,ACT_KEYB ; display 'Current keyboard code'
MOV BX,STDOUT ; to standard out
MOV CX,1 ; one replacement
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_ASCIIZ ; ptr to sublist
CALL SYSDISPMSG
JMP short KEYB_L_FINISHED
I_MESSAGE:
MOV BX,WORD PTR ES:[DI].INVOKED_KBD_ID ; get id code.
MOV NUMBER_HOLDER,BX ; transfer number to temp loc.
LEA SI,NUMBER_HOLDER ; sublist points to...
MOV PTR_TO_NUMBER,SI ; code page word
MOV AX,ACT_ID ; display 'Current ID: '
MOV BX,STDOUT ; to standard out
MOV CX,1 ; one replacement
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_NUMBER ; ptr to sublist
CALL SYSDISPMSG
MOV ID_DISPLAYED,1 ; ID was displayed.
JMP short KEYB_L_FINISHED
QUERY_CONTINUE1:
MOV AX,INV_KEYB_Q
MOV BX,STDOUT ; Else
XOR CX,CX ; Display message that KEYB
MOV DH,UTILITY_MSG_CLASS ; has not been installed
XOR DL,DL
CALL SYSDISPMSG
JMP short KEYB_CP_FINISHED
KEYB_L_FINISHED:
MOV BX,ES:[DI].INVOKED_CP_TABLE ; Get invoked code page
MOV NUMBER_HOLDER,BX ; transfer number to temp loc.
LEA SI,NUMBER_HOLDER ; sublist points to...
MOV PTR_TO_NUMBER,SI ; code page word
MOV AX,ACT_KEYB_CP ; display ' code page: '
MOV BX,STDOUT ; to standard out
MOV CX,1 ; one replacement
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_NUMBER ; ptr to sublist
CALL SYSDISPMSG
CMP ID_DISPLAYED,1 ; was id displayed?
JE KEYB_CP_FINISHED ; yes..continue.
MOV BX,WORD PTR ES:[DI].INVOKED_KBD_ID ; get id code.
or bx,bx ; no id given
JE KEYB_CP_FINISHED
MOV NUMBER_HOLDER,BX ; transfer number to temp loc.
LEA SI,NUMBER_HOLDER ; sublist points to...
MOV PTR_TO_NUMBER,SI ; code page word
MOV AX,ACT_ID ; display 'Current ID: '
MOV BX,STDOUT ; to standard out
MOV CX,1 ; one replacement
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_NUMBER ; ptr to sublist
CALL SYSDISPMSG
MOV AH,09H ; need a CR_LF here.
MOV DX,OFFSET CR_LF
INT 21H
KEYB_CP_FINISHED:
MOV AX,CON_INSTALLED ; If CON has been installed THEN
or ax,ax
JNE GET_ACTIVE_CP
JMP short CON_NOT_INSTALLED
GET_ACTIVE_CP:
MOV AX,0AD02H ; Get active code page
INT 2FH ; information from the console
JNC DISPLAY_ACTIVE_CP
JMP ERROR5
DISPLAY_ACTIVE_CP:
MOV NUMBER_HOLDER,BX ; transfer number to temp loc.
LEA SI,NUMBER_HOLDER ; sublist points to...
MOV PTR_TO_NUMBER,SI ; code page word
MOV AX,ACT_CON_CP ; display 'Current CON code page: '
MOV BX,STDOUT ; to standard out
MOV CX,1 ; one replacement
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_NUMBER ; ptr to sublist
CALL SYSDISPMSG
JMP KEYB_EXIT_NOT_RESIDENT ; Exit from Proc
CON_NOT_INSTALLED: ; ELSE
MOV AX,INV_CON_Q
MOV BX,STDOUT ; Else
XOR CX,CX ; Display message that CON does
MOV DH,UTILITY_MSG_CLASS ; not have active code page
XOR DL,DL
CALL SYSDISPMSG
JMP KEYB_EXIT_NOT_RESIDENT ; Exit from Proc
NOT_QUERY: ; IF not a query function requested
CALL BUILD_PATH ; Determine location of KEYBOARD.SYS
; ...and open file.
JNC VALID4 ; If no error in opening file then
JMP ERROR4
VALID4:
MOV KEYBSYS_FILE_HANDLE,AX ; Save handle
MOV BP,OFFSET CMD_PARM_LIST ; Set base pointer for structures
MOV BX,KEYBSYS_FILE_HANDLE ; Retrieve the file handle
MOV DX,OFFSET FILE_BUFFER ; Set address of buffer
;************************* CNS ********;
cmp [BP].RET_CODE_4,ID_VALID ; CNS is there an ID available
je ID_TYPED ; if so go find out if it is
jmp short GET_LANG ; a 1st or 4th parm, if not must
; must be a language
ID_TYPED:
call SCAN_ID ; scan the table for the ID
cmp ID_FOUND,1 ; if a legal ID check and see if
jne LOST_ID ; it is a first or fourth parm
cmp FTH_PARMID,1 ; if it is a fourth parm go
je GET_ID ; check for language compatibility
jmp short Language_found ; otherwise it must be a first
; parm id value
LOST_ID: ; otherwise must be a bogus match
; between language and ID codes
; or the ID code does not exist
jmp ERR1ID ; in the table
;************************* CNS ***********;
GET_LANG: ; Must be a language/or a 1st parm ID
XOR DI,DI ; Set number
LEA CX,[DI].KH_NUM_LANG+2 ; bytes to read header
MOV AH,3FH ; Read header of the Keyb Def file
INT 21H
JNC VALID5 ; If no error in opening file then
JMP ERROR4
VALID5:
CLD ; all moves/scans forward
MOV CX,SIGNATURE_LENGTH
MOV DI,OFFSET SIGNATURE ; Verify matching
MOV SI,OFFSET FB.KH_SIGNATURE ; signatures
REPE CMPSB
JE LANGUAGE_SPECIFIED
JMP ERROR4
; READ the language table
LANGUAGE_SPECIFIED:
MOV AX,FB.KH_NUM_LANG
MOV NUM_LANG,AX ; Save the number of languages
MUL LANG_PTR_SIZE ; Determine # of bytes to read
MOV DX,OFFSET FILE_BUFFER ; Establish beginning of buffer
MOV CX,AX
CMP CX,SIZE FILE_BUFFER ; Make sure buffer is not to small
JBE READ_LANG_TAB
JMP ERROR4
READ_LANG_TAB:
MOV AH,3FH ; Read language table from
INT 21H ; Keyb Def file
JNC READ_VALID ; If no error in opening file then
JMP ERROR4 ; Else display ERROR message
READ_VALID:
MOV CX,NUM_LANG ; Number of valid codes
MOV DI,OFFSET FILE_BUFFER ; Point to correct word in table
SCAN_LANG_TABLE: ; FOR language parm
MOV AX,[BP].LANGUAGE_PARM ; Get parameter
CMP [DI].KP_LANG_CODE,AX ; Valid Code ??
JE LANGUAGE_FOUND ; If not found AND more entries THEN
ADD DI,LANG_PTR_SIZE ; Check next entry
DEC CX ; Decrement count of entries
JNE SCAN_LANG_TABLE ; Else
JMP ERROR1 ; Display error message
;**************************** CNS ****
GET_ID: ; CNS - Must be an ID value
mov cx,1 ; initialize ctr value for # of ids
SEARCH_ID: ; minimum per country
; ; There is atleast 1 ID for each country
or cx,cx ; check for any more IDs left to check
jne FINDID ; Country has more than one ID check
jmp END_IDCHK ; Country & ID has been found or value
; is zero
FINDID:
push di ; save the current language entry ptr
push cx ; save the minimum # of ids before
; reading the table data from the disk
;**************************** CNS ***********
LANGUAGE_FOUND:
MOV CX,WORD PTR [DI].KP_ENTRY_PTR+2 ; Get offset of lang entry
MOV DX,WORD PTR [DI].KP_ENTRY_PTR ; in the Keyb Def file
MOV WORD PTR KEYBCMD_LANG_ENTRY_PTR,DX ; Save
MOV WORD PTR KEYBCMD_LANG_ENTRY_PTR+2,CX ; offset
MOV AH,42H ; Move file pointer to
MOV AL,0 ; location of language
INT 21H ; entry
JNC LSEEK_VALID
JMP ERROR4
LSEEK_VALID:
MOV DI,AX
MOV CX,SIZE KEYBSYS_LANG_ENTRY-1 ; Set number
; bytes to read header
MOV DX,OFFSET FILE_BUFFER
MOV AH,3FH ; Read language entry in
INT 21H ; Keyb Def file
JNC VALID6a ; If no error in file then
JMP ERROR4
;**************************** CNS **********************************************
valid6a:
cmp FOURTH_PARM,1 ; Is the ID a 4th Parm
jne VALID6 ; if not get out of routine, otherwise
pop cx ; restore # of ids for the country
; Check to see if this is the first
; time checking the primary ID
cmp cx,1 ; if there is just one ID check to make
jne CHK4PARM ; sure both flags are not set
; this should not be necessary w/ new parser
cmp FTH_PARMID,1 ; is the ID flag for switch set
jne CHK1N4 ; is the flag set only for the 4th
cmp FOURTH_PARM,1 ; if set only for the switch proceed
jne CHK1N4 ; if not must be a positional
mov cl,fb.kl_num_id ; get the number of IDs available from the table
mov FTH_PARMID,0 ; turn switch flag off so the table
; counter will not be reset
;ids available for the
CHK1N4: ;country
cmp ONE_PARMID,1 ; this was to be done if
jne CHK4PARM ; two the positional
cmp FOURTH_PARM,0 ; and switch was specified
jne CHK4PARM ; this should never happen
pop di ; if the parser is intact
jmp error3 ; report error & exit
CHK4PARM: ; check on the first ID
cmp FOURTH_PARM,1 ; ID was a switch
jne ABORT_LOOP ; otherwise get out of routine
call IDLANG_CHK ; check the ID
jmp short ADVANCE_PTR ; advance to the next position
ABORT_LOOP:
xor cx,cx ; end loop
ADVANCE_PTR:
pop di ;restore entry value
dec cx ; # of ids left to check
je NO_ADVANCE ; if 0, don't advance table position
cmp GOOD_MATCH,1 ; check to see if ID matched language
je NO_ADVANCE ; if equal do not advance
add di,LANG_PTR_SIZE ; step to the next entry
; in the table
NO_ADVANCE:
jmp SEARCH_ID ; for the country
; ; end of ID check for country
END_IDCHK:
cmp FOURTH_PARM,1 ; see if id was found
jne VALID6
cmp GOOD_MATCH,0 ; none found
jne VALID6 ; report error
mov [bp].ret_code_4,1 ; incompatible lang code
mov al,[bp].ret_code_4 ; id combo
jmp err2id
; otherwise found it
; continue to build tbl
;**************************** CNS **********************************************
VALID6:
MOV AX,WORD PTR FB.KL_LOGIC_PTR ; Save the offset of the state
MOV WORD PTR STATE_LOGIC_OFFSET,AX ; logic section
MOV AX,WORD PTR FB.KL_LOGIC_PTR+2 ; Save the offset of the state
MOV WORD PTR STATE_LOGIC_OFFSET+2,AX ; logic section
MOV DL,[BP].RET_CODE_2 ; IF code page was specified
CMP DL,2
JNE CODE_PAGE_SPECIFIED
JMP short DONE
CODE_PAGE_SPECIFIED: ; Then
;************************** CNS ***************************************
xor ah,ah
MOV Al,FB.KL_NUM_CP
;************************** CNS ***************************************
MOV NUM_CP,AX ; Save the number of code pages
MUL CP_PTR_SIZE ; Determine # of bytes to read
MOV DX,OFFSET FILE_BUFFER ; Establish beginning of buffer
MOV CX,AX
CMP CX,SIZE FILE_BUFFER ; Make sure buffer is not to small
JBE VALID7
JMP ERROR4
VALID7:
MOV AH,3FH ; Read code page table from
INT 21H ; Keyb Def file
JNC VALID8 ; If no error in opening file then
JMP ERROR4
VALID8:
MOV CX,NUM_CP ; Number of valid codes
MOV DI,OFFSET FILE_BUFFER ; Point to correct word in table
SCAN_CP_TABLE: ; FOR code page parm
MOV AX,[BP].CODE_PAGE_PARM ; Get parameter
CMP [DI].KC_CODE_PAGE,AX ; Valid Code ??
JE CODE_PAGE_FOUND ; If not found AND more entries THEN
ADD DI,CP_PTR_SIZE ; Check next entry
DEC CX ; Decrement count of entries
JNE SCAN_CP_TABLE ; Else
;;; if we can not find the CP, simply use the first one available for
;;; the language. This was done for NT because users can not really specified
;;; the code page id via KEYB.COM. By using the first CP, we maintain the
;;; compatibility with dos(keyb gr will succeed even the currnt code page is
;;; invalid for German layout
;;;
ifdef NOT_NTVDM
JMP ERROR2 ; Display error message
else
mov cx, 1
mov NUM_DESIG_CP, cx
mov [si].NUM_DESIGNATES, cx
jmp short SET_TO_SYSTEM_CP
endif
CODE_PAGE_FOUND:
MOV AX,WORD PTR [DI].KC_ENTRY_PTR
MOV WORD PTR CP_TAB_OFFSET,AX
MOV AX,WORD PTR [DI].KC_ENTRY_PTR+2
MOV WORD PTR CP_TAB_OFFSET+2,AX
DONE:
MOV SI,OFFSET DESIG_CP_BUFFER
MOV AX,CON_INSTALLED ; If CON is NOT installed THEN
or ax,ax
JE SYSTEM_CP
JMP short GET_DESIG_CPS
SYSTEM_CP:
MOV CX,1
MOV NUM_DESIG_CP,CX ; Set number of CPs = 1
MOV [SI].NUM_DESIGNATES,CX
MOV DL,[BP].RET_CODE_2 ; Check if code page parm
or dl,dl ; was specified
JNE SET_TO_SYSTEM_CP
MOV DX,[BP].CODE_PAGE_PARM
MOV [SI].DESIG_CP_ENTRY,DX ; Load specified code page into
JMP READY_TO_BUILD_TABLE ; designated code page list
SET_TO_SYSTEM_CP:
CALL FIND_FIRST_CP ; Call routine that sets the first
or ax,ax ; table found in the Keyb Def file
JE SET_TO_SYSTEM_CP2 ; to the system code page
JMP ERROR4
SET_TO_SYSTEM_CP2:
MOV SYS_CODE_PAGE,BX
MOV [BP].CODE_PAGE_PARM,BX
MOV [SI].DESIG_CP_ENTRY,BX ; Move sys CP into desig list
JMP READY_TO_BUILD_TABLE
GET_DESIG_CPS: ; ELSE
MOV AX,0AD03H
PUSH CS ; Make sure ES is set
POP ES
LEA DI,DESIG_CP_BUFFER
MOV CX,DESIG_CP_BUF_LEN
INT 2FH ; Get all designated code pages
JNC SET_DESIG_VARIABLES ; from console
JMP ERROR5
SET_DESIG_VARIABLES:
MOV CX,[SI].NUM_DESIGNATES
ADD CX,[SI].NUM_HW_CPS
MOV NUM_DESIG_CP,CX ; Set number of Designated CPs
BUFFER_CREATED:
MOV AX,0AD02H
INT 2FH ; Get invoked code page
SET_TO_CP_INVOKED:
MOV DL,[BP].RET_CODE_2 ; IF code page parm was specified
or dl,dl
JNE SET_TO_INVOKED_CP
MOV CX,NUM_DESIG_CP
MOV DESIG_LIST,SI
JMP short TEST_IF_DESIGNATED
SET_TO_INVOKED_CP:
CMP AX,1 ; IF a code page has been invoked
JNE SET_TO_INVOKED_CP3
CALL FIND_FIRST_CP ; Call the routine that sets the
or ax,ax ; first code page in the Keyb Def
JE SET_TO_INVOKED_CP2 ; file to the system code page
JMP ERROR4
SET_TO_INVOKED_CP2:
MOV [BP].CODE_PAGE_PARM,BX
MOV SYS_CODE_PAGE,BX
JMP short TEST_IF_DESIGNATED
SET_TO_INVOKED_CP3:
MOV [BP].CODE_PAGE_PARM,BX
TEST_IF_DESIGNATED:
MOV DX,[BP].CODE_PAGE_PARM
CMP [SI].DESIG_CP_ENTRY,DX ; Is Code page specified in the list
JE CODE_PAGE_DESIGNATED ; of designated code pages ?
NEXT_DESIG_CP:
ADD SI,2 ; Check next code page
DEC CX ; If all designated code pages have
JNZ TEST_IF_DESIGNATED ; been checked Then ERROR
JMP ERROR6
CODE_PAGE_DESIGNATED:
CMP SYS_CODE_PAGE,0
JNE READY_TO_BUILD_TABLE
CMP AX,1 ; IF a code page has been invoked
JE READY_TO_BUILD_TABLE
CMP [BP].CODE_PAGE_PARM,BX ; IF Invoked CP <> Specified CP
JE READY_TO_BUILD_TABLE ; Issue warning
;***************************************************************************
PUSH BX
PUSH CX
MOV AX,WARNING_1
MOV BX,STDOUT
XOR CX,CX
MOV DH,UTILITY_MSG_CLASS
XOR DL,DL
CALL SYSDISPMSG
POP CX
POP BX
;***************************************************************************
READY_TO_BUILD_TABLE:
MOV AX,KEYB_INSTALLED
or ax,ax ; Else if KEYB has not been installed
JNE BUILD_THE_TABLE
CALL FIND_SYS_TYPE ; Determine system type for INT 9 use
;------ LOAD IN SPECIAL INT 9 HANDLER AND SPECIAL TABLES
CALL INSTALL_INT_9 ; Install INT 9
CALL FIND_KEYB_TYPE ; Determine keyboard type table use
BUILD_THE_TABLE:
CALL TABLE_BUILD ; Build the TEMP_SHARED_DATA_AREA
CHECK_ERRORS:
; Take appropriate action considering
MOV CX,TB_RETURN_CODE ; return codes from TABLE_BUILD
jcxz CHECK_FOR_INV_CP ; If return code is not 0
MOV AX,KEYB_INSTALLED ; If KEYB has not been installed,
or ax,ax
JNE CHECK_ERROR_CONTINUE
CALL REMOVE_INT_9 ; remove installed vector
CHECK_ERROR_CONTINUE:
CMP CX,1 ; If return code = 1
JNE CHECK_ERROR2
JMP ERROR1 ; display error message
CHECK_ERROR2:
CMP CX,2 ; If return code = 2
JNE CHECK_ERROR3
JMP ERROR2
CHECK_ERROR3:
CMP CX,3 ; If return code = 3
JNE CHECK_ERROR4
JMP ERROR3 ; display error message
CHECK_ERROR4:
CMP CX,4 ; If return code = 4
JNE CHECK_ERROR5A
JMP ERROR4 ; display error message
CHECK_ERROR5A:
CMP CX,5 ; If return code = 5
JNE CHECK_ERROR6A
JMP ERROR5A ; display error message
CHECK_ERROR6A:
JMP ERROR6A ; If return code not 0,1,2,3,4 then
; display error message
CHECK_FOR_INV_CP:
MOV CX,CPN_INVALID ; Check if any CPs were not loaded
jcxz TERMINATE ; If some were invalid, issue
; warning message
;***************************************************************************
PUSH BX
PUSH CX
MOV AX,NOT_SUPP
MOV BX,STDOUT ; WARNING
XOR CX,CX ; MESSAGE
MOV DH,UTILITY_MSG_CLASS
XOR DL,DL
CALL SYSDISPMSG
POP CX
POP BX
;***************************************************************************
TERMINATE:
MOV AH,3EH ; Close the KEYBOARD.SYS file
MOV BX,KEYBSYS_FILE_HANDLE ; if open
or bx,bx
JE KEYB_EXIT
INT 21H
MOV AX,KEYB_INSTALLED
or ax,ax
JE KEYB_EXIT
JMP KEYB_EXIT_NOT_RESIDENT
KEYB_EXIT:
TEST SD.KEYB_TYPE,G_KB ; Q..FERRARI G??
JZ NO_FERRARI_G ; N..LEAVE NUMLK ALONE
TEST SD.SYSTEM_FLAG,PC_XT ; Q..PC/XT?
JNZ NO_FERRARI_G ; Y..LEAVE NUMLK ALONE
TEST SD.KEYB_TYPE,P_KB ; Q..FERRARI P??
JNZ NO_FERRARI_G ; Y..LEAVE NUMLK ALONE
;***CNS
CMP SECURE_FL,1 ; IF SECURITY FLAG SET
JNE NO_FERRARI_G ; DON'T TURN ON NUM_LK
;***CNS
CALL NUMLK_ON ; N..TURN NUMLK ON
NO_FERRARI_G:
TEST SD.SYSTEM_FLAG,EXT_16 ; extended INT 16 support?
JZ SKIP_CTRL_COPY
; Yes, load extened CTRL case table
MOV CX,L_CTRL_TAB ; CX = LENGTH OF EXTENDED TABLE
MOV SI,OFFSET CS:RPL_K8 ; POINT TO EXT. CTRL TABLES
MOV DI,OFFSET CS:K8 ; POINT TO REGULAR CTRL TABLE
CLD
REP MOVSB ; OVERLAY WITH EXT. CTRL TABLE
SKIP_CTRL_COPY:
CALL INSTALL_INT_9_NET ; Let the network know about INT 9
; (if the network is installed)
CALL INSTALL_INT_2F ; Install INT 2F
MOV AX,0AD82H ; Activate language
MOV BL,-1
INT 2FH
MOV AH,31H ; Function call to terminate but stay
XOR AL,AL ; resident
MOV DI,OFFSET SD_DEST_PTR ; Initialize destination ptr
MOV DX,ES:TSD.RESIDENT_END ; Get resident end
CALL COPY_SDA_SETUP ; Set up move common code
JMP COPY_SD_AREA ; Jump to proc that copies area in new
; part of memory
;***************************** CNS **************************************
ERR1ID:
;************************************************************************
MOV AX,INV_I ; invalid ID message
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,INVALID_PARMS
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP KEYB_EXIT_NOT_RESIDENT
ERR2ID:
;***************************************************************************
MOV AX,INV_COMBO ; invalid combination message
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,INVALID_PARMS
MOV EXIT_RET_CODE,AL
;**************************************************************************
JMP KEYB_EXIT_NOT_RESIDENT
;***************************** CNS ****************************************
ERROR1:
;***************************************************************************
MOV AX,INV_L ; invalid language code
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,INVALID_PARMS
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP KEYB_EXIT_NOT_RESIDENT
ERROR2:
;***************************************************************************
MOV AX,INV_CP ; invalid code page message
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,INVALID_PARMS
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP KEYB_EXIT_NOT_RESIDENT
ERROR3:
;***************************************************************************
MOV AX,INV_S ; invalid syntax message
MOV BX,STDOUT ; to standard out
;***CNS
LEA DI,STRING_HOLDER ;Set PTR to look at the STRING
PUSH SI ;Save current SI index
PUSH AX
MOV AX,OLD_PTR ;Last locale of the end of a PARAM
SUB CUR_PTR,AX ;Get the length via the PSP
MOV SI,CUR_PTR
MOV CX,SI ;Save it in CX to move in the chars
POP AX ;Restore the PTR to the command line position
MOV SI,OLD_PTR ;Last locale of the end of a PARAM
REP MOVSB ;Move in the chars until no more
LEA DI,STRING_HOLDER ;Set PTR to look at the STRING
POP SI ;Restore the PTR to the command line position
MOV CX,1 ;One replacement
MOV PTR_TO_COMLIN,DI ; language code asciiz string
PUSH AX
MOV AX,DS ; language code asciiz string
MOV SEG_OF_COMLIN,AX
POP AX
MOV AX,ERR_PART
ifdef BILINGUAL
or ax,ax
jnz ERR03_GO
mov ax,8 ; Value Disallow
ERR03_GO:
endif
LEA SI,SUBLIST_COMLIN
MOV DH,PARSE_ERR_CLASS ; parse error message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,INVALID_PARMS
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP short KEYB_EXIT_NOT_RESIDENT
ERROR4:
;***************************************************************************
MOV AX,INV_FN ; bad or missing file message
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,BAD_KEYB_DEF_FILE
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP short KEYB_EXIT_NOT_RESIDENT
ERROR5:
;***************************************************************************
MOV AX,INV_CON_Q ; CON code page not available.
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,CONSOLE_ERROR
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP short KEYB_EXIT_NOT_RESIDENT
ERROR5A:
;***************************************************************************
MOV AX,MEMORY_OVERF ; not enough resident memory.
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,MEMORY_OVERFLOW
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP short KEYB_EXIT_NOT_RESIDENT
ERROR6:
;***************************************************************************
MOV AX,NOT_DESIG ; code page not prepared.
MOV BX,STDOUT ; to standard out
XOR CX,CX ; no substitutions
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
CALL SYSDISPMSG ; display message
MOV AL,CP_NOT_DESIGNATED
MOV EXIT_RET_CODE,AL
;***************************************************************************
JMP short KEYB_EXIT_NOT_RESIDENT
ERROR6A:
;***************************************************************************
MOV NUMBER_HOLDER,BX ; transfer number to temp loc.
LEA SI,NUMBER_HOLDER ; sublist points to...
MOV PTR_TO_NUMBER,SI ; code page word
MOV AX,NOT_VALID ; display 'Code page requested....'
MOV BX,STDOUT ; to standard out
MOV CX,1 ; one replacement
MOV DH,UTILITY_MSG_CLASS ; utility message
XOR DL,DL ; no input
LEA SI,SUBLIST_NUMBER ; ptr to sublist
CALL SYSDISPMSG
MOV AL,KEYB_TABLE_NOT_LOAD
MOV EXIT_RET_CODE,AL
;***************************************************************************
KEYB_EXIT_NOT_RESIDENT:
MOV AH,04CH
MOV AL,QUERY_CALL ; Check if this was a query call
or al,al
JNE KEYB_EXIT3 ; IF yes then EXIT
MOV AL,EXIT_RET_CODE ; Check if return code was valid
or al,al
JNE KEYB_EXIT3 ; IF not then EXIT
COPY_INTO_SDA:
MOV AX,0AD82H ; Activate language
MOV BL,-1
INT 2FH
MOV AH,04CH
MOV AL,EXIT_RET_CODE
MOV DI,WORD PTR SHARED_AREA_PTR+2 ; Initialize destination ptr
MOV ES,WORD PTR SHARED_AREA_PTR
MOV DX,[BP].RESIDENT_END
CALL COPY_SDA_SETUP ; Set up move common code
JMP COPY_SD_AREA ; Jump to proc that copies area in new
KEYB_EXIT3:
MOV AL,EXIT_RET_CODE
MOV DI,WORD PTR SHARED_AREA_PTR+2 ; Initialize destination ptr
MOV ES,WORD PTR SHARED_AREA_PTR
MOV ES:[DI].TABLE_OK,1
INT 21H
KEYB_COMMAND ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Procedure: COPY_SDA_SETUP
;
; Description:
; Common setup logic for exit
;
; Input Registers:
; N/A
;
; Output Registers:
; N/A
;
; Logic:
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
COPY_SDA_SETUP PROC NEAR
push ax ;save existing values
push es
mov ax,cs:[2ch] ;check offset for address containin environ.
or ax,ax
je NO_FREEDOM
mov es,ax
mov ax,4900H ;make the free allocate mem func
int 21h
NO_FREEDOM:
pop es ;restore existing values
push bx
;Terminate and stay resident
mov bx,4 ;1st close file handles
;STDIN,STDOUT,STDERR
closeall:
mov ah,3eh
int 21h
dec bx
jnz closeall
pop bx
pop ax
MOV CL,4 ; Convert into paragrahs
SHR DX,CL
INC DX
MOV SI,OFFSET SD_SOURCE_PTR ; Initialize source ptr
XOR BP,BP
LEA BX,[BP].ACTIVE_LANGUAGE
ADD DI,BX ; Adjust for portion not copied
ADD SI,BX ; Adjust for portion not copied
MOV CX,SD_LENGTH ; Set length of SHARED_DATA_AREA
SUB CX,BX ; Adjust for portion not copied
RET
COPY_SDA_SETUP ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Procedure: NUMLK_ON
;
; Description:
; Turn Num Lock On.
;
; Input Registers:
; N/A
;
; Output Registers:
; N/A
;
; Logic:
; Set Num Lock bit in BIOS KB_FLAG
; Issue Int 16 to update lights
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NUMLK_ON PROC
PUSH ES
PUSH AX
MOV AX,DATA
MOV ES,AX
OR ES:KB_FLAG,NUM_STATE ; Num Lock state active
MOV AH,1 ; Issue keyboard query call to
INT 16H ; have BIOS update the lights
POP AX
POP ES
RET
NUMLK_ON ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Module: INSTALL_INT_9
;
; Description:
; Install our INT 9 driver.
;
; Input Registers:
; DS - points to our data segment
; BP - points to ES to find SHARED_DATA_AREA
;
; Output Registers:
; DS - points to our data segment
; AX, BX, DX, ES Trashed
;
; Logic:
; Get existing vector
; Install our vector
; Return
;
INSTALL_INT_9 PROC
PUSH ES
MOV AH,35H ; Get int 9 vector
MOV AL,9
INT 21H ; Vector in ES:BX
PUSH ES ; Save segment ES:
PUSH CS
POP ES
MOV WORD PTR ES:SD.OLD_INT_9,BX ; Offset
POP AX ; Recover ES: segment
MOV WORD PTR ES:SD.OLD_INT_9+2,AX ; Segment
MOV AH,25H
MOV AL,9
MOV DX,OFFSET KEYB_INT_9 ; Let DOS know about our handler
INT 21H
POP ES
RET
INSTALL_INT_9 ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Module: INSTALL_INT_9_NET
;
; Description:
;
;
; Input Registers:
; DS - points to our data segment
; BP - points to ES to find SHARED_DATA_AREA
;
; Output Registers:
; DS - points to our data segment
; AX, BX, DX, ES Trashed
;
; Logic:
; IF network is installed THEN
; Let it know about our INT 9
; Return
;
INSTALL_INT_9_NET PROC
PUSH ES
TEST SD.SYSTEM_FLAG,PC_NET ; TEST FOR PC_NETWORK
; IF NOT THE NETWORK INSTALLED
JZ INSTALL_9_DONE_NET ; SKIP THE PC NETWORK HANDSHAKE
; ES:BX TO CONTAIN INT 9 ADDR
MOV BX,OFFSET KEYB_INT_9
MOV AX,0B808H ; FUNCTION FOR PC NETWORK TO INSTALL
; THIS ADDRESS FOR THEIR JUMP TABLE
INT 2FH ; TELL PC_NET TO USE MY ADDR TO CHAIN TO
INSTALL_9_DONE_NET:
POP ES
RET
INSTALL_INT_9_NET ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Module: INSTALL_INT_2F
;
; Description:
; Install our INT 2F drivers.
;
; Input Registers:
; DS - points to our data segment
; BP - points to ES to find SHARED_DATA_AREA
;
; Output Registers:
; DS - points to our data segment
; AX, BX, DX, ES Trashed
;
; Logic:
; Get existing vectors
; Install our vectors
; Return
;
;
INSTALL_INT_2F PROC
MOV AH,35H ; Get int 2f vector
MOV AL,2FH
INT 21H ; Vector in ES:BX
PUSH ES ; Save segment ES:
PUSH CS
POP ES
MOV WORD PTR ES:SD.OLD_INT_2F,BX ; Offset
POP AX ; Recover ES: segment
MOV WORD PTR ES:SD.OLD_INT_2F+2,AX ; Segment
MOV AH,25H ; Set int 9 vector
MOV AL,2FH
MOV DX,OFFSET KEYB_INT_2F ; Vector in DS:DX
INT 21H
RET
INSTALL_INT_2F ENDP
;
;
; Module: REMOVE_INT_9
;
; Description:
; Remove our INT 9 driver.
;
; Input Registers:
; DS - points to our data segment
; BP - points to ES to find SHARED_DATA_AREA
;
; Output Registers:
; DS - points to our data segment
; AX, BX, DX, ES Trashed
;
; Logic:
; Get old vector
; Install old vector
; Return
;
REMOVE_INT_9 PROC
PUSH DS
PUSH ES
MOV ES,WORD PTR SHARED_AREA_PTR
MOV AX,WORD PTR ES:SD.OLD_INT_9+2 ; int 9 vector - segment
MOV DS,AX
MOV DX,WORD PTR ES:SD.OLD_INT_9 ; int 9 vector - offset
MOV AH,25H ; Set int 9 vector
MOV AL,9
INT 21H
REMOVE_9_DONE:
POP ES
POP DS
RET
REMOVE_INT_9 ENDP
IDLANG_CHK PROC NEAR
mov ax,fb.kl_id_code ;get the id code from the table
cmp ax,[bp].id_parm ;compare it to value taken
jne end_match ;from the switch-- if found
cmp ALPHA,0 ;a keyboard code was specified
je a_match ;no lang & a match
mov ax,fb.kl_lang_code ;compare lang codes
cmp ax,[BP].LANGUAGE_PARM ;they are equal
je a_match
jmp short end_match ;if not found go check next
;id for the same country
a_match:
mov good_match,1 ;report the ids match
end_match:
ret
IDLANG_CHK ENDP
;*********************** CNS *******************;
;**********************************SCAN_ID***********************;
; New variables defined - NUM_ID,ADRSS_LANG,ID_PTR_SIZE,ID_FOUND
;****************************************************************;
SCAN_ID PROC NEAR
xor di,di ;clear di to set at the
;beginning of KEYBSYS STRUCTURE
lea cx,[di].kh_num_ID+4 ; set number of bytes to read header
mov ah,3fh
int 21h
jnc VAL5ID
jmp short BAD_TAB ;bad table message
VAL5ID:
mov cx,SIGNATURE_LENGTH
mov di,offset SIGNATURE
mov si,offset FB.KH_SIGNATURE
repe CMPSB
je ID_SPECIFIED
jmp short BAD_TAB
ID_SPECIFIED:
mov ax,FB.KH_NUM_ID
mov NUM_ID,ax ; save # of IDs
mul ID_PTR_SIZE ; determine # of bytes to read
push ax ; save current # of bytes to read for
; ID values only
mov ax,FB.KH_NUM_LANG ; add on lang data in table
mul LANG_PTR_SIZE ; data that comes before the ID data
mov cx,ax ; save that value for the size compare
mov PASS_LANG,cx
pop ax ; restore the info for # of ID bytes to read
add cx,ax ; add that value to get total in CX
mov TOTAL_SIZE,cx ; save the total size
cmp cx,size FILE_BUFFER
jbe READ_ID_TAB
jmp short BAD_TAB
READ_ID_TAB:
mov dx,offset FILE_BUFFER
mov ah,3fh ;read language table from
int 21h ;keyb defn file
jnc READ_IDVAL
jmp short BAD_TAB
READ_IDVAL:
mov cx,NUM_ID
mov di,offset FILE_BUFFER
add di,PASS_LANG
SCAN_ID_TAB:
mov ax,[bp].ID_PARM
cmp [di].KP_ID_CODE,ax
je ID_HERE
add di,ID_PTR_SIZE
dec cx
jne SCAN_ID_TAB
jmp short FINALE
BAD_TAB:
mov ERR4ID,1
jmp short FINALE
ID_HERE:
mov ID_FOUND,1 ;reset ptr for
;current country
FINALE:
ret
SCAN_ID ENDP
;*******************************SCAN_ID END******;
;
; Module: BUILD_PATH
;
; Description:
; Build the complete filename of the Keyboard Definition File
;*************************************WGR*********************
; and open the file.
;+++++++++++++++++++++++++++++++++++++WGR+++++++++++++++++++++
;
; Input Registers:
; DS - points to our data segment
; ES - points to our data segment
; BP - offset of parmeter list
;
; Output Registers:
;************************************WGR**********************
; CARRY CLEAR
; AX = HANDLE
; CARRY SET (ERROR)
; NONE
;++++++++++++++++++++++++++++++++++++WGR++++++++++++++++++++++
; The complete filename will be available in FILE_NAME
;
; Logic:
;
; Determine whether path parameter was specified
; IF length is zero THEN
;****************************************WGR******************
; Try to open file in ACTIVE directory
; IF failed THEN
; Try to open file in ARGV(0) directory
; IF failed THEN
; Try to open file in ROOT directory (for DOS 3.3 compatibility)
; ENDIF
; ENDIF
; ENDIF
; ELSE
; Copy path from PSP to FILE_NAME memory area
; Try to open USER SPECIFIED file
;++++++++++++++++++++++++++++++++++++++++WGR++++++++++++++++++
;
;
KEYBOARD_SYS DB '\KEYBOARD.SYS',00
KEYB_SYS_ACTIVE DB 'KEYBOARD.SYS',00
KEYB_SYS_LENG EQU 14
KEYB_SYS_A_LENG EQU 13
ifdef JAPAN
PUBLIC FILE_NAME
endif ; JAPAN
FILE_NAME DB 128 DUP(0)
ifdef JAPAN
PUBLIC keyb_table
keyb_table label byte ; keyboard definition file search table
; len driver name sub type
db 9, 'KEYAX.SYS', 1
db 9, 'KEY01.SYS', 2
db 9, 'KEY02.SYS', 3
db 10,'KEYJ31.SYS',4
db 0
endif ; JAPAN
FILE_NOT_FOUND EQU 2
PATH_NOT_FOUND EQU 3
;
; Program Code
;
BUILD_PATH PROC NEAR
CLD
MOV DI,OFFSET FILE_NAME ; Get the offset of the filename
MOV CX,[BP].PATH_LENGTH ; If path is specified then
jcxz APPEND_KEYB_SYS
MOV SI,[BP].PATH_OFFSET ; Get the offset of the path
REPE MOVSB ; Copy each char of the specified
MOV AX,3D00H ; Open the KEYBOARD.SYS file
MOV DX,OFFSET FILE_NAME
INT 21H
RET ; path into the filename location
APPEND_KEYB_SYS:
MOV SI,OFFSET KEYB_SYS_ACTIVE ; copy name for active directory
MOV CX,KEYB_SYS_A_LENG ; to file name variable.
REPE MOVSB
MOV AX,3D00H ; try to open it.
MOV DX,OFFSET FILE_NAME
INT 21H
jnc opened_ok ; brif no error opening
cmp ax,PATH_NOT_FOUND ; was it path?
jz open_err_1
cmp ax,FILE_NOT_FOUND ; or file not found?
jnz open_err_2
open_err_1:
CALL COPY_ARGV0 ; yes....try ARGV(0) directory.
MOV AX,3D00H
MOV DX,OFFSET FILE_NAME
INT 21H
jnc opened_ok ; done if open ok
cmp ax,PATH_NOT_FOUND ; if path or file not found, try root
jz open_err_3
cmp ax,FILE_NOT_FOUND
jnz open_err_2
open_err_3:
MOV SI,OFFSET KEYBOARD_SYS ; try ROOT directory.
MOV DI,OFFSET FILE_NAME
MOV CX,KEYB_SYS_LENG
REPE MOVSB
MOV AX,3D00H
MOV DX,OFFSET FILE_NAME
INT 21H
jmp short opened_ok
open_err_2:
stc ; some other error, set error flag
opened_ok:
RET
BUILD_PATH ENDP
COPY_ARGV0 PROC
PUSH ES
PUSH DI
PUSH SI
PUSH CX
MOV DI,2CH ; Locate environment string
MOV ES,[DI]
XOR SI,SI
carv0_loop:
cmp word ptr es:[si],0 ; find ARGV(0) string
jz carv0_loop_exit
inc si
jmp carv0_loop
carv0_loop_exit:
ADD SI,4
LEA DI,FILE_NAME ; move string to work area
carv0_loop1:
MOV AL,ES:[SI]
MOV [DI],AL
INC SI
INC DI
cmp byte ptr es:[si],0
jnz carv0_loop1
carv0_loop2:
dec di
cmp byte ptr [di],'\' ; scan back to first character after "\"
jz carv0_loop2_exit
cmp byte ptr [di],0
jnz carv0_loop2
carv0_loop2_exit:
INC DI
PUSH CS
POP ES
LEA SI,KEYB_SYS_ACTIVE ; copy in "KEYBOARD.SYS"
MOV CX,KEYB_SYS_A_LENG
REPE MOVSB
POP CX
POP SI
POP DI
POP ES
RET
COPY_ARGV0 ENDP
;
;
; Module: FIND_FIRST_CP
;
; Description:
; Check the keyboard definition file for the first code page
;
; Input Registers:
; DS - points to our data segment
; ES - points to our data segment
; BP - offset of parmeter list
;
; Output Registers:
; NONE
;
; Logic:
; Open the file
; IF error in opening file THEN
; Display ERROR message and EXIT
; ELSE
; Save handle
; Set address of buffer
; READ header of Keyboard definition file
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; Check signature for correct file
; IF file signature is correct THEN
; READ language table
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; Use table to verify language parm
; Set pointer values
; IF code page was specified
; READ language entry
; IF error in reading file THEN
; Display ERROR message and EXIT
; ELSE
; READ first code page
; IF error in reading file THEN
; Display ERROR message and EXIT
; RET
;
;
FIND_FIRST_CP PROC NEAR
PUSH CX ; Save everything that
PUSH DX ; that will be changed
PUSH SI
PUSH DI
MOV BX,KEYBSYS_FILE_HANDLE ; Get handle
MOV DX,WORD PTR KEYBCMD_LANG_ENTRY_PTR ; LSEEK file pointer
MOV CX,WORD PTR KEYBCMD_LANG_ENTRY_PTR+2 ; to top of language entry
MOV AH,42H
MOV AL,0 ; If no problem with
INT 21H ; Keyb Def file Then
JNC FIND_FIRST_BEGIN
JMP short FIND_FIRST_CP_ERROR4
FIND_FIRST_BEGIN:
MOV DI,AX
MOV CX,SIZE KEYBSYS_LANG_ENTRY-1 ; Set number
; bytes to read header
MOV DX,OFFSET FILE_BUFFER
MOV AH,3FH ; Read language entry in
INT 21H ; keyboard definition file
JNC FIND_FIRST_VALID4 ; If no error in opening file then
JMP short FIND_FIRST_CP_ERROR4
FIND_FIRST_VALID4:
;************************** CNS *******;
xor ah,ah
MOV Al,FB.KL_NUM_CP
;************************** CNS *******;
MUL CP_PTR_SIZE ; Determine # of bytes to read
MOV DX,OFFSET FILE_BUFFER ; Establish beginning of buffer
MOV CX,AX
CMP CX,SIZE FILE_BUFFER ; Make sure buffer is not to small
JBE FIND_FIRST_VALID5
JMP short FIND_FIRST_CP_ERROR4
FIND_FIRST_VALID5:
MOV AH,3FH ; Read code page table from
INT 21H ; keyboard definition file
JNC FIND_FIRST_VALID6 ; If no error in opening file then
JMP short FIND_FIRST_CP_ERROR4
FIND_FIRST_VALID6:
MOV CX,NUM_CP ; Number of valid codes
MOV DI,OFFSET FILE_BUFFER ; Point to correct word in table
MOV BX,[DI].KC_CODE_PAGE ; Get parameter
XOR AX,AX
JMP short FIND_FIRST_RETURN
FIND_FIRST_CP_ERROR4:
MOV AX,4
FIND_FIRST_RETURN:
POP DI
POP SI
POP DX
POP CX
RET
FIND_FIRST_CP ENDP
.xlist
MSG_SERVICES <MSGDATA>
MSG_SERVICES <LOADmsg,DISPLAYmsg,CHARmsg,NUMmsg>
MSG_SERVICES <KEYB.CL1>
MSG_SERVICES <KEYB.CL2>
MSG_SERVICES <KEYB.CLA>
.list
;
; Temp Shared Data Area
; Contains data which is required by
; both the resident and transient KEYB code.
; All keyboard tables are stored in this area
; Structures for this area are in file KEYBSHAR.INC
;
db 'TEMP SHARED DATA'
SD_SOURCE_PTR LABEL BYTE
TEMP_SHARED_DATA SHARED_DATA_STR <>
CODE ENDS
END