|
|
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
|